线性表题目

目录

一、选择题

二、填空题

三、判断题

四、程序分析填空题

五、综合题


一、选择题

1若长度为n的线性表采用顺序存储结构,在其i个位置插入一个新元素算法的时间复杂度 C  

A. O(log2n)     B.O(1) C. O(n)     D.O(n2)

2、若一个线性表中最常用的操作是取第i个元素和找第i个元素的前趋元素,则采用  A )存储方式最节省时间。

    A. 顺序表        B. 单链表      C.  双链表       D. 单循环链表

3、具有线性结构的数据结构是  D 

A.      B.  C. 广义表     D. 

4、在一个长度为n的顺序表中,在第i个元素之前插入一个新元素时,需向后移动   个元素

A. n-i     B. n-i+1 C. n-i-1     D. i

5、非空的循环单链表head的尾结点p满足   )。

A. p->next==head        B. p->next==NULL    

C.  p==NULL       D. p==head

6、链表不具有的特点是(   

A. 可随机访问任一元素 B. 插入删除不需要移动元素

C. 不必事先估计存储空间 D. 所需空间与线性表长度成正比

7、在双向循环链表中,在p指针所指的结点后插入一个指针q所指向的新结点,修改指针的操作是(   )。

A. p->next=q;q->prior=p;p->next->prior=q;q->next=q;

B. p->next=q;p->next->prior=q;q->prior=p;q->next=p->next;

C. q->prior=p;q->next=p->next;p->next->prior=q;p->next=q;

D. q->next=p->next;q->prior=p;p->next=q;p->next=q;

8、线性表采用链式存储时,结点的存储地址   )。

A. 必须是连续的 B. 必须是不连续的

C. 连续与否均可     D. 和头结点的存储地址相连续

9、在一个长度为n的顺序表中删除第i个元素,需要向前移动(   )个元素

A. n-i   B. n-i+1 C. n-i-1     D. i+1

10线性表是n个   的有限序列具有相同特性的数据元素的一个有限序列。

A. 表元素 B. 字符 C. 数据元素 D. 数据项

11从表中任一结点出发,都能扫描整个表的是   

A. 单链表     B. 顺序表 C. 循环链表     D. 静态链表 这种存储结构,仍需要预先分配一个较大的空间,但在作为线性表的插入和删除操作时不需移动元素,仅需修改指针,故仍具有链式存储结构的主要优点。

12在具有n个结点的单链表上查找值为x的元素时,其时间复杂度为(   )

A. O(n)     B. O(1)       C. O(n2)      D. O(n-1)

13、线性表L=(a1,a2,……,an),下列说法正确的是   

A. 每个元素都有一个直接前驱和一个直接后继    

B. 线性表中至少要有一个元素

C. 表中诸元素的排列顺序必须是由小到大或由大到小

D. 除第一个和最后一个元素外,其余每个元素都由一个且仅有一个直接前驱和直接后继

14、一个顺序表的第一个元素的存储地址是90,每个元素的长度为2,则第6个元素的存储地址是   

A. 98     B. 100 存储地址是元素开始地址,而非结束地址 C. 102     D. 106

15、在线性表的下列存储结构中,读取元素花费的时间最少的是   )。

    A. 单链表       B. 双链表     C. 循环链表       D. 顺序表 有随机存储特性

16、在一个单链表中,若删除p所指向结点的后续结点,则执行(   

A. p->next=p->next->next;

B. p=p->next;p->next=p->next->next;

C. p =p->next;

D. p=p->next->next;

17、将长度为n的单链表连接在长度为m的单链表之后的算法的时间复杂度为   只要把接入的链表遍历一遍找到其最后一个即可。

A. O(1) B. O(n) C. O(m) D. O(m+n)

18、线性表的顺序存储结构是一种   存储结构

A. 随机存取 B. 顺序存取 C. 索引存取 D. 散列存取

19、顺序表中,插入一个元素所需移动的元素平均数是   )。

    A. (n-1)/2       B. n     C. n+1       D. (n+1)/2

20循环链表的主要优点是   )。

A. 不再需要头指针         B. 已知某结点位置后能容易找到其直接前驱 

C. 在进行插入、删除运算时能保证链表不断开 

D. 在表中任一结点出发都能扫描整个链表

21不带头结点的单链表head为空的判定条件是 A  )。

A. head==NULL               B.head->next==NULL    

C. head->next==head            D. head!=NULL

答案B是带头结点的

22、在下列对顺序表进行的操作中,算法时间复杂度为O(1)的是   

A. 访问第i个元素的前驱(1<=i<=n B. 在第i个元素之后插入一个新元素(1<=i<=n)

C. 删除第i个元素(1<=i<=n) D. 对顺序表中元素进行排序

答案是A.

顺序表L,长度为n,求第i个节点L[i],直接前驱L[i-1],因此为O(1)

答案B需要移动n-i+1个节点,因此为O(n)

答案C也需要移动n-i个节点

答案D根据排序方法不同最慢O(n^2),最快O(nlogn)

23、已知指针p和q分别指向某单链表中第一个结点和最后一个结点。假设指针s指向另一个单链表中某个结点,则在s所指结点之后插入上述链表应执行的语句为(   )

A. q->next=s->next;s->next=p;     

B. s->next=p;q->next=s->next;      

C. p->next=s->next;s->next=q;    

D. s->next=qp->next=s->next

24、在以下的叙述中,正确的是  )

A. 线性表的顺序存储结构优于链表存储结构

B. 线性表的顺序存储结构适用于频繁插入/删除数据元素的情况

C. 线性表的链表存储结构适用于频繁插入/删除数据元素的情况

D. 线性表的链表存储结构优于顺序存储结构

25、在表长为n的顺序表中,当在任何位置删除一个元素的概率相同时,删除一个元素所需移动的平均个数为   )。

A. (n-1)/2       B. n/2     C. (n+1)/2 D. n

26、在一个单链表中,已知q所指结点是p所指结点的前驱结点,若在q和p之间插入一个结点s,则执行   )。

A. s->next=p->next; p->next=s;              

B. p->next=s->next;s->next=p;  

C. q->next=s;s->next=p;            

D. p->next=s;s->next=q;

27、在单链表中,指针p指向元素为x的结点,实现删除x的后继的语句是(   )

A. p=p->next;     B. p->next=p->next->next;   

C. p->next=p; D. p=p->next->next;

28在头指针为head且表长大于1的单循环链表中,指针p指向表中某个结点,若p->next->next==head,则   )。

A. p指向头结点 B. p指向尾结点 C. p的直接后继是头结点 D. p的直接后继是尾结点 p是倒数第二个节点

二、填空题

1设单链表的结点结构为(data,next)。已知指针p指向单链表中的结点,q指向新结点,欲将q插入到p结点之后,则需要执行的语句:                                   

答案:q->next=p->next   p->next=q

2线性表的逻辑结构是          ,其所含元素的个数称为线性表的        

答案:线性结构  长度

3、写出带头结点的双向循环链表L为空表的条件                  

答案:L->prior==L->next==L

4、带头结点的单链表head为空的条件是           

答案:head->next==NULL

5、在一个单链表中删除p所指结点的后继结点时,应执行以下操作:

q = p->next;

p->next= q->next;

三、判断题

1、单链表不是一种随机存储结构O

单链表是一种顺序存储结构,其中的每个元素都是一个节点,每个节点存储了元素的值和一个指向下一个节点的指针。因此,在单链表中存储的元素按照它们在表中的顺序存储。与随机存储结构不同,随机存储结构允许在任意位置读取元素,而单链表则需要从表头开始遍历整个表。 

2、在具有头结点的单链表中,头指针指向链表的第一个数据结点X

头指针指向头节点,Head指针为单链表的头指针,单链表L:L既是单链表的名字,也是其头指针

3、用循环单链表表示的链队列中,可以不设队头指针,仅在队尾设置队尾指针。O

用循环单链表表示的链队列中,因为队头和队尾相接,所以仅在队尾设置队尾指针即可遍历整个队列。队头指针不再需要,因为可以通过队尾指针确定队头。在循环单链表的链队列中,队头和队尾指针始终都在不断变化,因此在加入和删除元素时只需要更改相应的指针。这种方法可以避免在普通单链表的链队列中的固定队头和队尾指针造成的困难,即当队列为空时无法删除任何元素。

4、顺序存储方式只能用于存储线性结构X

顺序存储方式通常用于存储线性结构,例如数组和队列。但它也可以用于存储非线性结构,例如树和图。

5、在线性表的顺序存储结构中,逻辑上相邻的两个元素但是在物理位置上不一定是相邻的X

6、链式存储的线性表可以随机存取X

链式存储的线性表的每个节点只能通过链接前驱节点或后继节点来访问,不能通过下标或其他方式随机访问。

四、程序分析填空题

1、函数GetElem实现返回单链表的第i个元素请在空格处将算法补充完整

int GetElem(LinkList L,int i,Elemtype *e){
		LinkList p;int j;
p=L->next;j=1;
		while(p&&ji)  return ERROR;
*e=       (2)     ;
return OK;
}

答案:(1)p=p->next     (2)p->data

2、函数实现单链表的插入算法请在空格处将算法补充完整

int ListInsert(LinkList L,int i,ElemType e){
    LNode *p,*s;int j;
  	p=L;j=0;
  	while((p!=NULL)&&(jnext;j++;
	}
  	if(p==NULL||j>i-1) return ERROR;
  	s=(LNode *)malloc(sizeof(LNode));  
  	s->data=e;
  	      (1)           ;                
  	      (2)          ;
  	return OK;
}/*ListInsert*/

答案:(1)s->next=p->next    (2)p->next=s

3、函数ListDelete_sq实现顺序表删除算法请在空格处将算法补充完整

int ListDelete_sq(Sqlist *L,int i){
    int k;
    if(i<1||i>L->length) return ERROR;
for(k=i-1;klength-1;k++) 
L->slist[k]=    (1)      ;
           (2)       ;                       
    return OK;
}
答案:(1)L->slist[k+1]     (2) --L->Length  

4、函数实现单链表的删除算法请在空格处将算法补充完整

int ListDelete(LinkList L,int i,ElemType *s){
    LNode *p,*q;
    int j;
    p=L;j=0;
    while((      (1)     )&&(jnext;j++;
    }
    if(p->next==NULL||j>i-1) return ERROR;
    q=p->next;                  
           (2)          ;
    *s=q->data;
    free(q);
    return OK;
}/*listDelete*/
答案:(1)p->next!=NULL    (2)p->next=q->next
注意默认都是具备头节点的

5、写出算法的功能

int L(head){
		node * head;
		int n=0;
		node *p;
		p=head;
		while(p!=NULL)
		{ p=p->next;
		   n++;
		 }
		return(n);
	}
答案:求单链表head的长度

五、综合题

1、编写算法,实现带头结点单链表的逆置算法

答案:void invent(Lnode *head)
    {Lnode *p,*q;
     if(!head->next) return ERROR;
     p=head->next; q=p->next; p->next =NULL;
     while(q)
         {p=q; q=q->next; p->next=head->next; head->next=p;}
    }



void ReverseList(ListLNode *L)
{
    ListLNode *p, *q;
    p = L -> next;
    L->next = NULL;
    while (p != NULL)
    {
        q = p->next;
        p->next = L->next;
        L->next = p;
        p = q;
    }
}

 2、有两个循环链表,链头指针分别为L1和L2,要求写出算法将L2链表链到L1链表之后,且连接后仍保持循环链表形式

答案:void merge(Lnode *L1, Lnode *L2)
    {Lnode *p,*q ;
     while(p->next!=L1)
p=p->next;
while(q->next!=L2)
q=q->next;
q->next=L1; p->next =L2;
    }



void ConcatList(ListLNode *L1, ListLNode *L2)
{
    ListLNode *p = L1 -> next;
    while (p -> next != L1)
    {
        p = p->next;
    }
    p->next = L2 -> next;
    p = p->next;
    while (p->next != L2)
    {
        p = p->next;
    }
    p->next = L1;
}

3、设一个带头结点的单向链表的头指针为head,设计算法,将链表的记录,按照data域的值递增排序。

答案:void assending(Lnode *head)
    {Lnode *p,*q , *r, *s;
     p=head->next; q=p->next; p->next=NULL;
     while(q)
{r=q; q=q->next;
if(r->data<=p->data) 
{r->next=p; head->next=r; p=r; }
else
{while(!p && r->data>p->data)
{s=p; p=p->next; }
r->next=p; s->next=r;}
p=head->next; }
    }


void sortList(LinkList *head)
{
    LinkList *p, *q;
    int temp;
    if (head->next == NULL || head->next->next == NULL)
        return;
    for (p = head->next; p->next != NULL; p = p->next) {
        for (q = p->next; q != NULL; q = q->next) { //每一轮循环都会把后面最小的换到前面
            if (p->data > q->data) {
                temp = p->data;
                p->data = q->data;
                q->data = temp;
            }
        }
    }
}

4、编写算法,将一个头指针为head不带头结点的单链表改造为一个单向循环链表,并分析算法的时间复杂度。

答案:
void linklist_c(Lnode *head)
    {Lnode *p; p=head;
     if(!p) return ERROR;
while(p->next!=NULL)
p=p->next;
p->next=head;
    }



void changeToCycleList(LinkList *head) {
    LinkList *p = head;
    while (p->next != NULL) {
        p = p->next;
    }
    p->next = head;
}

设单链表的长度(数据结点数)为N,则该算法的时间主要花费在查找链表最后一个结点上(算法中的while循环),所以该算法的时间复杂度为O(N)。

5、已知head为带头结点的单循环链表的头指针,链表中的数据元素依次为(a1,a2,a3,a4,…,an),A为指向空的顺序表的指针。阅读以下程序段,并回答问题:

(1)写出执行下列程序段后的顺序表A中的数据元素;

(2)简要叙述该程序段的功能。

if(head->next!=head)
{
p=head->next;
A->length=0;
while(p->next!=head)
{
p=p->next;
A->data[A->length ++]=p->data;
if(p->next!=head)p=p->next;
}
}

答案:
 (1)  (a2, a4, …, )   (2)将循环单链表中偶数结点位置的元素值写入顺序表A

6、设顺序表va中的数据元数递增有序。试写一算法,将x插入到顺序表的适当位置上,以保持该表的有序性。

答案:
void Insert_sq(Sqlist va[], ElemType x)
    {int i, j, n;
     n=length(va[]);
     if(x>=va[i])
va[n]=x;
else
{i=0;
while(x>va[i]) i++;
for(j=n-1;j>=I;j--)
va[j+1]=va[j];
va[i]=x; }
n++;
    }


void insert_sort_list(int va[], int &n, int x) {
    int i;
n=length(va[]);
    for (i = n - 1; i >= 0 && va[i] > x; i--)
        va[i + 1] = va[i];
    va[i + 1] = x;
    n++;
}

7、假设线性表采用顺序存储结构,表中元素值为整型。阅读算法f2,设顺序表L=(3,7,3,2,1,1,8,7,3),写出执行算法f2后的线性表L的数据元素,并描述该算法的功能。

void f2(SeqList *L){  
int i,j,k;
k=0;
for(i=0;ilength;i++){  
for(j=0;jdata[i]!=L->data[j];j++);
   			if(j==k){ 
if(k!=i)L->data[k]=L->data[i];
   				k++;
   			}
}
L->length=k;
}

答案:
 (3,7,2,1,8)  删除顺序表中重复的元素
在算法f2中,第二个if语句的条件k!=i的作用是判断k和i的值是否相等,
如果相等,说明该元素不需要再被复制到表中;如果不相等,则说明该元素在表中不存在,
需要将该元素复制到表的第k个位置。具体地,在算法f2中,首先从前往后遍历整个线性
表L,并且用k变量记录表L中去重后的元素数。在内层循环中,使用j从0到k-1遍历去重
后的元素,并判断当前元素是否与表L中去重后的元素相等。如果该元素在表L中不存在,
则该元素为表L中的一个新元素,将其复制到表的第k个位置。

8、已知线性表中的元素以值递增有序排列,并以单链表作存储结构。试写一算法,删除表中所有大于x且小于y的元素(若表中存在这样的元素)同时释放被删除结点空间。

答案:

void Delete_list(Lnode *head, ElemType x, ElemType y)
    {Lnode *p, *q;
     if(!head) return ERROR;
p=head; q=p;
while(!p) 
{if(p->data>x) && (p->datanext; free(p); 
p=head; q=p; }
else
{q->next=p->next; free(p);
p=q->next; }
else
{q=p; p=p->next; }
            }
    }


void deleteRange(struct Node **head, int x, int y) {
    struct Node *p = *head, *pre = NULL;
    while (p && p->val < x) {  
// 找到第一个值大于等于x的结点p,以及p前面的结点pre
        pre = p;
        p = p->next;
    }

    struct Node *q = p, *pre_q = pre;
    while (q && q->val < y) {  
// 找到第一个值大于等于y的结点q,以及q前面的结点pre_q
        pre_q = q;
        q = q->next;
    }

    while (p != q) {  
// 从pre的后继结点开始遍历链表,删除所有值大于x且小于y的结点,并释放它们的空间
        struct Node *temp = p;
        p = p->next;
        free(temp);
    }
    pre->next = q;  // 将pre的后继结点设为q
    if (pre == NULL) {  // 若删除的是头结点,则需更新表头
        *head = q;
    }
}

9、在带头结点的循环链表L中,结点的数据元素为整型,且按值递增有序存放。给定两个整数a和b,且a

#include 
#include 

struct Node {
    int val;
    struct Node* next;
};

void delete_range(struct Node** head, int a, int b) {
    struct Node* p = (*head)->next;
    struct Node* pre = *head;

    while (p != *head && p->val <= a) {
        pre = p;
        p = p->next;
    }

    struct Node* q = p;
    struct Node* pre_q = pre;

    while (q != *head && q->val < b) {
        pre_q = q;
        q = q->next;
    }

    while (p != q) {
        struct Node* temp = p;
        p = p->next;
        free(temp);
    }

    if (p->val < b) {
        pre->next = q;
    } else {
        pre->next = p;
        p = p->next;
    }

    *head = pre;
}

int main() {
    // 创建一个带头结点的循环链表,并初始化一些数据
    struct Node* head = (struct Node*) malloc(sizeof(struct Node));
    head->next = head;  // 将头结点的next指针指向自己
    struct Node* tail = head;  // tail指向尾结点

    int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int n = sizeof(data) / sizeof(int);

    for (int i = 0; i < n; i++) {
        struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
        new_node->val = data[i];
        new_node->next = head;
        tail->next = new_node;
        tail = new_node;
    }

    printf("Original list:\n");
    struct Node* p = head->next;
    while (p != head) {
        printf("%d ", p->val);
        p = p->next;
    }
    printf("\n");

    int a = 3, b = 8;
    delete_range(&head, a, b);

    printf("List after deleting nodes with values between %d and %d:\n", a, b);
    p = head->next;
    while (p != head) {
        printf("%d ", p->val);
        p = p->next;
    }
    printf("\n");

    // 释放链表的空间
    p = head;
    while (p != NULL) {
        struct Node* temp = p;
        p = p->next;
        free(temp);
    }

    return 0;
}

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