数据结构各章考研习题重点总结

    • 第一章-绪论
        • 应用题
    • 第二章-线性表
        • 客观题
        • 应用题
        • 算法设计题
    • 第三章-栈和队列
        • 客观题
        • 应用题
        • 设计题
    • 第四章-串
        • 客观题
        • 应用题
        • 算法设计题
    • 第五章-数组和广义表
        • 客观题
    • 第六章-树和二叉树
        • 客观题
        • 应用题
        • 算法设计题
    • 第七章-图
        • 算法设计题
    • 第十章-排序
        • 客观题

第一章-绪论

应用题

1. 数据存储结构包括哪几种类型?数据逻辑结构包括哪几种类型?
答:存储结构包括顺序存储,链式存储,索引存储和散列存储;
逻辑结构包括线性结构和非线性结构。更细分的说,逻辑结构包括集合、线性结构、树形结构和图形(网状)结构。

2. 数据结构是一门研究什么内容的学科?
答:数据结构是一门研究在非数值计算的程序设计问题中,计算机的操作对象及 对象间的关系和施加于对象的操作等的学科。

3. 数据元素之间的关系在计算机中有几种表示方法?各有什么特点?
答:四种表示方法。
1、顺序存储方式。数据元素顺序存放,每个存储结点只含一个元素。存储位置反映数据元素间的逻辑关系。存储密度大,但有些操作(如插入、删除)效率较差。
2、链式存储方式。每个存储结点除包含数据元素信息外还包含一组(至少一个)指针。指针反映数据元素间的逻辑关系。这种方式不要求存储空间连续,便于动态操作(如插入、删除等),但存储空间开销大(用于指针),另外不能折半查找等。
3、索引存储方式。除数据元素存储在一地址连续的存储空间外,尚需建立一个索引表,索引表的索引项指示存储结点的存储位置(下标)或存储区间端点(下标,非稠密索引)兼有静态和动态特性。
4、散列存储方式。利用散列函数和解决冲突的方法,将关键字散列在连续的有限的地址空间内,并将散列函数的值解释成关键字所在元素的存储地址。其特点是存取速度快,只能按关键字随机存取,不能顺序存取,也不能折半存取。

4. 评价一个好的算法,你是从哪几方面来考虑的?
答:1、算法的正确性。 2、算法的易读性。 3、算法的健壮性 4、算法的时空效率。

5. 对于一个数据结构,一般包括哪三个方面的讨论?
答:逻辑结构,存储结构,操作(运算)。

6. 数据结构与数据类型有什么区别?
“数据结构”这一术语有两种含义,一是作为一门课程的名称;二是作为一个科学的概念作为科学概念,目前尚无公认定义,一般认为,讨论数据结构要包括三个方面,一是数据的逻辑结构,二是数据的存储结构,三是对数据进行的操作(运算)。而数据类型是值的集合和操作的集合,可以看作是已实现了的数据结构,后者是前者的一种简化情况。

7. 算法的五个重要特征是什么?
答:有穷性,确定性,可行性,零个或多个输入和1至多个输出。

第二章-线性表

客观题

  1. 线性表的顺序存储结构是一种( )。
    A.随机存取的存储结构 B.顺序存取的存储结构
    C.索引存取的存储结构 D.Hash存取的存储结构

答案:A
顺序存储结构的地址在内存中是连续的,所以可以通过计算地址实现随机存取。而链式存储结构的存储地址不一定连续,只能通过逐个结点的指针顺序存取。

  1. 若某线性表最常用的操作是存取任一指定序号的元素和在最后进行插入和删除运算,则利用( )存储方式最节省时间。
    A.顺序表 B.双链表 C.带头结点的双循环链表 D.单循环链表

答案:A
顺序表的优点之一是随机存取,即时间复杂度为O(1),而插入和删除的时间复杂度都是O(n),但是在最后插入结点和删除结点的时间复杂度都是O(1)。

  1. 设一个链表最常用的操作是在末尾插入结点和删除尾结点,则选用( )最省时间
    A.单链表 B.单循环链表
    C.带尾指针的单循环链表 D.带头结点的双循环链表

答案:D
带有尾指针的单循环链表删除尾结点时要遍历整个链表,时间复杂度是O(n)。只有用带头结点的双循环链表完成要求的操作最节省时间,时间复杂度是O(1)。

  1. 顺序存储结构属于静态结构,链式结构属于动态结构。(×)

应用题

  1. 线性表的顺序存储结构具有三个弱点:第一,在作插入或删除操作时,需要移动大量元素;第二,由于难以估计,必须预先分配较大的空间,往往使存储空间不能得到充分利用;第三,表的容量难以扩充。试问,线性表的链式存储结构是否一定能够克服上述三个弱点?请简述之
    答:一般说链式存储结构克服了顺序存储结构的三个弱点。首先,插入、删除不需移动元素,只修改指针,时间复杂度为O(1);其次,不需要预先分配空间,可根据需要动态申请空间;其三,表容量只受可用内存空间的限制。其缺点是因为指针增加了空间开销,当空间不允许时,就不能克服顺序存储结构的缺点。

  2. 在单链表和双向链表中,能否从当前结点出发访问到任何一个结点?
    答:在单链表中不能从当前结点(若当前结点不是第一结点)出发访问到任何一个结点。因为链表运算只能从头指针开始,访问到链表中每个结点。在双链表中从当前结点反向可以到第一结点,正向可以到最后结点,因而从当前结点出发可以访问到链表中任何一个结点。

  3. 解释链表的头指针、头结点、首元结点这三个概念
    头结点:头结点是在链表的首元结点之前附设的一个结点,数据域通常用来保存跟链表有关的信息,比如链表的长度;
    首元结点:首元结点是链表的开始结点,指链表中存储线性表中第一个数据元素a1的结点。
    头指针:头指针是指向链表中第一个结点的指针,如果链表存在头结点则头指针就是指向头结点的地址,反之指向首元结点的地址。

  4. 设双向循环链表中结点的数据域、前驱和后继指针域分别为data、pre和next,试写出在指针P所指结点之前插入一s结点的C语言描述语句。
    答:在指针P所指结点前插入结点s的语句如下:
    s->pre=p->pre; s->next=p; p->pre->next=s; p->pre=s;

  5. 请简要说明下列函数的主要功能。
    void func( LinkList LI, LinkList L2)
    {LNode*p, *q, *r;
    q=L2->next;
    while (g)
    {p= LI;
    while (p->next)
    {if (p->next->data = q->data)
    {r=p->next; p->next=r->next; free®;}
    p = p->next;
    }
    q=q->next;
    }
    return;
    }
    答:算法实现集合的差运算C=A-B。将链表L2中的元素依次到链表L1中查找,有则从L1中删除。

算法设计题

  1. 两个单链表合并成一个链表的算法
void MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc){
	//已知单链线性表La和Lb的元素按值非递减排列
	//归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列
	pa=La->next;  pb=Lb->next;
	Lc=pc=pa;            //用La的头结点作为Lc的头结点
	while(pa && pb){
		if(pa->data <= pb->data){
			pc->next=pa; pc=pa; pa=pa->next;
		}
		else{pc->next=pb; pc=pb; pb=pb->next;}
	}
	pc->next=pa?pa:pb;    //插入剩余段
	free(Lb);             //释放Lb的头结点
}
  1. 头插法实现一个单链表的创建过程算法
void CreateList_L(LinkList &L,int n){
	L=(LinkList)malloc(sizeof(LNode));
	L->next = NULL;   //先建立一个带头结点的单链表
	for(i=n; i>0; --i){
	p=(LinkList)malloc(sizeof(LNode));  //生成新结点
		scanf(&p->data);  	//输入元素值
		p->next = L->next;
		L->next = p;   //插入到表头
	}
}
  1. 逆置顺序表的算法
核心语句是:
for(i=0; i<=(n-1)/2; i++) a[i]<-->a[n-i-1];
  1. 带头结点的单链表逆置
核心语句段如下:
while(p!=NULL)           //head是链表头结点的指针,p初值指向第一元素结点
	{r=o->next;          //暂存p的后继
	p->next=head->next; head->next=p;     //逆置
	p=r;}                //恢复待逆置结点
  1. 删除单链表中的重复元素
本题未说单链表有序,因此要依次从每个结点出发,遍历整个链表,删除重复元素。删除结点要记住被删结点的前驱,不能断链。核心语句段如下:
while(pre!=null)          //用pre控制依次从每个结点出发,初始指向第一元素
	{m=pre->data; q=pre; p=pre->next;
	while(p!=null)
		if(p->data==m) {u=p; p=p->next; free(u);}    //删重复结点
		else{q->next=p; q=p; p=p->next;}
	q->next=p;            //有可能链表尾结点值是m
	pre=pre->next;        //下一趟
	}

第三章-栈和队列

客观题

  1. 在栈的ADT定义中,除初始化操作外,其他基本操作的初始条件都要求 栈已存在
  2. 堆栈是一种 操作受限 的线性表,它只能在线性表的 一端 进行插入和删除操作,,对栈的访问是按照 后进先出 的原则进行的。
  3. 顺序栈用data[1…n]存储数据,栈顶指针是top,则值为x的元素入栈的操作是 if(top!=n) data[++top]=x;

应用题

  1. 若有一个一维数组A,它的元素下标从1开始到MAX。要在数组A中建立两个栈共享同一空间,栈Sl的栈顶指针为topl,栈S2的栈顶指针为top2,为了最大限度地利用数组A的空间,则应该如何共享?栈满和栈空的条件是什么?
    答:两站共享数组A,top1=0时S1栈空,top2=MAX+1时,S2栈空,top2-top1=1时栈满。

  2. (1)什么是递归程序?
    答:一个函数在结束本函数运行之前,直接或间接调用函数自身,称为递归。

    例如,函数f在执行中,又调用函数f自身,称为直接递归;若函数f执行中,调用函数g,而g执行中,又调用函数f,这称为间接递归。在实际应用中,多为直接递归,也常简称为递归
    

    (2)递归程序的优、缺点是什么?
    答:递归程序的优点是程序结构简单、易读、清晰,易证明其正确性。缺点是执行中占内存空间较多,运行效率低,不易优化。
    (3)递归程序在执行时,应借助于什么来完成?
    答:递归程序执行中需借助栈这种数据结构来实现。
    (4)递归程序的入口语句、出口语句一般用什么语句实现?
    答:递归程序的入口语句和出口语句一般用条件判断语句来实现。

  3. 简述顺序存储队列的假溢出的避免方法及队列满和空的条件。
    答:设顺序存储队列用一维数组q[m]表示,其中m为队列中元素个数,队列中元素在向量中的下标从0到m-1。设队头指针为front,队尾指针是rear,约定font指向队头元素的前一位置,rear指向队尾元素。当front等于-1时队空,rear等于m-1时为队满。由于队列的性质(“删除”在队头而“插入”在队尾),所以当队尾指针rear等于m-1时,再无法入队。若经过几次退队,队列中会有空闲单元,所以队列并不是真满,这称为“假溢出”。其解决办法有二,一是将队列元素向前“平移”(占用0至rear-front-1);二是将队列看成首尾相连即看做循环队列(0…m-1)。在循环队列下,仍定义front=rear时为队空,而判断队满则常用两种方法:一种是用“牺牲一个单元”,即rear+1=front(准确记是(rear+1)%m=front,m是队列容量)时为队满;另一种方法是“设标记”,如设标记tag,tag=0时,若因删除导致front=rear为队空;tag=1时,若因插入导致font=rear则为队满。

设计题

假设称正读和反读都相同的字符序列为“回文”,例如, ‘abcba’是回文, 'abcde’和 ‘ababab’则不是回文。试写一个算法判別读入的一个以’@’为结束符的字符序列是否是“回文”。

设以字符数组A存储读入的字符串,字符串长度为n。核心语句端如下:
for(int i=0l i<n/2; i++)
	if(A[i]!=A[n-1-i]){count<<"字符串非中心对称"<<endl; exit(0);}
cout<<"字符串中心对称"<<endl;

第四章-串

客观题

  1. 设正文串长度为n,模式串长度为m,则串匹配的KMP算法的时间复杂度为 O(m+n)
  2. 实现字符串拷贝的函数 strcpy为:
    void strcpy(char*a, char *t)/copy t to s/
    { while( *s++=*t++)}

应用题

在字符串模式匹配的KMP算法中,求模式的next数组值的定义如下:

N e x t [ j ] = { 0 , 当 j = 1 时 m a x ( k ∣ 1 < k < j 且 ′ P 1.... P k − 1 ′ = ′ P j − k + 1... P j − 1 ′ ) 1 , 其 他 情 况 Next[j]= \begin{cases} 0,当j=1时\\ max(k | 1Next[j]=0j=1max(k1<k<jP1....Pk1=Pjk+1...Pj1)1
请问:
(1)当j=1时,为什么要取next[1]=0?

答:当模式串中第一个字符与主串中某字符比较不等(失配)时, next[1]=0表示模式串中已没有字符可与主串中当前字符s[i]比较,主串当前指针应后移至下一字符,再和模式串中第一个字符进行比较。
(2)为什么要取max{k},k最大是多少?
答:当主串第i个字符与模式串中第j个字符失配时,若主串i不回溯,则假定模式串第k个字符与主串第i个字符比较,k值应满足条件1 (3)其他情况是什么情况?为什么取 next[j]=1?
答:在上面两种情况外发生失配时,主串指针i不回溯,在最坏情况下,模式串从第1
个字符开始与主串第i个字符比较,以便不丢失可能的匹配。

算法设计题

设s、t为两个字符串,分别放在两个一维数组中,m、n分别为其长度,判断t是否为s的子串。如果是,输出子串所在位置(第一个字符),否则输出0。(注:用程序实现。)

首先应查找字符串s的pos位置,将第pos个字符到字符串s尾的子串向后移动字符串t的长度,然后将字符串t复制到字符串s的第pos位置后。对插入位置pos要验证其合法性,题目假设给字符串s的空间足够大,故对插入不必判溢出。
while(*p!='\0' && i<pos) {p++; i++;}     //查pos位置
if(*p == '\0') {cout<<"pos位置大于字符串s的长度"<<endl; exit(0);}
else                                     //查找字符串的尾
	while(*p!='\0'){ p++; i++;}          //查到尾时,i为字符'\0'的下标,p也指向'\0'
while(*q!='\0'){q++; x++;}               //查找字符串t的长度x,循环结束时q指向'\0'
for(j=i; j>=pos; j--){*(p+x)=*p; p--;}   //串s的pso后的子串右移
q--;                                     //指针q回退到串t的最后一个字符
for(j=1; j<=x; j++) *p--=*q--;           //将t串插入s的pos位置上

第五章-数组和广义表

客观题

  1. 设7行6列的数组a以列序为主序顺序存储,基地址为1024,每个元素占2个存储单元,第4行第5列的元素(假定无第0行第0列)的存储地址是( )。
    A.1068          B.1086          C.1084          D.1066

答案:B

  1. 对矩阵压缩存储是为了( )。
    A.方便运算          B.方便储存          C.提高运算速度          D.减少储存空间

答案:D

3.设有一个n行n列的对称矩阵A,将其下三角部分按行存放在一个一维数组B中,A[0][0]存放于B[0]中,那第i行的对角元素A[i][i]存放于B中( )处。
A.(i+3)*i/2          B.(i+1)*i/2          C.(2n-i+1)*i/2          D(2n-i-1)i/2

答案:A

  1. 已知广义表LS=((a,b,c),(d,e,f)),运用head和tail函数取出LS中原子e的运算是( )。
    A、head(tail(LS))
    B、tail(head(LS))
    C、head(tail(head(tail(LS)))
    D、head(tail(tail(head(LS))))

答案:C
tail(LS) = ((d,e,f))
head(tail(LS)) = (d,e,f)
tail(head(tail(LS))) = (e,f)//无论如何都会加上这个()括号
head(tail(head(tail(LS)))) = e//head可以去除单个元素

  1. 广义表A=(a,b,(c,d),(e,(f,g))),则下面式子Head(Tail(Head(Tail(Tail(A)))))的值为( ).
    A、(g)          B、(d)         C、c          D、d

答案:D

  1. 数组的存储结构采用 顺序存储结构 存储方式。

  2. 二维数组A[10…20,5…10]采用行序为主序方式存储,毎个数据元素占4个存储单元,且A[10,5]的存储地址是1000,则A[18,9]的存储地址是 1208

  3. 设数组a[1…50,1…80]的基地址为2000,每个元素占2个存储单元,若以行序为主序顺序存储,则元素a[45,68]的存储地址为 9174 ;若以列序为主序顺序存储,则元素a[45,68]的存储地址为 8788

第六章-树和二叉树

客观题

  1. 已知一棵完全二叉树的第6层(设根是第1层)有8个叶结点,则该完全二叉树的结点个数最多是( )。
    A、39          B、52          C、111          D、119

答案:C

  1. 对n(n≧2)个权值均不相同的字符构造哈夫曼树。下列关于该哈夫曼树的叙述中,错误的是( )。
    A.该树一定是一棵完全二叉树
    B.树中一定没有度为1的结点
    C.树中两个权值最小的结点一定是兄弟结点
    D.树中任一非叶结点的权值一定不小于下一层任一结点的权值

答案:A

  1. 若一棵二叉树的前序遍历序列为a,e,b,d,c,后序遍历序列为b,c,d,e,a,则根结点的孩子结点( )。
    A、只有e         B、有e、b         C、有e、c          D、无法确定

答案:A

  1. 5个字符有如下4种编码方案,不是前缀编码的是( )。
    A、01,0000,0001,001,1         B、011,000.001,010,1        
    C、000,001,010,011,100        D、0,100,110,1110,1100

答案: D
前缀编码是指一个编码不是另一个编码的前缀

  1. 树是一种逻辑关系,表示数据元素之间存在的关系为( )。
    A、集合关系        B、一对一关系         C、一对多关系         D、多对多关系

答案:C

  1. 下列判断中( )是正确的。
    A、二叉树就是度为2的树         B、二叉树中不存在度大于2的结点        
    C、二叉树是有序树         D、二叉树的每个结点的度都为2

答案:B

  1. 在下述结论中,正确的是( )。
    ①只有一个结点的二又树的度为0
    ②二叉树的度为2。
    ③二又树的左右子树可任意交换
    ④深度为K的完全二叉树的结点个数小于或等于深度相同的满二叉树。
    A.①②③ B.②③④ C.②④ D.①④

答案:D

  1. 具有10个叶结点的二又树中有( )个度为2的结点。
    A、8          B、9          C、10          D、11

答案:B
对任何一棵二叉树T,如果其终端结点数为n0,度为2的节点数为n2,则n0=n2+1

  1. 一棵完全二叉树上有1001个结点,其中叶子结点的个数是( )。
    A、250          B、500          C、254          D、505          E、以上答案都不对

答案:E
因为n=n0+n1+n2,n2=n0-1,所以n=2n0+n1-1。在完全二叉树中,n1取1或0,这里n=1001,n1只能为0,所以n=2n0-1,n0=501,选E

  1. 当结点数目一定时,具有最小深度的二叉树是( )。
    A、满二叉树          B、完全二叉树         C、线素二叉树          D、二叉排序树

答案:B

  1. 设二叉树中有n2个度为2的结点,有n1个度为1的结点,有n0个度为0的结点,则该二叉树中空指针个数为( )。
    A、n2+n1+n0          B、n2+n1+2n0          C、2n2+n1          D、n1+2n0

答案:D
度为2的结点没空指针,度为1的结点有一个空指针,度为0的结点(叶子)有两个空指针

  1. 若二叉树采用二叉链表存储结构,要交换其所有分支结点左、右子树的位置,
    利用( )遍历方法最合适。
    A、前序 B、中序 C、后序 D、按层次

答案:AC

  1. 根据( )可以唯一地确定一棵二叉树。
    A、先序遍历和后序遍历 B、先序遍历和层次遍历
    C、中序遍历和层次遍历 D、中序遍历和后序遍历

答案:CD

  1. 某二叉树的前序序列和中序序列正好相反,则该二叉树一定具有( )的特征
    A、二叉树为空或只有一个结点
    B、若二叉树不为空,则任一结点不能同时拥有左孩子和右孩子
    C、若二叉树不为空,则任一结点没有左孩子
    D、若二叉树不为空,则任一结点没有右孩子

答案:ABD

  1. 在下列存储形式中,哪一个不是树的存储式( )。
    A、双亲表示法B、孩子链表表示法C、孩子兄弟表示法D、顺序存储表示法

答案:D

  1. n个结点的线索二叉树上含有的线索数为( )。
    A、2n B、n-1 C、n+1 D、n

答案:C
线索二叉树是利用二叉树的空链域加上线索,n个结点的二叉树有n+1个空链域

  1. 二叉树在线索化后,仍不能有效求解的问题是()。
    A、先序线索二叉树中求先序后继 B、中序线索二叉树中求中序后继
    C、中序线索二叉树中求中序前驱 D、后序线索二叉树中求后序后继

答案:D

  1. 在线素二叉树中,下面说法不正确的是( )。
    A、在中序线索树中,若某结点有右孩子,则其后继结点是它的右子树的左支末端结点
    B、线素二叉树是利用二叉树的n+1个空指针来存放结点前驱和后继信息的
    C、每个结点通过线索都可以直接找到它的前驱和后继
    D、在中序线索树中,若某结点有左孩子,则其前駆结点是它的左子树的右支末端结点

答案:C

  1. 一棵 Huffman树共有215个结点,对其进行 Huffman编码,共能得到( )个不同的码字。
    A、107 B、108 C、214 D、215

答案:B
Huffman树只有叶子节点才是编码字,而Huffman树中的节点,要么度为0,要么度为2。本题中除了树根总共有214个结点,叶子节点为214的一半再加一个等于108,所以能得到108个不同的码字

  1. 二叉树是一般树的特殊情形。( × )
  2. 树与二叉树是两种不同的树形结构。( √ )
  3. 二叉树只能采用二叉链表来存储。( × )
  4. 二叉树中不存在度大于2的结点,当某个结点只有一棵子树时,无所谓左右子树之分。( × )
  5. 具有10个叶结点的二叉树中,有9个度为2的结点。( √ )
  6. 中序序列和后序序列相同的二叉树为:空树和缺右子树的单支树。( )

答案:×
中序序列和后序序列相同的二叉树为:空树和任何结点都缺右子树的单支树

  1. 树在计算机内的表示方式有 双亲链表表示法, 孩子链表表示法, 孩子兄弟表示法
  2. 在二叉树中,指针p所指结点为叶子结点的条件是 p->lchild= =null && p->rchild= =null
  3. 中缀式a+b3+4(c-d)对应的前缀式为 ++a×b3×4-cd ,若a=1,b=2,c=3,d=4,则后缀式db/cca-b+的运算结果为 18
  4. 在树的孩子兄弟表示法中,二叉链表的左指针指向 结点的第一个孩子 ,右指针指向 结点的右兄弟
  5. 有数据WG={7,19,2,6,32,3,21,10},则所建Huffman树的树高是 6 ,带权路径长度WPL为 261
  6. 设n0为哈夫曼树的叶子结点数目,则该哈夫曼树共有 2n0-1个结点。

应用题

设一棵二叉树的先序、中序遍历序列分别为
先序遍历序列: ABDFCEGH       中序遍历序列: BFDAGEHC
(1)画出这棵二叉树。
(2)画出这棵二叉树的后序线索树。
(3)将这棵二叉树转换成对应的树(或森林)。

答案:略

算法设计题

  1. 二叉树的带权路径长度(WPL)是二叉树中所有叶结点的带权路径长度之和。给定一棵二叉树T,采用二叉链表存储,结点结构为: left weight right,其中叶结点的weight域保存该结点的非负权值。设root为指向T的根结点的指针,请设计求T的WPL的算法,要求:
    (1)给出算法的基本设计思想
    答:设二叉树根结点的层次为1,在遍历二叉树的函数中増加层次参数,初始值为1。遍历二叉树,在访间结点时若是叶子结点,则求其带权路径长度,将所有叶子结点的带权路径长度相加,即得到二叉树的带权路径长度。
    (2)使用C或C+语言,给出二叉树结点的数据类型定义
typedef struct node
{ int weight;                 //结点的权值,设为整型
struct node *left, *right;       //指向结点左、右子女的指针
}BiNode, *BiTree;

(3)根据设计思想,采用C或C++语言描述算法,关键之处给出注释。

int WPL=0//权路径长度初值为0,是全局变量
void inorder(BiTree bt, level lv)
//bt是二叉树,1y是结点的层次,初值为1,本算法求二叉树bt的带权路径长度
{if(bt)
	{inorder(bt->left, lv+1);              //中序遍历左子树
	if(bt->left==null && bt->right==null)  //判断该结点是否为叶子
		WPL+=(lV-1)*bt->weight;            //累加结点带权路径长度
	inorder(bt->right, lv+1);              //中序遍历右子树
    }
}      
  1. 设计一算法分别求出二元树的叶结点,度数为1的结点,度数为2的结点的个数。
    答:结点计数可以在遍历中解决。根据“访问根结点”、“递归调用左子树”、“递归调用右子树”三者位置的不同,而有前序、后序和中序遍历。叶子结点是左右子女均无的结点,度为1的结点是只有一个子女的结点,度为2的结点是左右子女均有的结点。

  2. 给定一组项及其权值,假定项都存放于二叉树的树叶结点,则具有最小带权外部路径长度的树称为 Huffman树。
    (1)给出构造 Huffman树的算法。

答:哈夫曼树的构造过程:
①根据给定的n个权值{W1,W2,W3,,Wn}构成n棵二叉树的集合F={T1,T2…,Tn},其中
毎棵二叉树Ti只有权值为Wi的根结点,其左右子树均为空。
②在F中选取两棵根结点的权值最小的树作左右子树构造一棵新二叉树,新二叉树根结
点的权值为其左右子树上根结点的权值之和。
③在F中删除这两棵树,同时将新得到的二叉树加入F中。
④重复②和③,直到F中只剩一棵树为止。这棵树便是哈夫曼树。

(2)给定项及相应的权如下表,画出执行上述算法后得到的Huffman树。

序号 1 2 3 4 5 6 7 8 9
A B C D E F G H I
15 6 7 12 25 4 6 1 15

(3)用C语言编写构造 Huffman树的程序。

答:含有n个叶子结点的哈夫曼树共有2n-1个结点,采用静态链表作为存储结构,
设置大小为2n-1的数组。核心语句段如下:
for(i=0; i<2*n-1; i++ )     //置初值,结点的权、左右子女、双亲
	{ T[i].parent=-1; T[i].lc=-1; T[i].rc=-1;
	if (i<n)  T[i].weight=w[i];  else T[i].weight=0; 
	}
for(i=n; i<2*n-1; i++ )                         //构造新二叉树
	{ p1=p2=0;  small1=small2=maxint; 
	//赋初值,p1、p2是最小和次小权值结点的下标
	for(j=0; j<i; j++ )
		if(T[j].weight<small1 && T[j].parent == -1 )        //最小值
			{ p2=p1; small2=small1; pl=j; small1=t[j].weight; }
		else if(T[j].weight<small2 && T[j].parent == -1)      //次小值
			{ p2=j; small2=T[j].weight; } 
	T[i].weight =T[p1].weight+T[p2].weight; }  //合并成一颗新二叉树 
	T[i].lc =p1; T[i].rc=p2;                 //置双亲的左右子女
	T[p1].parent=i;  T[p2].parent=i;         //置左、右子女的双亲

第七章-图

  1. 若无向图G=(V,E)中含有7个顶点,要保证图G在任何情况下都是连通的,则需要的边数最少是( C )。
    A、6 B、15 C、16 D、21

要保证n个顶点的无向图在任何情况下都是连通的,则需要先由n-1个顶点组成完全图,从第n个顶点引一条到n-1任一顶点的边,则图肯定是连通的。本题先由6个顶点组成完全图,需要6(6-1)/2=15条边,故本题需要的最少边数是16条

  1. 下列关于最小生成树的叙述中,正确的是( )。
    Ⅰ、最小生成树的代价唯一
    Ⅱ、所有权值最小的边一定会出现在所有的最小生成树中
    Ⅲ、使用普里姆(Pim)算法从不同顶点开始得到的最小生成树一定相同
    Ⅳ、使用普里姆算法和克鲁斯卡尔( Kruskal)算法得到的最小生成树总不相同
    A、仅Ⅰ         B、仅Ⅱ         C、仅I、Ⅲ         D、仅Ⅱ、Ⅳ

答案:A

  1. 下面AOE网表示一项包含8个活动的工程。通过同时加快若干活动的进度可以缩短整个工程的工期。下列选项中,加快其进度就可以缩短工程工期的是( )
    A、c和e         B、d和c         C、f和d         D、f和h
    数据结构各章考研习题重点总结_第1张图片

答案:C
假设工期单位为天,可以得出工期为27天,有三条路径,分别为1356,13246,13256.想要缩短工期,就必须同时缩小这三条路径上的权重,最优选择当然是缩短b了,可是选项没有,只能退而求其次,同时缩小d和f的权重,故选c

  1. n个顶点的无向图的邻接表最多有( )个表结点。
    A、n2         B、n(n-1)         C、n(n+1)         D、n(n-1)/2

答案:B
邻接表中每条边存储两次,所以有n(n-1)/2条边就有 n(n-1)个结点

  1. 下列表述中,错误的说法是( )。
    A、n个结点的树的各结点度数之和为n-1
    B、n个顶点的无向图最多有n*(n-1)条边
    C、用邻接矩阵存储图时所需存储空间的大小与图的顶点数有关,而与边数无关。
    D、哈希表中冲突的可能性大小与装填因子有关

答案:B
注意A选项是树不是图

  1. 执行( )操作时,需要使用队列作辅助存储空间。
    A、查找哈希(Hash)表           B、广度优先搜索图        
    C、先序(根)遍历二叉树         D、深度优先搜素图

答案:B

  1. 图的BFS生成树的树高比DFS生成树的树高( )。
    A、小或相等         B、小         C、大或相等         D、大

答案:A

  1. 无向图G=(V,E),其中V{a,b,c,d,e,f},E={(a,b),(a,e),(a,c),(b,e),(c,f),(f,d),(e,d)},对该图进行深度优先遍历,得到的顶点序列正确的是( )。
    A、a,b,e,c,d,f         B、a,c,f,e,b,d         C、a,e,b,c,f,d         D、a,e,d,f,c,b

答案:D

  1. 在图采用邻接表存储时,求最小生成树的Prim算法的时间复杂度为()。
    A、O(n)         B、O(n+e)         C、O(n2)         D、O(n3)

答案:B

  1. 在求边稠密的图的最小代价生成树时,采用( )算法较合适。
    A、普里姆(Prim)                     B、克鲁斯卡尔( Kruskal)        
    C、迪杰斯特拉( Dijkstra)         D、其他

答案:A

  1. 已知有向图G=(V,E),其中V={V1,V2,V3,V4,V5,V6,V7},E={,,,,,,,,},G的拓扑序列是
    ( )。
    A、V1V3V4V6V2V5V7           B、V1,V3,V2,V6,V4,V5,V7        
    C、V1,V3,V4,V5,V2,V6,V7         D、V1,V2,V5,V3,V4,V6,V7

答案:A

  1. 在用邻接表表示图时,拓扑排序算法时间复杂度为( )。
    A、O(n) B、O(n+e) C、O(nn) D、O(nn*n)

答案:B

  1. 关键路径是AOE网中( )。
    A、从始点到终点的最短路径 B、从始点到终点的最长路径
    C.从始点到终点的边数最多的路径 D、从始点到终点的边数最少的路径

答案:B

  1. 下列关于AOE网的叙述中,不正确的是( )。
    A、关键活动不按期完成就会影响整个工程的完成时间
    B、任何一个关键活动提前完成,那么整个工程将会提前完成
    C、所有的关键活动提前完成,那么整个工程将会提前完成
    D、某些关键活动若提前完成,那么整个工程将会提前完成

答案:B

  1. 在n个结点的无向图中,若边数>n-1,则该图必是连通图。( × )

这道题反过来的说法是对的,若一个N个结点的连通图,则其边数必大于或等于N-1
该图必是连通图是连通是比较强的条件
以下两种说法是对的:
在n个结点的无向图中,若该图是连通图,则其边数大于等于n-1,
在n个结点的无向图中,若边数大于(n-2)(n-1)/2,该图必是连通图

  1. 有n-1条边的图肯定都是生成树。( × )

  2. 最小代价生成树是唯一的。( )

答案:×。最小生成树是不一定唯一,最小生成树代价唯一

  1. 需要借助于一个队列来实现DFS算法。( )

答案:×。BFS广度优先算法需要借助于一个队列来实现,DFS深度优先算法不需要

  1. AOV网的含义是以边表示活动的网。( )

答案:×。用顶点表示活动,用弧表示活动间的优先关系的有向图称为顶点表示活动的网,简称AOV网。

  1. 在数据结构中,线性结构、树形结构和图形结构数据元素之间分别存在
    一对一一对多多对多 的联系

  2. 有n个顶点的有向图,至少需要 n 条弧才能保证是连通的。

  3. n个顶点e条边的图采用邻接表存储,则空间复杂度是 O(n+e)

  4. 求最短路径的Dijkstra算法的时间复杂度为 O(n2)

算法设计题

设无向图G有n个顶点,m条边。试编写用邻接表存储该图的算法。(设顶点值用1~ n或0~ n-1编号)

邻接表存储结构是顶点向量和顶点的邻接点链表相结合的存储结构。核心语句段如下:
cin>>n>>m;                     //n个顶点和m条边
for(i=0; i<n; i++)             //输入顶点信息,建立定点向量
	{cin>>g[i].vertex;g[i].firstarc=null;}
for(k=0; k<m; k++)             //输入边信息
	{cin>>v1>>v2;              //输入两个顶点
	i=GraphLocateVertex(g,v1); j=GraphLocateVertex(g,v2);  //顶点定位
	p=new(ArcNode);            //申请边结点
	p->adjvex=j; p->next=g[i].firstarc; g[i].firstarc=p;   //将边结点链入
	p=new(ArcNode)(ArcNode);   //申请边结点,链入j到i的一条边
	p->adjvex=i;  p->next=g[j].firstarc; g[j].firstarc=p;
}//for

第十章-排序

客观题

  1. 已知关键字序列5,8,12,19,28,20,15,22是小根堆(最小堆),插入关键3,调整后得到的小根堆是( )
    A、3,5,12,8,28,20,15,22,19         B、3,5,12,19,20,15,22,8,28        
    C、3,8,12,5,20,15,22,28,19         D、3,12,5,8,28,20,15,22,19

答案:A

  1. 希尔排序的组内排序采用的是( )
    A、直接插入排序         B、折半插入排序         C、快速排序         D、归并排序

答案:A

  1. 下列排序算法中,其中()是稳定的。
    A、堆排序,冒泡排序         B、快速排序,堆排序        
    C、直接选择排序,归并排序         D、归并排序,冒泡排序

答案:D

  1. 下列内部排序算法中:
    A、快速排序         B、直接插入排序         C、二路归并排序        
    D、简单选择排序         E、起泡排序         F、堆排序
    (1)其比较次数与序列初态无关的算法是(CD)
    (2)不稳定的排序算法是(ADF)
    (3)在初始序列已基本有序(除去n个元素中的某k个元素后即呈有序,k< 况下,排序效率最高的算法是(B)
    (4)排序的平均时间复杂度为O( nlogn)的算法是(ACF),为O(mn)的算法是(BDE)

  2. 对一组数据(84,47,25,15,21)排序,数据的排列次序在排序的过程中的变化为
    (1) 84 47 25 15 21         (2) 15 47 25 84 21        
    (3) 15 21 25 84 47         (4) 15 21 25 47 84
    则采用的排序是( )。
    A、选择         B、冒泡         C、快速         D、插入

答案:A

  1. ( )占用的额外空间的空间复杂性为O(1)
    A、堆排序算法         B、归并排序算法         C、快速排序算法         D、以上答案都不对

答案:A

  1. 对序列{15,9,7,8,20,-1,4,}用希尔排序方法排序,经一趟后序列变为{15,-1,4,8,20,9,7},则该次采用的增量是()
    A、1         B、4         C、3         D、2

答案:B

  1. 快速排序算法在最好情况下的时间复杂度是()
    A.O(n)         B.O(n^2)         C.O(nlog2n)         D.O(log2n)

答案:C

  1. 归并排序中,归并的趟数是( )
    A.O(n)         B.O(logn)         C.O(nlogn)         D.O(n*n)

答案:B

  1. 内排序要求数据一定要以顺序方式存储。(×)

  2. 排序算法中的比较次数与初始元素序列排序无关。(×)

  3. 排序的稳定性是指排序算法中的比较次数保持不变,且算法能够终止。(×)

  4. 时间复杂度为O(n2)、空间复杂度为O(1)且与文件初始状态无关的排序算法是直接插入排序.( ×)

  5. 由于希尔排序的最后一趟与直接插入排序过程相同,因此前者一定比后者花费的时间更多.( ×)

  6. 对于n个记录的集合进行冒泡排序,在最坏情况下所需要的时间是O(n^2).(√)

  7. 直接选择排序是不稳定排序.(√)

  8. 堆肯定是一颗平衡二叉树.( ×)

  9. 堆是满二叉树.( ×)

  10. 直接选择排序算法在最好情况下所做的交换元素次数为0

  11. 设用希尔排序对数组{98,36,-9,0,47,23,1,8,10,7}进行排序,给出的步长(也称增量序列)依次是4,2,1,则排序需3趟,写出第一趟结束后,数组中数据的排列次序 (10,7,-9,0,47,23,1,8,98,36)

  12. 堆排序的算法时间复杂度为 O(nlog2n)

  13. 在堆排序中,首先需要进行的操作是 建堆

  14. 每次使两个有序表合并成一个有序表,这种排序方法叫做 归并排序

你可能感兴趣的:(数据结构)