线性表(3)--习题

来源:互联网 发布:腾讯大数据 会 11.22 编辑:程序博客网 时间:2024/05/19 02:44

1.带头结点的单链表head为空的判断条件是(B)

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

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


2.不带头结点的单链表head为空的条件是(A)

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

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


3.在一个单链表中的p所指结点之前插入结点s,可执行如下操作:

s->next=p->next;

p->next=s;

t=p->data;

p->data=s->data;

s->data=t;


4.下面是将不带头结点的链表L逆置的程序,请将程序补充完整。

void invert(Node *L){Node *p,*q,*r;p=L;q=p->next;while(q!=NULL){<u>r=q->next;q->next=p;</u>p=q;q=r;}L->next=NULL;L=p;}


5.请编写一个带头结点的链表L逆置的程序。

void invert(Node *L){Node *p,*q,*r;p=L;q=NULL;while(p!=NULL){r=p;p=p->next;r->next=q;q=r;}L=q;}


6.设线性表有n元素,以下操作中,哪些在顺序表上实现比在链表上实现效率高

(1)输出第i(1<=i<=n)个元素值【顺序表O(1),链表O(n)】

(2)交换第1个和第2个元素值【同为O(1)】

(3)顺序输出这n个元素值【同为O(n)】

(4)输出与给定x相等的元素在线性表中的序号【同为O(n)】


7.设计一个算法int increase(LinkList *L),判断带头结点的单链表L是否是递增的,若是返回1,否则返回0。

int increase(LinkList *L){LinkList *p;ElemType e;p=L->next;//p是第一个结点 e=p->data;//e是第一个结点的 数据 p=p->next;//p是第二个结点 while(p){if(e<p->data){//e小于后继结点的数据 e=p->data;p=p->next;}elsebreak;}if(!p)return 1;//p==NULL,即循环至链表尾 elsereturn 0;


8.设计算法将值x以结点的形式,插入到已知不带头结点的单链表L中。要求插到一个与给定值(k)相匹配的结点的直接前驱位置上。若找不到与k相匹配的结点,则将x插入链表的尾部。其结点结构如图所示。



完整代码:

#include <stdio.h>#include <stdlib.h>typedef struct LNode{int data;struct LNode *next;}LNode,*LinkList;LinkList insert(LinkList L,int x,int k);int main(){LinkList L=NULL,p,tail=NULL,LL=NULL;int i;for(i=0;i<4;i++){p=(LinkList)malloc(sizeof(LNode));scanf("%d",&p->data);p->next=NULL;if(L==NULL){L=p;tail=L;}else{tail->next=p;tail=p;}}LL=insert(L,5,3);while(LL){printf("%d ",LL->data);LL=LL->next;}return 0;} LinkList insert(LinkList L,int x,int k){LinkList newdata,temp,pre;newdata=(LinkList)malloc(sizeof(LNode));newdata->data=x;if(L==NULL)L=newdata;else{temp=L->next;pre=L;while(temp!=NULL&&temp->data!=k){temp=temp->next;pre=pre->next;}if(temp==NULL)pre->next=newdata;else{pre->next=newdata;newdata->next=temp;}}return L;}

测试运行:



9.设有序表(递增)以带表头结点的单链表存储。请设计一个函数,实现在该表中插入一个新元素的操作。要求插入后仍为有序表。其结点结构如图所示。

代码:

typedef struct LNode{int data;struct LNode *next;}LNode,*LinkList;LinkList insert(LinkList L,int x){LinkList newdata,p;newdata=(LinkList)malloc(sizeof(LNode));newdata->data=x;p=L->next;while(p){if(p->data>x){newdata->next=p;p=newdata;return L;}p=p->next;}p=newdata;newdata->next=NULL;return L;}


10.如果一个线性表既能够较快的查找,又能适应动态变化的要求,可以采用下列哪一种查找方法(D)

A.分块 B.顺序C.折半D.哈希


顺序查找是最基本的查找方法,对线性表内的元素从前到后逐个比较,直到找到目标元素。顺序查找的效率较低,但是能够适应增加(删除)元素的要求。

折半查找对线性表的元素大小顺序有要求,需要预先排序。折半查找的效率较高,为olog2n),但是对动态变化的适应性差。增加元素会要求进行一次重新排序。

分块查找的效率介于顺序查找和折半查找,它吸收了折半查找的思想,同时能够基本适应动态变化。

哈希查找的效率较高,为o(1),同时能够满足动态变化的要求。


11.编写逆向输出的不带头结点的单向链表中数据域的递归算法。

void PRINT(LinkList L){if(L->next!=NULL){PRINT(L->next);printf("%d ",L->data);}}


12.编写一个递归算法,删除单链表中所有值为x的结点。

void delete(LinkList L,int x){if(L->next==NULL)return;if(head->next->data==x){head->next=head->next->next;delete(head,x);}elsedelete(head->next,x);}


13.将长度为n的单链表接到长度为m的单链表后面的时间复杂度为(C)

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


只需要将长度为n的链表头接到长度为m的单链表尾上,这个时间复杂度为O(1),但是从长度为m的单链表头查找到其链表尾需要的时间复杂度为O(m),故总的时间复杂度为O(m)。


14.设A为递增有序的单链表(长度为n),B为递减有序的单链表(长度为m),编写程序,利用原表的存储空间,将A和B合并成一个递增有序的单链表,要求时间复杂度为O(m+n),并写出算法思想。


首先将B倒转过来,使其也成为一个递增有序的单链表

void reverse(LinkList L)//不带头结点{LinkList p,q,r;p=L; q=NULL;while(p){<span style="white-space:pre"></span><span style="font-family:Arial, Helvetica, sans-serif;">r=p;</span>p=p->next;r->next=q;q=r;}L=q;}

下一步就是合并两个递增有序的单链表:

LinkList merge(LinkList a,LinkList b){LinkList s,r,p=a,q=b;//s为新链表表头,r为新链表的当前最后一个结点//先确定新链表表头的归属,剩下的只需比较大小插入表尾 if(p->data<=q->data){//p中数据小 s=p;r=p;p=p->next;}else{s=q;r=q;q=q->next;} while(p&&q) {//将较小的一方插入至表尾,直到一方结束 if(p->data<=q->data){//p中数据小 r->next=p;p=p->next;}else{//类似上面 r->next=q;q=q->next;}}if(!p){//p先结束 r->next=q;}else{//q先结束 r->next=q;}return s;}

最后合并一下:

LinkList func(LinkList a,LinkList b){LinkList result;reverse(b);result=merge(a,b);return result;}


15.建立一个数组链表,数组A的元素个数为7,每个元素存放一个指向链表的指针。随机生成50个50以内的正整数,对每个数n,求m=n%7。将n插入到数组A[m]所指向的链表中。此链表中的所有元素要求从小到大排序。


分析:随机函数int Random(int i)返回0-i之间的随机数,每次只需将该数对应的结点插入到数组中的某个元素起始的序列中即可。函数void inser(LinkList top,LinkList input)即在以top为起始点的序列中插入input结点的操作,为保证有序采取的是直接插入排序。

typedef struct LNode{int data;struct LNode *next;}LNode,*LinkList;LinkList A[7];void init(){int i;for(i=0;i<7;i++){A[i]=(LinkList)malloc(sizeof(LNode));A[i].data=0;//初始化,A[i]头结点数据域为iA[i].next=NULL;}}void insert(LinkList top,LinkList input){LinkList current,pre;pre=top;current=top->next;if(!current){//第一次插入 current=input; }while(current){if(input->data<current->data){pre=current;current=current->next;}else{//将input插在pre和current之间 pre->next=input;input->next=current;return;}}current=input;//input的数据比链表已有数据都大 pre->next=current;}void func(){int num,i;LinkList newdata;for(i=0;i<50;i++){num=Random(50);//产生随机数 newdata=(LinkList)malloc(sizeof(LNode));newdata->data=num;newdata->next=NULL;insert(A[num%7],newdata);}}

16.假设用链表表示八进制数,如八进制数536被表示为下面链表:


要求写一个函数Add,它有两个参数P和Q,分别指向表示八进制的链表。执行函数调用Add(P,Q)后,将返回表示P八进制数加Q八进制数所得数的链表R。例如,假设再有P链表:


则执行Add(P,Q),结果应返回下面链表:



17.在某商店仓库中,欲对电视机按其价格从低到高的次序构造一个头指针为head的、不带表头结点的单循环链表,链表的每个结点指出同样价格的电视机的台数。现有m台价格为n元的电视机入库,试编写出仓库电视机的进货算法。

链表的结点类型为:

typedef struct list{float price;int num;struct list *next;}LinkList;


分析:可以分如下几个情况考虑:

情况1:如果仓库为空,进入一批货后,我们建立一个有一个结点的循环链表;

情况2:如果仓库中没有该价格的电视机(仓库非空),则需要在链表中的一定位置插入一个结点;

情况3:仓库中有该价格的电视机,则直接在相应结点上加上新进货的台数。

void addlist(int m,int n,LinkList *head){LinkList p,q;if(!head){p=(*LinkList)malloc(sizeof(LinkList));p->price=n;p->num=m;p->next=head;head=p;return;}//情况1q=head;if(head->price>n){p=(*LinkList)malloc(sizeof(LinkList));p->price=n;p->num=m;p->next=head;head=p;return;} //插入的价格小于链表第一个元素while(n>=q->price){if(n==q->price){q->num=q->num+m;return;}//情况3 r=q->next;if(n<r->price||r->price<q->price){p=(*LinkList)malloc(sizeof(LinkList));p->price=n;p->num=m;q->next=p;p->next=r;return;//情况2 }q=q->next;} }


18.已知一个带有表头结点的单链表,结点结构为,假设该链表只给出了头指针list。在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点(k为正整数)。若查找成功,算法输出该结点的data域的值,并返回1;否则,只返回0.要求:

(1)描述算法的基本设计思想;

(2)描述算法的详细实现步骤;

(3)根据设计思想和实现步骤,编写算法,关键之处给出简要注释。


(1)从头至尾遍历单链表,并用指针p指向当前结点的前k个结点。当遍历到链表的最后一个结点时,指针p所指向的结点即为所查找的结点。

(2)增加两个指针变量和一个整型变量,从链表头向后遍历,其中p1指向当前遍历的结点,指针p指向p1所指向结点的前k个结点,如果p1之前没有k个结点,那么p指向表头结点。用整型变量i表示当前遍历了多少个结点,当i>k时,指针p随着每次遍历,也向后移动一个结点。当遍历完成时,p或者指向表头结点,或者指向链表中倒数第k个位置上的结点。

(3)算法描述

int LocateElement(LinkList list,int k){p1=list->link;p=list;i=1;while(p1){p1=pi->link;i++;if(i>k){p=p->next;//如果i>k,则p也往后移 }}if(p==list)return 0;//说明链表没有k个结点 else{printf("%d\n",p->data);return 1;}}



0 0
原创粉丝点击