数据结构C语言算法大全.docx
- 文档编号:5371965
- 上传时间:2022-12-15
- 格式:DOCX
- 页数:16
- 大小:150.01KB
数据结构C语言算法大全.docx
《数据结构C语言算法大全.docx》由会员分享,可在线阅读,更多相关《数据结构C语言算法大全.docx(16页珍藏版)》请在冰豆网上搜索。
数据结构C语言算法大全
1)插入操作
在顺序表L的第i(1<=L.length+1)个位置插入新元素e。
如果i的输入不合法,则返回false,表示插入失败;否则,将顺序表的第i个元素以及其后的元素右移一个位置,腾出一个空位置插入新元素e,顺序表长度增加1,插入成功,返回true。
1.boolListInsert(SqList&L,inti,ElemTypee){
2.//本算法实现将元素e插入到顺序表L中第i个位置
3.if(i<1||i>L.length+1)
4.returnfalse;//判断i的范围是否有效
5.if(L.length>=MaxSize)
6.returnfalse;//当前存储空间已满,不能插入
7.for(intj=L.length;j>=i;j--)//将第i个位置及之后的元素后移
8.L.data[j]=L.data[j-l];
9.L.data[i-1]=e;//在位置i处放入e
10.L.length++;//线性表长度加1
11.returntrue;
12.}
2)删除操作
删除顺序表L中第i(1<=i<=L.length)个位置的元素,成功则返回true,否则返回false,并将被删除的元素用引用变量e返回。
复制纯文本新窗口
1.boolListDelete(SqList&L,inti,int&e){
2.//本算法实现删除顺序表L中第i个位置的元素
3.if(i<1||i>L.length)
4.returnfalse;//判断i的范围是否有效
5.e=L.data[i-1];//将被删除的元素赋值给e
6.for(intj=i;j 7.L.data[j-1]=L.data[j]; 8.L.length--;//线性表长度减1 9.returntrue; 10.} 3)按值查找(顺序查找) 在顺序表L中查找第一个元素值等于e的元素,并返回其下标。 1.intLocateElem(SqListL,ElemTypee){ 2.//本算法实现查找顺序表中值为e的元素,如果查找成功,返回元素位序,否则返回0 3.inti; 4.for(i=0;i 5.if(L.data[i]==e) 6.returni+1;//下标为i的元素值等于e,返回其位号i+1 7.return0;//退出循环,说明查找失败 8.} 单链表的定义 1.typedefstructLNode{//定义单链表结点类型 2.ElemTypedata;//数据域 3.structLNode*next;//指针域 4.}LNode,*LinkList; 采用头插法建立单链表 该方法从一个空表开始,生成新结点,并将读取到的数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头,即头结点之后,如图2-4所示。 图2-4 头插法建立单链表 头插法建立单链表的算法如下: 1.LinkListCreatList1(LinkList&L){ 2.//从表尾到表头逆向建立单链表L,每次均在头结点之后插入元素 3.LNode*s;intx; 4.L=(LinkList)malloc(sizeof(LNode));//创建头结点 5.L->next=NULL;//初始为空链表 6.scanf("%d",&x);//输入结点的值 7. 8.while(x! =9999){//输入9999表示结束 9.s=(LNode*)malloc(sizeof(LNode));//创建新结点 10.s->data=x; 11.s->next=L->next;//重点(如果使用头插法的话) 12.L->next=s;//将新结点插入表中,L为头指针 13.scanf("%d",&x); 14.}//while结束 15. 16.returnL; 17.} 采用尾插法建立单链表 头插法建立单链表的算法虽然简单,但生成的链表中结点的次序和输入数据的顺序不一致。 若希望两者次序一致,可采用尾插法。 该方法是将新结点插入到当前链表的表尾上,为此必须增加一个尾指针r,使其始终指向当前链表的尾结点,如图2-5所示。 图2-5 尾插法建立单链表 尾插法建立单链表的算法如下: 1.LinkListCreatList2(LinkList&L){ 2.//从表头到表尾正向建立单链表L,每次均在表尾插入元素 3.intx;//设元素类型为整型 4.L=(LinkList)malloc(sizeof(LNode)); 5.LNode*s,*r=L;//r为表尾指针 6.scanf("%d",&x);//输入结点的值 7. 8.while(x! =9999){//输入9999表示结束 9.s=(LNode*)malloc(sizeof(LNode)); 10.s->data=x;//重点 11.r->next=s; 12.r=s;//r指向新的表尾结点 13.scanf("%d",&x); 14.} 15. 16.r->next=NULL;//尾结点指针置空 17.returnL; 18.} 按序号查找结点值 在单链表中从第一个结点出发,顺指针next域逐个往下搜索,直到找到第i个结点为止,否则返回最后一个结点指针域NULL。 按序号查找结点值的算法如下: 1.LNodeGetElem(LinkListL,inti){ 2.//本算法取出单链表L(带头结点)中第i个位置的结点指针 3.intj=1;//计数,初始为1 4.LNode*p=L->next;//头结点指针赋给p//注意 5. 6.if(i==0) 7.returnL;//若i等于0,则返回头结点 8.if(i<1) 9.returnNULL;//若i无效,则返回NULL 10. 11.while(p&&j 12.p=p->next; 13.j++; 14.} 15. 16.returnp;//返回第i个结点的指针,如果i大于表长,p=NULL,直接返回p即可 17.} 按值查找表结点 从单链表第一个结点开始,由前往后依次比较表中各结点数据域的值,若某结点数据域的值等于给定值e,则返回该结点的指针。 若整个单链表中没有这样的结点,则返回NULL。 按值查找结点的算法如下: 1.LNodeLocateElem(LinkListL,ElemTypee){ //本算法查找单链表L(带头结点)中数据域值等于e的结点指针,否则返回NULL 2.LNode*p=L->next; 3.while(p! =NULL&&p->data! =e)//从第1个结点开始查找data域为e的结点 4.p=p->next; 5. 6.returnp;//找到后返回该结点指针,否则返回NULL 7.} 插入结点操作 插入操作是将值为x的新结点插入到单链表的第i个位置上。 先检查插入位置的合法性,然后找到待插入位置的前驱结点,即第i-1个结点,再在其后插入新结点。 算法首先调用上面的按序号查找算法GetElem(L, i-1),查找第i-1个结点。 假设返回的第i-1个结点为*p,然后令新结,点*s的指针域指向*p的后继结点,再令结点*p的指针域指向新插入的结点*s。 其操作过程如图2-6所示。 图2-6 单链表的插入操作 实现插入结点的代码片段如下: 1.p=GetElem(L,i-1);//语句①,查找插入位置的前驱结点 2.s->next=p->next;//语句②,图2-6中辑作步骤1 3.p->next=s;//语句③,图2-6中操作步骤2 删除结点操作 删除操作是将单链表的第i个结点删除。 先检查删除位置的合法性,然后查找表中第i-1个结点,即被删结点的前驱结点,再将其删除。 其操作过程如图2-7所示。 图2-7 单链表结点的删除 假设结点*p为找到的被删结点的前驱结点,为了实现这一操作后的逻辑关系的变化,仅需修改*p的指针域,即将*p的指针域next指向*q的下一结点。 实现删除结点的代码片段如下: 1.p=GetElem(L,i-1);//查找删除位置的前驱结点 2.q=p->next;//令q指向被删除结点 3.p->next=q->next//将*q结点从链中“断开” 4.free(q);//释放结点的存储空间 和插入算法一样,该算法的主要时间也是耗费在查找操作上,时间复杂度为O(n)。 扩展: 删除结点*p 要实现删除某一个给定结点*p,通常的做法是先从链表的头结点开始顺序找到其前驱结点,然后再执行删除操作即可,算法的时间复杂度为O(n)。 其实,删除结点*p的操作可以用删除*p的后继结点操作来实现,实质就是将其后继结点的值赋予其自身,然后删除后继结点,也能使得时间复杂度为O (1)。 实现上述操作的代码片段如下: 1.q=p->next;//令q向*p的后继结点 2.p->data=p->next->data;//和后继结点交换数据域 3.p->next=q->next;//将*q结点从链中“断开”问题 4.free(q);//释放后继结点的存储空间 双链表 双链表中结点类型的描述如下: 1.typedefstructDNode{//定义双链表结点类型 2.ElemTypedata;//数据域 3.structDNode*prior,*next;//前驱和后继指针 4.}DNode,*DLinklist; 双链表仅仅是在单链表的结点中增加了一个指向其前驱的prior指针,因此,在双链表中执行按值查找和按位查找的操作和单链表相同。 但双链表在插入和删除操作的实现上,和单链表有着较大的不同。 这是因为“链”变化时也需要对prior指针做出修改,其关键在于保证在修改的过程中不断链。 此外,双链表可以很方便地找到其前驱结点,因此,插入、删除结点算法的时间复杂度仅为O (1)。 双链表的插入操作 在双链表中p所指的结点之后插入结点*s,其指针的变化过程如图2-9所示。 插入操作的代码片段如下: 1.s->next=p->next;//语句①,将结点*s插入到结点*p之后 2.p->next->prior=s;//语句② 3.s->prior=p;//语句③ 4.p->next=s;//语句④ 图2-9 双链表插入结点过程 上述代码的语句顺序不是唯一的,但也不是任意的,①②两步必须在④步之前,否则*p的后继结点的指针就丢掉了,导致插入失败。 为了加深理解,读者可以在纸上画出示意图。 若问题改成要求在结点*p之前插入结点*s,请读者思考具体的操作步骤。 双链表的删除操作 删除双链表中结点*p的后继结点*q,其指针的变化过程如图2-10所示。 图2-10 双链表删除结点过程 删除操作的代码片段如下: 1.p->next=q->next;//图2-10中步骤①① 2.q->next->prior=p;//图2-10中步骤② 3.free(q);//释放结点空间 栈的基本操作 各种辅导书中给出的基本操作的名称不尽相同,但所表达的意思大致是一样的。 这里我们以严蔚敏编写的教材为准给出栈的基本操作,希望读者能熟记下面的基本操作: InitStack(&S): 初始化一个空栈S。 StackEmpty(S): 判断一个栈是否为空,若栈S为空返回true,否则返回false。 Push(&S,x): 进栈,若栈S未满,将x加入使之成为新桟顶。 Pop(&S,&x): 出栈,若栈S非空,弹出栈顶元素,并用x返回。 GetTop(S,&x): 读栈顶元素,若栈S非空,用x返回栈顶元素。 ClearStack(&S): 销毁栈,并释放栈S占用的存储空间。 注意: 符号'&'是C++特有的,用来表示引用,有的书上釆用C语言中的指针类型‘*’,也可以达到传址的目的。 在解答算法题时,若题干没有做出限制,可以直接使用这些基本的操作函数。 1.栈的顺序存储结构 //-----栈的顺序存储表示----- #defineSTACK_INIT_SIZE100; #defineSTACKINCREMENT10; typedefstruct{ SElemType*base; SElemType*top; intstacksize; }SqStack; StatusInitStack(SqStack&S) {//构造一个空栈S S.base=(ElemType*)malloc(STACK_INIT_SIZE* sizeof(ElemType)); if(! S.base)exit(OVERFLOW);//存储分配失败 S.top=S.base; S.stacksize=STACK_INIT_SIZE; returnOK; } StatusPush(SqStack&S,SElemTypee){ if(S.top-S.base>=S.stacksize){//栈满,追加存储空间 S.base=(ElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(ElemType)); if(! S.base)exit(OVERFLOW);//存储分配失败 S.top=S.base+S.stacksize; S.stacksize+=STACKINCREMENT; } *S.top++=e; returnOK; } StatusPop(SqStack&S,SElemType&e){ //若栈不空,则删除S的栈顶元素, //用e返回其值,并返回OK; //否则返回ERROR if(S.top==S.base)returnERROR; e=*--S.top; returnOK; } 链队列: typedefstructQNode{//结点类型 QElemTypedata; structQNode*next; }QNode,*QueuePtr; 链队列——链式映象 typedefstruct{//链队列类型 QueuePtrfront;//队头指针 QueuePtrrear;//队尾指针 }LinkQueue; StatusInitQueue(LinkQueue&Q){ //构造一个空队列Q Q.front=Q.rear= (QueuePtr)malloc(sizeof(QNode)); if(! Q.front)exit(OVERFLOW); //存储分配失败 Q.front->next=NULL; returnOK; } StatusEnQueue(LinkQueue&Q, QElemTypee){ //插入元素e为Q的新的队尾元素 p=(QueuePtr)malloc(sizeof(QNode)); if(! p)exit(OVERFLOW);//存储分配失败 p->data=e;p->next=NULL; Q.rear->next=p;Q.rear=p; returnOK; } StatusDeQueue(LinkQueue&Q, QElemType&e){ //若队列不空,则删除Q的队头元素, //用e返回其值,并返回OK;否则返回ERROR if(Q.front==Q.rear)returnERROR; p=Q.front->next;e=p->data; Q.front->next=p->next; if(Q.rear==p)Q.rear=Q.front; free(p);returnOK; } 循环队列: #defineMAXQSIZE100//最大队列长度 typedefstruct{ QElemType*base;//动态分配存储空间 intfront;//头指针,若队列不空, //指向队列头元素 intrear;//尾指针,若队列不空,指向 //队列尾元素的下一个位置 }SqQueue; 循环队列——顺序映象 StatusInitQueue(SqQueue&Q){ //构造一个空队列Q Q.base=(ElemType*)malloc(MAXQSIZE*sizeof(ElemType)); if(! Q.base)exit(OVERFLOW); //存储分配失败 Q.front=Q.rear=0; returnOK; } StatusEnQueue(SqQueue&Q,ElemTypee) {//插入元素e为Q的新的队尾元素 if((Q.rear+1)%MAXQSIZE==Q.front) returnERROR;//队列满 Q.base[Q.rear]=e; Q.rear=(Q.rear+1)%MAXQSIZE; returnOK; } StatusDeQueue(SqQueue&Q,ElemType&e) {//若队列不空,则删除Q的队头元素, //用e返回其值,并返回OK;否则返回ERROR if(Q.front==Q.rear)returnERROR; e=Q.base[Q.front]; Q.front=(Q.front+1)%MAXQSIZE; returnOK; } 经典算法: 1.行编辑 while(ch! =EOF){//EOF为全文结束符 while(ch! =EOF&&ch! ='\n'){ switch(ch){ case'#': Pop(S,c);break; case'@': ClearStack(S);break;//重置S为空栈 default: Push(S,ch);break; } ch=getchar();//从终端接收下一个字符 } 2. 从原表达式求得后缀式的规律为: 1)设立操作数栈; 2)设表达式的结束符为“#”, 予设运算符栈的栈底为“#”; 3)若当前字符是操作数, 则直接发送给后缀式。 4)若当前运算符的优先数高于栈顶 运算符,则进栈; 5)否则,退出栈顶运算符发送给后 缀式; 6)“(”对它之前后的运算符起隔离 作用,“)”可视为自相应左括弧开始 的表达式的结束符。 算法: voidtransform(charsuffix[],charexp[]){ InitStack(S);Push(S,#); p=exp;ch=*p; while(! StackEmpty(S)){ if(! IN(ch,OP))Pass(Suffix,ch); else{} if(ch! =#){p++;ch=*p;} else{Pop(S,ch);Pass(Suffix,ch);} }//while }//CrtExptree …… switch(ch){ case(: Push(S,ch);break; case): Pop(S,c); while(c! =() {Pass(Suffix,c);Pop(S,c)} break; defult: while(Gettop(S,c)&&(precede(c,ch))) {Pass(Suffix,c);Pop(S,c);} if(ch! =#)Push(S,ch); break; }//switch 3.汉诺塔 voidhanoi(intn,charx,chary,charz){ //将塔座x上按直径由小到大且至上而下编号为1至n //的n个圆盘按规则搬到塔座z上,y可用作辅助塔座。 1if(n==1) 2move(x,1,z);//将编号为1的圆盘从x移到z 3else{ 4hanoi(n-1,x,z,y);//将x上编号为1至n-1的 //圆盘移到y,z作辅助塔 5move(x,n,z);//将编号为n的圆盘从x移到z 6hanoi(n-1,y,x,z);//将y上编号为1至n-1的 //圆盘移到z,x作辅助塔 7} 8} 树: 二叉树的顺序存储: #defineMAX_TREE_SIZE100//二叉树的最大结点数 typedefTElemTypeSqBiTree[MAX_ TREE_SIZE];//0号单元存储根结点 SqBiTreebt; 二叉树的二叉链表存储: typedefstructBiTNode{//结点结构 TElemTypedata; structBiTNode*lchild,*rchild; //左右孩子指针 }BiTNode,*BiTree; 二叉树的三叉链表存储: typedefstructTriTNode{//结点结构 TElemTypedata; structTriTNode*lchild,*rchild; //左右孩子指针 structTriTNode*parent;//双亲指针 }TriTNode,*TriTree; 二叉树的双亲链表存储: typedefstructBPTNode{//结点结构 TElemTypedata; int*parent;//指向双亲的指针 charLRTag;//左、右孩子标志域 }BPTNode 树的结构: typedefstructBPTree{//树结构 BPTNodenodes[MAX_TREE_SIZE]; intnum_node;//结点数目 introot;//根结点的位置 }BPTree 树的先序遍历: voidPreorder(BiTreeT, void(*visit)(TElemTyp
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 语言 算法 大全