皮皮网

【顾比atr源码】【驱动保护例子源码】【720think 源码】stdlist源码

来源:python sort源码 时间:2024-12-28 23:34:19

1.八数码C++源代码
2.数据结构编程求救
3.STL容器—list使用技巧
4.x,y 都是int, x++=y++ 为什么错?
5.如何使用MDK5.0建立STM32F103工程

stdlist源码

八数码C++源代码

       #include<cstdio>

       #include<vector>

       #include<queue>

       #include<ctime>

       #define maxhash

       #define hash(x) x%maxhash

       using namespace std;

       typedef unsigned long long ULL;

       vector<ULL>list[maxhash];

       vector<int>dist[maxhash];

       inline int abs(int x)

       {

       return x<0?-x:x;

       }

       int hval[][];

       void fill_hval(int *d)

       {

       for(int i=0;i<=8;i++)//number i

       {

       int pos;

       for(int k=1;k<=9;k++)//i's position

       if(d[k]==i)

       {

       pos=k;

       break;

       }

       for(int j=1;j<=9;j++)

       {

       hval[i][j]=abs((j-1)/3-(pos-1)/3)+abs((j-1)%3-(pos-1)%3);

       }

       }

       }

       int h(ULL d)

       {

       int answer=0;

       for(int i=9;i>=1;i--)

       {

       int x=d%;

       d/=;

       answer+=hval[x][i];

       }

       return answer;

       }

       int ToARR(ULL s,int *d)

       {

       int z=0;

       for(int i=9;i>=1;i--)

       {

       d[i]=s%;

       if(d[i]==0) z=i;

       s/=;

       }

       return z;

       }

       ULL ToULL(int *d)

       {

       ULL ans=0;

       for(int i=1;i<=9;i++)

       ans=ans*+d[i];

       return ans;

       }

       void insert(ULL x,int di)

       {

       ULL hx=hash(x);

       list[hx].push_back(x);

       dist[hx].push_back(di);

       }

       int find(ULL x)

       {

       ULL hx=hash(x);

       int size=list[hx].size();

       for(int i=0;i<size;i++)

       if(x==list[hx][i]) return dist[hx][i];

       return -1;

       }

       inline void swap(int &x,int &y)

       {

       int t=x;

       x=y;

       y=t;

       }

       struct state{

       int step;

       ULL x;

       friend bool operator <(state a,state b)

       {

       return a.step>b.step;

       }

       };

       int cnt=0;

       void AStar(int *from,int *to)

       {

       priority_queue<state>q;

       ULL x=ToULL(from);

       ULL y=ToULL(to);

       fill_hval(to);

       q.push((state){ h(x),x});

       insert(x,0);

       int d[];

       while(!q.empty())

       {

       cnt++;

       state s=q.top();

       ULL i=s.x; q.pop();

       int step=find(i);

       int z=ToARR(i,d);

       //printf("%lld %d %d\n",i,step,z);

       if(i==y) return;

       if(z-3>0)

       {

       swap(d[z],d[z-3]);

       ULL j=ToULL(d);

       swap(d[z],d[z-3]);

       if(find(j)!=-1) goto out1;

       q.push((state){ step+h(j),j});

       insert(j,step+1);

       }

       out1:

       if(z+3<)

       {

       swap(d[z],d[z+3]);

       ULL j=ToULL(d);

       swap(d[z],d[z+3]);

       if(find(j)!=-1) goto out2;

       q.push((state){ step+h(j),j});

       insert(j,step+1);

       }

       out2:

       if(z%3!=0)

       {

       swap(d[z],d[z+1]);

       ULL j=ToULL(d);

       swap(d[z],d[z+1]);

       if(find(j)!=-1) goto out3;

       q.push((state){ step+h(j),j});

       insert(j,step+1);

       }

       out3:

       if(z%3!=1)

       {

       swap(d[z],d[z-1]);

       ULL j=ToULL(d);

       swap(d[z],d[z-1]);

       if(find(j)!=-1) continue;

       q.push((state){ step+h(j),j});

       insert(j,step+1);

       }

       }

       }

       int from[],to[];

       void work()

       {

       for(int i=1;i<=9;i++)

       scanf("%d",&from[i]);

       for(int i=1;i<=9;i++)

       scanf("%d",&to[i]);

       AStar(from,to);

       ULL y=ToULL(to);

       printf("%d ",find(y));

       #ifdef DEBUG

       printf("%d ",clock());

       printf("%d ",cnt);

       #endif

       }

       int main()

       {

       #ifdef DEBUG

       freopen("debug.in","r",stdin);

       freopen("debug.out","w",stdout);

       #endif

       work();

       return 0;

       }

       这是基于曼哈顿距离的估价函数的Astar

数据结构编程求救

       试验一:

       #include<iostream>

       #include<string>

       using namespace std;

       struct List

       {

        int num;

        List *next;

       };

       List *head=NULL;

       List* CreateList()

       {

        List *pL;

        List *pEnd;

        pL=new List;

        head=pL;

        pEnd=pL;

        cout<<"请输入节点的数目,以 0 结束"<<endl;

        cin>>pL->num;

        while(pL->num!=0)

        {

        pEnd->next=pL;

        pEnd=pL;

        pL=new List;

        cin>>pL->num;

        }

        delete pL;

        pEnd->next=NULL;

        return head;

       }

       void ShowList(List *head)

       {

        cout<<endl;

        cout<<"链表节点如下:"<<endl;

        while(head)

        {

        cout<<head->num<<endl;

        head=head->next;

        }

       }

       void InsertList(List *head,int num)

       {

        List *list =new List;

        List *l;

        while(head)

        {

        l=head;

        head=head->next;

        }

        list->num=num;

        list->next=NULL;

        l->next=list;

       }

       void DeleteList(List *head, int num)

       {

       List *l;

        if(head->num==num)

        {

        l=head;

        head=head->next;

        ::head=head;

        delete l;

        return ;

        }

        List *l1=head;

        while(head)

        {

        if(head->next==NULL){

        cout<<"找不到不要删除的数字."<<endl;

        return ;

        }

        if(head->next->num==num)

        {

        l=head->next;

        head->next=l->next;

        delete l;

        ::head=l1;

        cout<<"操作成功"<<endl;

        return ;

        }

        head=head->next;

        }

        cout<<"找不到不要删除的数字."<<endl;

       }

       int GetListNum(List *head)

       {

        int num=0;

        while(head)

        {

        num++;

        head=head->next;

        }

        return num;

       }

       int main()

       {

        string str;

       begin:

        cout<<"1->增加链表 2->显示链表 3->插入节点 4->删除节点 5->节点数目"<<endl;

        cin>>str;

        if(str[0]=='1')

        {

        CreateList();

        }

        else if(str[0]=='2')

        {

        if(head==NULL)

        {

        cout<<"你的链表现在是空的,请增加链表"<<endl;

        getchar();

        getchar();

        system("cls");

        goto begin;

        }

        ShowList(head);

        }

        else if(str[0]=='3')

        {

        if(head==NULL)

        {

        cout<<"你的链表现在是空的,请增加链表"<<endl;

        getchar();

        getchar();

        system("cls");

        goto begin;

        }

        int num;

        cout<<"请输入要插入的数字:"<<endl;

        cin>>num;

        InsertList(head,num);

        }

        else if(str[0]=='4')

        {

        if(head==NULL)

        {

        cout<<"你的链表现在是空的,请增加链表"<<endl;

        getchar();

        getchar();

        system("cls");

        goto begin;

        }

        int num;

        cout<<"请输入要删除的数字:"<<endl;

        cin>>num;

        DeleteList(head,num);

        }

        else if(str[0]=='5')

        {

        cout<<"节点数是:"<<GetListNum(head)<<endl;

        }

        else

        {

        cout<<"输入错误,请重新输入.";

        }

        if(str[0]!='Q' && str[0]!='q'){

        cout<<endl<<endl;

        getchar();

        getchar();

        system("cls");

        goto begin;

        }

       }

       试验二:

       #include<iostream>

       #include<string>

       using namespace std;

       struct Stack {

        char c;

        Stack *pNext;

       };

       void InitStack(Stack *&s)

       {

        s=NULL;

       }

       char Peek(Stack *s)

       {

        if(s==NULL) {

        cout<<"栈是空的."<<endl;

        return -1;

        }

        return s->c;

       }

       void Push(Stack *&s,Stack *newS)

       {

        newS->pNext=s;

        s=newS;

       }

       char Pop(Stack *&s)

       {

        if(s==NULL)

        {

        cout<<"栈是空的."<<endl;

        return -1;

        }

        Stack *pNext;

        char c;

        if(s)

        {

        pNext=s->pNext;

        c=s->c;

        delete s;

        s=pNext;

        return c;

        }

       }

       int main()

       {

        Stack *s;

        Stack *s1;

        InitStack(s);

        long num;

        int m;

        int k;

        char c;

        cout<<"输入一个数:"<<endl;

        cin>>num;

        cout<<"输入要转换的进制:"<<endl;

        cin>>k;

        while(num!=0)

        {

        m=num%k;

        c=(int('0')+m);

        s1=new Stack;

        s1->c=c;

        Push(s,s1);

        num/=k;

        }

        while(s)

        {

        cout<<Pop(s);

        }

        cout<<endl;

       }

STL容器—list使用技巧

       列表容器(list)在STL中是一种序列容器,特点是非连续内存分配。对比vector,其查找操作通常较慢,但插入和删除操作速度较快。列表通常实现为双向链表,顾比atr源码这为实现单链表提供了便利。通过双向链接,可在常数时间内进行插入和删除操作,但查找操作需遍历整个列表,时间复杂度为O(n)。

       查看上图,可了解std::list在内存中的布局,列表中的元素通过双向链接结点存储,每个结点包含数据和指向前后结点的指针。

       列表的查找操作耗时,一旦找到元素,后续操作如更新、插入或删除则为常数时间复杂度。从性能角度看,list并不总是最佳选择,但在某些场景下仍具有优势。

       以下代码展示了如何使用list进行内存分配测试,结果显示list的内存分配与vector不同,不会在插入元素时进行内存重新分配和数据拷贝。驱动保护例子源码

       清理list内存通常较为复杂。std::list自身并未提供内存释放接口,且标准库不保证立即释放内存。只有vector和string容器支持类似std::vector的swap函数,以在清理内存时立即释放空间。例如,chromium.org源代码中的stl_util.h文件中的清理代码仅适用于vector和string。

       尽管在多数情况下std::list似乎并不突出,它在某些特定场景中仍具有用武之地。例如,当需要频繁插入和删除元素,而访问元素的顺序不固定时,list可能是更优选择。此外,当处理大量数据且内存使用效率是关键因素时,list的特性也能带来优势。因此,在权衡效率和特定需求后,list仍值得在编程实践中考虑。

x,y 都是int, x++=y++ 为什么错?

       赋值运算需要左值,而x++不是左值。x++的本意是使用x的值,在使用后将x自加1,那么如果把x++用在赋值运算的720think 源码左边的话,赋值时是赋给原先的x还是自加后的x呢?显然是未定义的,所以这种操作是错误的。

       下面转一篇关于左值和右值的文章,相信会对你帮助很大的。

       左值(lvalue)和右值(rvalue)是编程中两个非常基本的概念,但是也非常容易让人误解,看了很多文章,自我感觉真正将这个问题讲的很透彻的文章还没有看见,所以自告奋勇来尝试一下。如果左值右值的概念不是非常清楚的话,它们迟早会像拦路虎一样跳出来,让你烦心不已,就像玩电脑游戏的时候每隔一段时间总有那么几个地雷考验你的耐性,如果一次把所有地雷扫尽就好了。:)

       左值(lvalue)和右值(rvalue)最先来源于编译理论(感谢南大小百合的programs)。在C语言中表示位于赋值运算符两侧的两个值,左边的就叫左值,右边的就叫右值。比如:

       int ii = 5;//ii是左值,5是右值

       int jj = ii;//jj是左值,ii是右值

       上面表明,左值肯定可以作为右值使用,但反之则不然。左值和右值的驱动鼠标模拟源码最早区别就在于能否改变。左值是可以变的,右值不能变。注1

       注1:这一点在C++中已经猪羊变色,不再成立。拱猪游戏还是挺好玩的,我还真抓过好几次全红心,不过真的好险。:)

       在很多文章中提到,在C++中,左值更多的指的是可以定位,即有地址的值,而右值没有地址。注2

       注2:这一点仍然不准确,我在程序中生成一个临时右值std::vector(),你能够说它没有地址吗?难道它是没有肉体的鬼魂或幽灵?它是有地址的,而且它也是绝对的右值。

       在现代C++中,现在左值和右值基本上已经失去它们原本所具有的意义,对于左值表达式,通过具体名字和引用(pointer or reference)来指定一个对象。非左值就是右值。我来下一个定义:

       左值表示程序中必须有一个特定的名字引用到这个值。

       右值表示程序中没有一个特定的名字引用到这个值。

       跟它们是物流供求asp源码否可以改变,是否在栈或堆(stack or heap)中有地址毫无关系。

       1.左值

       在下面的代码中:

       int ii = 5;

       int const jj = ii;

       int a[5];

       a[0] = ;

       *(a+3) = ;

       int const& max( int const& a, int const& b ) //call by reference

       {

        return a > b ? a : b;

       }

       int& fun(int& a) //call by reference

       {

        a += 5;

        return a;

       }

       ii,jj,a[0],*(a+3),还有函数max的返回值比如max(ii, jj),注3函数fun的返回值fun(ii)都是左值。,它们都是有特定的引用名字的值。ii,jj,a[0],*(a+3),max(ii, jj),fun(ii)分别就是它们的名字。

       注3:在这里有一个不太容易分清楚的盲点。那就是有人会问max(8, 9)到达是左值还是右值,C++标准规定常量引用(reference to const)可以引用到右值,所以max(8, 9)似乎应该是右值,不过不管它是左值,还是右值,我们都不能试图去改变它。为了与前面的概念一致,我认为它是左值,不可改变的常量左值。

       左值有不能改变的,即被const所修饰的左值,比如上面的jj,max(ii, jj)都是被常量(const)魔咒所困住的左值。

       没有被const困住的左值当然是可以改变的,比如下面的代码都是成立的:

       ii = ;

       a[0] = ;

       fun(ii) = ; //OK!

       我们的眼睛没有问题,fun(ii) = ;完全正确,因为它是可以改变的左值。所以我们看STL的源码,就会理解std::vector中的重载operator[]运算符的返回值为什么要写成引用,因为operator[]必须返回左值。

       2.右值

       没有特定名字的值是右值。先看下面的代码:

       std::list();

       std::string(“It is a rvalue!”);

       int fun1() //call by value

       {

        …

       }

       int* fun2() //call by reference

       {

        …

       }

       其中std::list(),std::string(“It is a rvalue!”),函数fun1的返回值fun1(),函数fun2的返回值fun2()都是右值,它们的值都没有特定的名字去引用。也许有人会奇怪,fun2()也是右值?最前面的max(a,b)不是左值吗?

       请看清楚,函数fun2的返回值是pointer,pointer也是call by value,而函数max的返回值是reference,reference是call by reference。所以说C++中引入reference不仅仅是为了方便,它也是一种必须。注4

       注4:Scott Meyer写的《More Effective C++》的条款1专门讲了pointer和reference的区别,写的很好,辨别的非常清楚。

       fun2()是右值,但 *fun2()却是左值,就跟经常看到的*p一样,所以看C++库代码的时候,会发现重载operator*的函数返回值是reference。

       当然我还遗漏了一种右值,那就是字面上的(literal)值,比如5,8.,’a’等等理所当然的都是右值。

       右值最初出现的时候,一个最大的特征就是不可改变。但就跟我们的道德标准一样,时代不同了,标准也变化了,以前的三纲五常早已经被扔到历史的垃圾堆里面了。

       C++中有可以改变的右值,而且这个特性还非常有用。那就是用户自定义的类(class)的构造函数生成的临时对象。比如:

       std::vector(9),std::deque(),……都是可以改变的右值。在Herb Sutter的《More Exceptional C++》中的条款7的page页有这样几行代码:

       // Example 7-2(b): The right way to shrink-to-fit a vector.

       vector<Customer> c( );

       // ...now c.capacity() >= ...

       // erase all but the first elements

       c.erase( c.begin()+, c.end() );

       // the following line does shrink c's

       // internal buffer to fit (or close)

       vector<Customer>( c ).swap( c );

       // ...now c.capacity() == c.size(), or

       // perhaps a little more than c.size()

       认真看几遍,你会发现但vector的大小增大到一定程度,你又用不着这么多空间的时候,你会想办法把它收缩到最合适的大小,但利用别的办法比如调用成员函数reserve()都无法办到,这个时候就必须利用右值可以改变这个性质了。

       vector<Customer>( c ).swap( c );这行代码就是点睛之处。

       首先使用复制构造函数生成临时右值vector<Customer>( c ),这个右值正好是合适大小,然后和c交换注5,c就变成合适大小了,最后在整个表达式结束的时候,这个临时右值析构归还内存空间。真是绅士一般的优雅!

       注5:这个时候这个临时右值就发生了改变。

       如果还不理解,可以看看书,或者直接看库的源代码。

       至于为什么会这样?我思考了一下,我想是这样的,我们看类(class)的数据布置结构,会发现它的每一个数据成员都是有名字的,我想编译器在编译的过程中,都会生成一个外部不所知的对这个临时对象右值的名字引用,但需要改变这个临时对象的时候,这个名字就用上了。比如:

       class Point

       {

       public: //纯粹为了方便,我把数据成员公开,现实中尽量不要这样用

        int x, y ,z;

        ……//其他各种成员函数

       };

       我们现在就可以改变右值,用到了匿名的引用名字。

       Point().x = 6;//改变了右值

       Point().y = 6;//同意改变了右值,不过注意,这个右值跟上面的不是同一个。

       总结

       左值和右值的真正区别我想就是这些了,左值表示有特定的名字引用,而右值没有特定的名字引用。当然我仍然会有疏忽,希望大家能够提醒我,指正我的不足。

       前两天看Herb Sutter从邮件中寄来的新文章(我订阅他的新文章邮件通知),一篇是讲Tuple数据结构的,没有什么新意,以前好像看过,还有一篇名字是:(Mostly)Private,地址为/documents/s=/cujcexpsutter/ 内容本身并不深,但看完文章,发现随处可见C++的波诡云谲,又会对什么叫袖里乾坤,滴水藏海多一份感性认识。

       在下一篇文章我想从不同于一般的角度,从自己的经历谈谈在校毕业生在IT行业怎样找工作,我想会让所有读者都有一些思考,不仅仅是求职者。题目我已经想好了,就叫《扮虎吃猪》,不过现在我有一些别的事情要忙,所以可能会让大家等几天。

       转载请注明来源,谢谢!

如何使用MDK5.0建立STMF工程

       1.解压stmfx_stdperiph_lib.zip 可以从ST官方网站免费下载。

       2.创建一个Demo文件夹

        2.1 新建子文件夹User,用于存放用户源程序

        2.2 新建子文件夹Project,用户KEIL工程文件

        2.3 在Project下依次创建Obj和List子文件夹,存放编译过程中产生的中间文件。

       3. 复制源代码到Demo文件夹

        3.1 将stmfx_stdperiph_lib\STMFx_StdPeriph_Lib_V3.1.2Libraries文件整体复制到Demo文件夹下。这就是ST的标准库,是以源代码形式提供的。

        3.2 将库中的演示代码IOToggle中的文件复制到Demo\User文件夹.

       4. 新建一个Keil MDK工程

        4.1 启动Keil MDK,点击菜单 New uVision Project,然后按向导进行操作

        4.2 选择CPU类型为 STMFZE (这是安富莱STM开发板采用CPU类型)

        4.3 当提示是否复制启动代码时,请选择否。(我们用最新的库中的启动代码,不用Keil软件自带的旧版本启动文件)

        4.4 根据自己的需要修改Target名字。(名字任意)

        4.5 为了便于代码管理,在这个Project下创建几个Group (名字可以任意)

        User : 存放用户自己写的源代码

        RVMDK : 存放启动文件(汇编文件)

        StdPeriph_Driver : 存放ST标准库文件

        CMSIS : 存放CMSIS接口文件(这也是库的一部分)

        4.6 创建好Group后,我们开始依次添加文件。

       5. 修改源代码。我们将修改main.c 文件,换成我们自己跑马灯程序。

       6. 配置工程, 点击“Options”按钮

        6.1 切换到Output。

        选择Object文件夹。

        在Create Hex File 前打钩。

        6.2 切换带Listing。

        选择Listings文件夹

        6.3 切换到C/C++

        添加两个预编译宏 STMFX_HD, USE_STDPERIPH_DRIVER (这是ST库用到了这两个宏)

        修改Includes路径

        6.4 切换到Debug

        选择硬件调试器(缺省是软件仿真),我们选择Cortex-M3 J-Link调试器

        再 Run to main前打钩

        6.4 切换到Utilities

        选额调试器类型,我们选择Cortex-M3 J-Link

        点settings按钮,添加Flash编程算法,我们选择STM高密度器件,Flash容量K字节

       7. 配置工程完毕。下面开始编译。

       8. 编译OK,开始调试。

       9. 教程结束。