考研数据结构算法经典.docx
- 文档编号:6250812
- 上传时间:2023-01-04
- 格式:DOCX
- 页数:21
- 大小:20.08KB
考研数据结构算法经典.docx
《考研数据结构算法经典.docx》由会员分享,可在线阅读,更多相关《考研数据结构算法经典.docx(21页珍藏版)》请在冰豆网上搜索。
考研数据结构算法经典
一、线性表
1.逆转顺序表中的所有元素
算法思想:
第一个元素和最后一个元素对调,第二个元素和倒数第二个元素对调,……,依此类推。
voidReverse(intA[],intn)
{inti,t;
for(i=0;i {t=A[i]; A[i]=A[n-i-1]; A[n-i-1]=t; }} 2.删除线性链表中数据域为item的所有结点 算法思想: 先从链表的第2个结点开始,从前往后依次判断链表中的所有结点是否满足条件,若某个结点的数据域为item,则删除该结点。 最后再回过头来判断链表中的第 1个结点是否满足条件,若满足则将其删除。 voidPurgeItem(LinkList&list) {LinkListp,q=list; p=list->next; while(p! =NULL) {if(p->data==item){ q->next=p->next; free(p); p=q->next; }else{ q=p; p=p->next; }} if(list->data==item) {q=list; list=list->next; free(q); }} 3.逆转线性链表 voidReverse(LinkList&list) {LinkListp,q,r; p=list; q=NULL; while(p! =NULL) {r=q; q=p; p=p->next; q->next=r; } list=q; } 4.复制线性链表(递归) LinkListCopy(LinkListlista) {LinkListlistb; if(lista==NULL) returnNULL; else{ listb=(LinkList)malloc(sizeof(LNode)); listb->data=lista->data; listb->next=Copy(lista->next); returnlistb; } } 5.将两个按值有序排列的非空线性链表合并为一个按值有序的线性链表 LinkListMergeList(LinkListlista,LinkListlistb) {LinkListlistc,p=lista,q=listb,r; //listc指向lista和listb所指结点中较小者 if(lista->data<=listb->data){ listc=lista; r=lista; p=lista->next; }else{ listc=listb; r=listb; q=listb->next; } while(p! =NULL&&q! =NULL) {if(p->data<=q->data){ r->next=p; r=p; p=p->next; }else{ r->next=q; r=q; q=q->next; } } //将剩余结点(即未参加比较的且已按升序排列的结点)链接到整个链表后面 r->next=(p! =NULL)? p: q; returnlistc; } 二、树 1.二叉树的先序遍历(非递归算法) 算法思想: 若p所指结点不为空,则访问该结点,然后将该结点的地址入栈,然后再将p指向其左孩子结点;若p所指向的结点为空,则从堆栈中退出栈顶元素(某个结点的地址),将p指向其右孩子结点。 重复上述过程,直到p=NULL且堆栈为空,遍历结束。 #defineMAX_STACK50 voidPreOrderTraverse(BTreeT) {BTreeSTACK[MAX_STACK],p=T; inttop=-1; while(p! =NULL||top! =-1) {while(p! =NULL) {VISIT(p); STACK[++top]=p; p=p->lchild; } p=STACK[top--]; p=p->rchild; }} 2.二叉树的中序遍历(非递归算法) 算法思想: 若p所指结点不为空,则将该结点的地址p入栈,然后再将p指向其左孩子结点;若p所指向的结点为空,则从堆栈中退出栈顶元素(某个结点的地址)送p,并访问该结点,然后再将p指向该结点的右孩子结点。 重复上述过程,直到p=NULL且堆栈为空,遍历结束。 #defineMAX_STACK50 voidInOrderTraverse(BTreeT) {BTreeSTACK[MAX_STACK],p=T; inttop=-1; while(p! =NULL||top! =-1); {while(p! =NULL) {STACK[++top]=p; p=p->lchild; } p=STACK[top--]; VISIT(p); p=p->rchild; } } 3.二叉树的后序遍历(非递归算法) 算法思想: 当p指向某一结点时,不能马上对它进行访问,而要先访问它的左子树,因而要将此结点的地址入栈;当其左子树访问完毕后,再次搜索到该结点时(该结点地址通过退栈得到),还不能对它进行访问,还需要先访问它的右子树,所以,再一次将该结点的地址入栈。 只有当该结点的右子树访问完毕后回到该结点时,才能访问该结点。 为了标明某结点是否可以访问,引入一个标志变量flag,当flag=0时表示该结点暂不访问,flag=1时表示该结点可以访问。 flag的值随同该结点的地址一起入栈和出栈。 因此,算法中设置了两个堆栈,其中STACK1存放结点的地址,STACK2存放标志变量flag,两个堆栈使用同一栈顶指针top,且top的初始值为.1。 #defineMAX_STACK50 voidPostOrderTraverse(BTreeT) {BTreeSTACK1[MAX_STACK],p=T; intSTACK2[MAX_STACK],flag,top=-1; while(p! =NULL||top! =-1) {while(p! =NULL){ STACK1[++top]=p; STACK2[top]=0; p=p->lchild; } p=STACK1[top]; flag=STACK2[top--]; if(flag==0){ STACK1[++top]=p; STACK2[top]=1; p=p->rchild; }else{ VISIT(p); p=NULL; } } } 4.二叉树的按层次遍历 算法思想: 设置一个队列,首先将根结点(的地址)入队列,然后依次从队列中退出一个元素,每退出一个元素,先访问该元素所指的结点,然后依次将该结点的左孩子结点(若存在的话)和右孩子结点(若存在的话)入队列。 如此重复下去,直到队列为空。 #defineMAX_QUEUE50 voidLayeredOrderTraverse(BTreeT) {BTreeQUEUE[MAX_QUEUE],p; intfront,rear; if(T! =NULL) {QUEUE[0]=T; front=-1; rear=0; while(front { p=QUEUE[++front]; VISIT(P); if(p->lchild! =NULL) QUEUE[++rear]=p->lchild; if(p->rchild! =NULL) QUEUE[++rear]=p->rchild; } } } 5.建立二叉树(从键盘输入数据,先序遍历递归算法) BTreeCreateBT() {charch; BTreeT; sacnf("%c",&ch); if(ch=='') returnNULL; else{ T=(BTree)malloc(sizeof(BTNode)); T->data=ch; T->lchild=CreateBT(); T->rchild=CreateBT(); returnT; } } 6.建立二叉树(从数组获取数据) BTreeCreateBT(intA[],inti,intn) {BTreep; if(i>n) returnNULL; else{ p=(BTree)malloc(sizeof(BTNode)); p->data=A[i]; p->lchild=CreateBT(A,2*i,n); p->rchild=CreateBT(A,2*i+1,n); returnp; } } T=CreateBT(A,1,n); BTreeCreateBT(intA[],intn) { inti; BTree*pT; //对应n个结点申请可容纳n个指针变量的内存空间 pT=(BTree*)malloc(sizeof(BTree)*n); //若数组中的某个元素不等于零,则申请相应的结点空间并进行赋值 for(i=1;i<=n;i++) { if(A[i]! =0){ pT[i]=(BTree)malloc(sizeof(BTNode)); pT[i]->data=A[i]; }else{ pT[i]=NULL; } } //修改结点的指针域的内容,使父结点指向左、右孩子结点 for(i=1;i<=n;i++) { if(pT[i]! =NULL) {pT[i]->lchild=pT[2*i]; pT[i]->rchild=pT[2*i+1]; } } } 7.求二叉树的深度(递归算法) intDepth(BTreeT) { intldepth,rdepth; if(T==NULL) return0; else{ ldepth=Depth(T->lchild); rdepth=Depth(T->rchild); if(ldepth>rdepth) returnldepth+1; else returnrdepth+1; } } 8.求二叉树的深度(非递归算法) 算法思想: 对二叉树进行遍历,遍历过程中依次记录各个结点所处的层次数以及当前已经访问过的结点所处的最大层次数。 每当访问到某个叶子结点时,将该叶子结点所处的层次数与最大层次数进行比较,若前者大于后者,则修改最大层次数为该叶子结点的层次数,否则不作修改。 遍历结束时,所记录的最大层次数即为该二叉树的深度。 本算法使用的是非递归的中序遍历算法(其它遍历顺序也可以)。 #defineMAX_STACK50 intDepth(BTreeT) { BTreeSTACK1[MAX_STACK],p=T; intSTACK2[MAX_STACK]; intcurdepth,maxdepth=0,top=-1; if(T! =NULL) { curdepth=1; while(p! =NULL||top! =-) { while(p! =NULL) { STACK1[++top]=p; STACK2[top]=curdepth; p=p->lchild; curdepth++; } p=STACK1[top]; curdepth=STACK2[top--]; if(p->lchild==NULL&&p->rchild==NULL) if(curdepth>maxdepth) maxdepth=curdepth; p=p->rchild; curdepth++; } } returnmaxdepth; } 9.求结点所在层次 算法思想: 采用后序遍历的非递归算法对二叉树进行遍历,遍历过程中对每一个结点判断其是否为满足条件的结点,若是满足条件的结点,则此时堆栈中保存的元素个数再加 1即为该结点所在的层次。 #defineMAX_STACK50 intLayerNode(BTreeT,intitem) { BTreeSTACK1[MAX_STACK],p=T; intSTACK2[MAX_STACK],flag,top=-1; while(p! =NULL||top! =-1) {while(p! =NULL) {STACK1[++top]=p; STACK2[top]=0; p=p->lchild; } p=STACK1[top]; flag=STACK2[top--]; if(flag==0){ STACK1[++top]=p; STACK2[top]=1; p=p->rchild; }else{ if(p->data==item) returntop+2; p=NULL; } } } 10.交换二叉树中所有结点的左右子树的位置 算法思想: 按层次遍历二叉树,遍历过程中每当访问一个结点时,就将该结点的左右子树的位置对 调。 #defineMAX_QUEUE50 voidExchangeBT(BTreeT) {BTreeQUEUE[MAX_QUEUE],temp,p=T; intfront,rear; if(T! =NULL) { QUEUE[0]=T; front=-1; rear=0; while(front {p=QUEUE[++front]; temp=p->lchild; p->lchild=p->rchild; p->rchild=temp; if(p->lchild! =NULL) QUEUE[++rear]=p->lchild; if(p->rchild! =NULL) QUEUE[++rear]=p->rchild; } } } 11.删除二叉树中以某个结点为根结点的子树 算法思想: 先序遍历找到符合条件的结点(其它遍历方法亦可),然后删除以该结点为根结点的子树。 最后把该结点的父结点的相应的指针域置为NULL。 为此,需在算法中设置一个指针变量用以指示当前结点的父结点。 #defineMAX_STACK50 BTreeDeleteSubtree(BTree&T,intitem) { BTreeSTACK[MAX_STACK],q,p=T; inttop=-1; if(T->data==item) { DestroyBT(T); T=NULL; returnNULL; } else {while(p! =NULL||top! =-1) {while(p! =NULL) {if(p->data==item) {if(q->lchild==p) q->lchild=NULL; else q->rchild=NULL; DestroyBT(p); returnT; } STACK[++top]=p; q=p; p=p->lchild; } q=STACK[top--]; p=q->rchild; } } } 三、查找 1.顺序查找的递归算法 intRecurSeqSearch(intA[],intn,intkey,inti) { if(i>=n) return-1; if(A[i]==key) returni; else returnRecurSeqSearch(A,n,key,i+1); } pos=RecurSeqSearch(A,n,key,0); 2.折半查找 intBinSearch(intA[],intn,intkey) { intlow=0,high=n-1,mid; while(low<=high) { mid=(low+high)/2; if(key==A[mid]) returnmid; if(key>A[mid]) low=mid+1; else high=mid–1; } return-1; } 3.折半查找的递归算法 intRecurBinSearch(intA[],intlow,inthigh,intkey) { intmid; if(low>high) return-1; else{ mid=(low+high)/2; if(key==A[mid]) returnmid; if(key>A[mid]) returnRecurBinSearch(A,mid+1,high,key); else returnRecurBinSearch(A,low,mid-1,key); } } pos=RecurBinSearch(A,0,n-1,key); 4.在按值递增排列且长度为 n的线性表中折半查找并插入一元素 voidBinInsert(intA[],int&n,intkey) { intj,low=0,high=n-1,mid; while(low<=high) { mid=(low+high)/2; if(key>A[mid]) low=mid+1; else high=mid–1; } for(j=n;j>low;j--) A[j]=A[j-1]; A[low]=key; n++; } 5.在按值递增排列且长度为 n的线性表中折半查找值不小于 key的最小元素 voidBinSearch(intA[],intn,intkey) { intlow=0,high=n-1,mid; while(low<=high) { mid=(low+high)/2; if(key==A[mid]) returnmid; if(key>A[mid]) low=mid+1; else high=mid–1; } if(low<=n-1) returnlow; else return-1; } 四、排序 1.插入排序 算法思想: 第 i趟插入排序为: 在含有i.1个元素的有序子序列中插入一个元素,使之成为含有i个元素的有序子序列。 在查找插入位置的过程中,可以同时后移元素。 整个过程为进行n.1趟插入,即先将整个序列的第1个元素看成是有序的,然后从第2个元素起逐个进行插入,直到整个序列有序为止。 voidInsertSort(intA[],intn) { inti,j,temp; for(i=1;i<=n-1;i++) { if(A[i] { j=i-1; temp=A[i];
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 考研 数据结构 算法 经典