派大汤的数据结构错题本

数据结构错题本

  • 数据结构的基本概念
  • 时间、空间复杂度计算
  • 队列

数据结构的基本概念

1.抽象数据类型(Abstract Data Type 简称ADT)是指一个数学模型以及定义在此数学模型上的一组操作。
抽象数据类型=存储结构+运算操作

时间、空间复杂度计算

1.已知两个长度分别为m 和 n 的升序链表,若将它们合并为一个长度为 m+n 的降序链表,则最坏情况下的时间复杂度是(D)。

A.O(n)
B.O(m+n)
C.O(min(m ,n))
D.O(max(m,n))

解答:
核心代码为:

//循环两两比较,小的存入结果
int i=0,j=0;
LinkList L;
InitList(L);
int *q=A->next;	//长为m的表A
int *p=B->next;	//长为n的表B
int *r=L->next;	//长为m+n的升序表L
while(p->next!=NULL && q->next!=NULL){
    if(q->data<p->data)
        r->data=p;
        p=p->next;
    else
       	r->data=q;
       	q=q->next;
    r=r->next;
}
//还剩一个没有比较完的顺序表
while(p->next!=NULL) {
    r.data=p->data;
    r=r->next;
    p=p->next;
}
while(q->next!=NULL)){
    r.data=q->data;
    r=r->next;
    q=q->next;
}

最多比较次数,m+n-1 ()
最少比较次数,min(m,n) (将短表比较完)

根据年计算时间复杂度的原则:

只需找循环中的一个基本操作,分析它的执行次数与n的关系即可,其它的操作影响n的系数。

所以最长的while循环为将长表比较完,不需要管剩下的短表,即O(max(m,n))。

2.一个算法所需时间由下述递归方程表示,试求出该算法的时间复杂度级别(或阶)。

T ( n ) = { 1 n=1 2 T ( n / 2 ) + n n>1 T(n)= \begin{cases} 1& \text{n=1}\\ 2T(n /2)+n& \text{n>1} \end{cases} T(n)={12T(n/2)+nn=1n>1
上式中,n是问题规模,为简单期间,设n是2的整数次幂。

分析:递归的时间复杂度题目一般使用公式递推出第n个式子与第一个式子之间的关系。

解答:
设n= 2 k 2^k 2k(k>0),根据题目所给定义有
T( 2 0 2^0 20)=1
T( 2 1 2^1 21)=2T( 2 0 2^0 20)+ 2 1 2^1 21
T( 2 2 2^2 22)=2T( 2 1 2^1 21)+ 2 2 2^2 22= 2 2 2^2 22T( 2 0 2^0 20)+2* 2 2 2^2 22
T( 2 3 2^3 23)=2T( 2 2 2^2 22)+ 2 3 2^3 23= 2 3 2^3 23T( 2 0 2^0 20)+3* 2 3 2^3 23

T( 2 k 2^k 2k)= 2 k 2^k 2kT( 2 0 2^0 20)+k* 2 k 2^k 2k

又上述递推关系可得:
T(n)= 2 log ⁡ 2 n 2^{\log_{2}{n}} 2log2n+n* log ⁡ 2 n \log_{2}n log2n=O(n* log ⁡ 2 n \log_{2}n log2n)

1 . 假设链表不带头结点且所有操作在表头进行,则下列最不适合作为链栈的是(C)。

A.只有表头结点指针,没有表尾指针的双向循环链表。
B.只有表尾结点指针,没有表头指针的双向循环链表。
C.只有表头结点指针,没有表尾指针的单向循环链表。
D.只有表尾结点指针,没有表头指针的单向循环链表。

解答:考虑最为复杂的删除操作,因为删除操作需要被删除结点以及被删除结点的前驱结点。

A、B:对于双向循环链表,无论表头指针还是表尾指针都可以方便地找到表头结点,在表头进行插入删除操作。

C、D:对于单向循环链表,因为表尾指针是表头指针的前驱,所以可以进行删除表头的操作。但是相反,如果只有表头指针则在寻找表尾指针的时候需要O(n)的复杂度,所以最不适合作为链栈使用。

2.一个栈的入栈序列为1,2,3…n出栈序列为P1,P2,P3…Pn。若P2=3,则P3可能取值的个数为(n-1)。

解答:
当P2为3时,P1可以取的值为1、2、4。

当P1=1时,P3可以取2、4…n。
当P1=2时,P3可以取1、4…n。
当P1=4时,P3可以取2、5…n。

所以综上所述,P3除3外均可取得,为n-1个。

(多选)3.下列关于栈的叙述中错误的是(A、C、D)。

A.采用非递归方式重写递归程序时必须使用栈。
B.函数调用时,必须使用栈保留必要的信息。
C.只要确定入栈序列就可以确定出栈序列。
D.栈是一种操作受限的线性表,允许在表的两端操作。

解答:
A.当计算1到n的和时,可以采用递归程序实现,但是采用非递归方式实现时,不一定需要使用栈。

B.当程序执行时,需要有一个栈来保存函数的执行顺序(下一步要做什么),当某一函数执行完成,则将这个函数返回它的值并从栈中Pop,然后再执行后面的函数。

4.向一个栈顶指针为top的链栈中插入一个x结点,则执行(C)。

A.top->next=x;
B.x->next=top->next;top->next=x;
C.x->next=top;top=x;
D:x->next=top;top=top->next;

解答:

链栈----什么是链栈?用链表实现的栈,物理结构是单链表形式。

单链表的指针方向是如何指示的?由栈顶指向栈底还是栈底指向栈顶?
分析一哈:
第一种情况:由栈底指向栈顶,当元素出栈时,则需要top指针的前驱结点,而由栈底指向栈顶是无法找到这个前驱结点的,所以不是由栈底指向栈顶。

第二种情况:由栈顶指向栈底,可以找到top的后继结点,并置为top,所以是由栈顶指向栈底的。

所以,top可以看做单链表(链栈)的头指针,即使用头插法插入x结点,让x指向top,并让x称为top结点。
x->next=top;x=top;选择 C。

思考:如果链栈的top指针指向栈顶元素的下一个存储空间呢?如何进行插入操作?

我们可以将这个问题转化为带有头结点的链表的插入操作,在头结点之后插入一个结点x,所以操作为
x->next=top->next;top->next=x;

队列

1 . 已知循环队列的存储空间为数组A[21],front 指向队头元素的前一个位置,rear指向队尾元素,假设当前front和rear的值分别为8和3,则该队列的长度为(16)。

解答:求取队列中元素个数问题

  1. 当front与rear指针都分别指向队头、队尾元素时
    队列长度=(rear+1-fornt+maxsie)%maxsize;
  2. 当front与rear指针都分别指向队头、队尾元素下一个位置时
    队列长度=(rear-fornt+maxsie)%maxsize;
  3. 当front与rear指针都分别指向队头元素的上一个位置、队尾元素时
    队列长度=(rear-fornt+maxsie)%maxsize;

注意题干描述:rear指向队尾元素,front指向队头元素的前一个位置。这种情况等价于rear指向队尾元素的下一个元素,front指向队头元素。计算都为:(rear - front + maxsize)%maxsize = 16。

2.已知循环队列存储在一维数组A[0…n-1]中,且队列非空时front与rear分别指向队头元素和队尾元素。若初始时队列为空,且要求第一个进入队列的元素存储在A[0]处,则初始时front与rear的值分别是(0,n-1)。

解答:这个题目考察反推能力。第一个进入的元素既是队列的队头元素又是队尾元素,此时队头指针和队尾指针指向同一个位置,即为0。元素入队的时候front不变,所以front在队列为空时也指向0,而rear会+1,所以rear在队列为空时会指向0的前一个位置 n-1。

3.循环队列放在一维数组A[0…M-1]中,end1指向队头元素,end2指向队尾元素的后一个位置,假设队列两端都可以进行入队和出队的操作,队列中最多能容纳M-1个元素。初始时为空。下列判断队空和队满的条件中,正确的是(A)。

A.队空:end1 == end2; 队满:end1 == (end2+1)mod M
B.队空:end1 == end2; 队满:end2 == (end1+1)mod (M-1)
C.队空:end2 == (end1+1)mod M; 队满:end1 == (end2+1)mod M
D.队空:end1 == (end2+1)mod M; 队满:end2 == (end1+1)mod (M-1)

解答:
先分析队满的情况:一般情况下,end2+1==end1 就可以表示队列已满。但是当end2在队列尾部,end1在队列头部时,要用 mod M(有M个空间) 的方法让end2 回到 队头。所以判断队满的方式为:end1 == (end2+1)mod M。

再分析队空的情况: 当队中只有一个元素时,发现cd选项的判别方法可以认为是队空的条件,也可以是队中只有一个元素的条件。

你可能感兴趣的:(基础学习,数据结构)