您好,欢迎访问三七文档
当前位置:首页 > 临时分类 > 数据结构复习资料(亲自整理)
一、简答题1、链表:链表就是一串存储数据的链式结构。链式的优点在于,每个数据之间都是相关联的。2、线性结构:线性结构是一个有序数据元素的集合。常用的线性结构有:线性表,栈,队列,双队列,数组,串。3、树与二叉树二叉树是每个结点最多有两个子树的有序树;树是由n(n=1)个有限节点组成一个具有层次关系的集合。树和二叉树的2个主要差别:1.树中结点的最大度数没有限制,而二叉树结点的最大度数为2;2.树的结点无左、右之分,而二叉树的结点有左、右之分。4、堆堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:堆中某个节点的值总是不大于或不小于其父节点的值;堆总是一棵完全二叉树。5、二叉排序树二叉排序数的(递归)定义:1、若左子树非空,则左子树所有节点的值均小于它的根节点;2、若右子树非空,则右子树所有节点的值均大于于它的根节点;3、左右子树也分别为二叉排序树。二、应用题1、树与二叉树①前中后序遍历序列一、已知前序、中序遍历,求后序遍历例:前序遍历:GDAFEMHZ中序遍历:ADEFGHMZ画树求法:第一步,根据前序遍历的特点,我们知道根结点为G第二步,观察中序遍历ADEFGHMZ。其中root节点G左侧的ADEF必然是root的左子树,G右侧的HMZ必然是root的右子树。第三步,观察左子树ADEF,左子树的中的根节点必然是大树的root的leftchild。在前序遍历中,大树的root的leftchild位于root之后,所以左子树的根节点为D。第四步,同样的道理,root的右子树节点HMZ中的根节点也可以通过前序遍历求得。在前序遍历中,一定是先把root和root的所有左子树节点遍历完之后才会遍历右子树,并且遍历的左子树的第一个节点就是左子树的根节点。同理,遍历的右子树的第一个节点就是右子树的根节点。②树与二叉树的转换树转换为二叉树:二叉树转换为树:③二叉树线索化注意:图中的实线表示指针,虚线表示线索。结点C的左线索为空,表示C是中序序列的开始结点,无前趋;结点E的右线索为空,表示E是中序序列的终端结点,无后继。线索二叉树中,一个结点是叶结点的充要条件为:左、右标志均是1。2、图①邻接表一、邻接表邻接表是图的一种链式存储结构。邻接表中,对图中每个顶点建立一个单链表,第i个单链表中的结点表示依附于顶点Vi的边(对有向图是以顶点Vi为尾的弧)。邻接表中的表结点和头结点结构:表结点adjvexnextarcinfo头结点datafirstarc二、无向图的邻接表3、4、图7-5三、有向图的邻接表和逆邻接表(一)在有向图的邻接表中,第i个单链表链接的边都是顶点i发出的边。(二)为了求第i个顶点的入度,需要遍历整个邻接表。因此可以建立逆邻接表。(三)在有向图的逆邻接表中,第i个单链表链接的边都是进入顶点i的边。四、邻接表小结◆设图中有n个顶点,e条边,则用邻接表表示无向图时,需要n个顶点结点,2e个表结点;用邻接表表示有向图时,若不考虑逆邻接表,只需n个顶点结点,e个边结点。◆在无向图的邻接表中,顶点vi的度恰为第i个链表中的结点数。◆在有向图中,第i个链表中的结点个数只是顶点vi的出度。在逆邻接表中的第i个链表中的结点个数为vi的入度。②邻接矩阵(有向、无向)1.图的邻接矩阵表示法在图的邻接矩阵表示法中:①用邻接矩阵表示顶点间的相邻关系②用一个顺序表来存储顶点信息2.图的邻接矩阵(AdacencyMatrix)设G=(V,E)是具有n个顶点的图,则G的邻接矩阵是具有如下性质的n阶方阵:【例】下图中无向图G5和有向图G6的邻接矩阵分别为Al和A2。③广度优先遍历广度优先遍历是连通图的一种遍历策略。其基本思想如下:1、从图中某个顶点V0出发,并访问此顶点;2、从V0出发,访问V0的各个未曾访问的邻接点W1,W2,…,Wk;然后,依次从W1,W2,…,Wk出发访问各自未被访问的邻接点;3、重复步骤2,直到全部顶点都被访问为止。例如下图中:1.从0开始,首先找到0的关联顶点3,42.由3出发,找到1,2;由4出发,找到1,但是1已经遍历过,所以忽略。3.由1出发,没有关联顶点;由2出发,没有关联顶点。所以最后顺序是0,3,4,1,2④深度优先遍历深度优先遍历是连通图的一种遍历策略。其基本思想如下:设x是当前被访问顶点,在对x做过访问标记后,选择一条从x出发的未检测过的边(x,y)。若发现顶点y已访问过,则重新选择另一条从x出发的未检测过的边,否则沿边(x,y)到达未曾访问过的y,对y访问并将其标记为已访问过;然后从y开始搜索,直到搜索完从y出发的所有路径,即访问完所有从y出发可达的顶点之后,才回溯到顶点x,并且再选择一条从x出发的未检测过的边。上述过程直至从x出发的所有边都已检测过为止。例如下图中:1.从0开始,首先找到0的关联顶点32.由3出发,找到1;由1出发,没有关联的顶点。3.回到3,从3出发,找到2;由2出发,没有关联的顶点。4.回到4,出4出发,找到1,因为1已经被访问过了,所以不访问。所以最后顺序是0,3,1,2,4⑤Prim算法基本思想:假设G=(V,E)是连通的,TE是G上最小生成树中边的集合。算法从U={u0}(u0∈V)、TE={}开始。重复执行下列操作:在所有u∈U,v∈V-U的边(u,v)∈E中找一条权值最小的边(u0,v0)并入集合TE中,同时v0并入U,直到V=U为止。此时,TE中必有n-1条边,T=(V,TE)为G的最小生成树。Prim算法的核心:始终保持TE中的边集构成一棵生成树。注意:prim算法适合稠密图,其时间复杂度为O(n^2),其时间复杂度与边得数目无关,而kruskal算法的时间复杂度为O(eloge)跟边的数目有关,适合稀疏图。⑥Krusal算法图中先将每个顶点看作独立的子图,然后查找最小权值边,这条边是有限制条件的,边得两个顶点必须不在同一个图中,如上图,第一个图中找到最小权值边为(v1,v3),且满足限制条件,继续查找到边(v4,v6),(v2,v5),(v3,v6),当查找到最后一条边时,仅仅只有(v2,v3)满足限制条件,其他的如(v3,v4),(v1,v4)都在一个子图里面,不满足条件,至此已经找到最小生成树的所有边。⑦拓扑排序由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。对上图进行拓扑排序的结果:2-8-0-3-7-1-5-6-9-4-11-10-125、检索①二叉排序建立typedefstructnode{intdata;structnode*lchild;structnode*rchild;}node;voidInit(node*t){t=NULL;}voidInOrder(node*t)//中序遍历输出{if(t!=NULL){InOrder(t-lchild);printf(%d,t-data);InOrder(t-rchild);}}②二叉排序删除btree*DelNode(btree*p){if(p-lchild){btree*r=p-lchild;//r指向其左子树;btree*prer=p-lchild;//prer指向其左子树;while(r-rchild!=NULL)//搜索左子树的最右边的叶子结点r{prer=r;r=r-rchild;}p-data=r-data;if(prer!=r)//若r不是p的左孩子,把r的左孩子作为r的父亲的右孩子prer-rchild=r-lchild;elsep-lchild=r-lchild;//否则结点p的左子树指向r的左子树free(r);returnp;}else{btree*q=p-rchild;//q指向其右子树;free(p);returnq;}}③Huffman树、编码与解码例.给定有18个字符组成的文本:AADATARAEFRTAAFTER求各字符的哈夫曼码。(1)统计:(2)构造Huffman树:(3)在左分枝标0,右分枝标1:(4)确定Huffman编码:(5)译码:例.给定代码序列:001000111010101011110文本为:AAFARADET④散列存储6、内排序①希尔排序voidShellPass(SeqListR,intd){//希尔排序中的一趟排序,d为当前增量for(i=d+1;i=n;i++)//将R[d+1..n]分别插入各组当前的有序区if(R[i].keyR[i-d].key){R[0]=R[i];j=i-d;//R[0]只是暂存单元,不是哨兵do{//查找R[i]的插入位置R[j+d];=R[j];//后移记录j=j-d;//查找前一记录}while(j0&&R[0].keyR[j].key);R[j+d]=R[0];//插入R[i]到正确的位置上}//endif}//ShellPassvoidShellSort(SeqListR){intincrement=n;//增量初值,不妨设n0do{increment=increment/3+1;//求下一增量ShellPass(R,increment);//一趟增量为increment的Shell插入排序}while(increment1)}//ShellSort②直接插入排序voidlnsertSort(SeqListR){//对顺序表R中的记录R[1..n]按递增序进行插入排序inti,j;for(i=2;i=n;i++)//依次插入R[2],…,R[n]if(R[i].keyR[i-1].key){//若R[i].key大于等于有序区中所有的keys,则R[i]//应在原有位置上R[0]=R[i];j=i-1;//R[0]是哨兵,且是R[i]的副本do{//从右向左在有序区R[1..i-1]中查找R[i]的插入位置R[j+1]=R[j];//将关键字大于R[i].key的记录后移j--;}while(R[0].keyR[j].key);//当R[i].key≥R[j].key时终止R[j+1]=R[0];//R[i]插入到正确的位置上}//endif}//InsertSort③选择排序voidSelectSort(SeqListR){inti,j,k;for(i=1;in;i++){//做第i趟排序(1≤i≤n-1)k=i;for(j=i+1;j=n;j++)//在当前无序区R[i..n]中选key最小的记录R[k]if(R[j].keyR[k].key)k=j;//k记下目前找到的最小关键字所在的位置if(k!=i){//交换R[i]和R[k]R[0]=R[i];R[i]=R[k];R[k]=R[0];//R[0]作暂存单元}//endif}//endfor}//SeleetSort④交换排序voidBubbleSort(SeqListR){//R(l..n)是待排序的文件,采用自下向上扫描,对R做冒泡排序inti,j;Booleanexchange;//交换标志for(i=1;in;i++){//最多做n-1趟排序exchange=FALSE;//本趟排序开始前,交换标志应为假for(j=n-1;j=i;j--)//对当前无序区R[i..n]自下向上扫描if(R[j+1].keyR[j].key){//交换记录R[0]=R[j+1];//R[0]不是哨兵,仅做暂存单元R[j+1]=R[j];R[j]=R[0];exchange=TRUE;//发生了交换,故将交换标志置为真}if(!exchange)//本趟排序未发生交换,提前终止算法return;}//endfor(外循环)}//BubbleSortvoidQuickSort(SeqListR,intlow,inthigh){//对R[low..high]快速排序intpivotpos;//划分后的基准记录的位置if(lowhigh){//仅当区间长度大于1时才须排序pivotpos=Partition(R,low,high);//对R[low..
本文标题:数据结构复习资料(亲自整理)
链接地址:https://www.777doc.com/doc-1810788 .html