c语言之链表编程
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2.1 试描述头指针、头结点、开始结点的区别,并说明头指针和头结点的作用。
头指针:存放链表首地址的指针变量。头结点:链表的开始结点之前的一个同类型结点。开始结点:链表的第一个元素所在的结点。
头指针的作用:用于确定链表的地址。头结点的作用:方便于处理开始结点的操作和处理其它结点的操作保持一致,也方便于处理空表的操作和处理非空表的操作保持一致。
2.2 有哪些链表可由一个尾指针来唯一确定?即从尾指针出发能访问链表上任何一个结点。单循环链表,双链表,双循环链表
2.3 设线性表存放在向量A[arrsize]的前elenum个分量中,且递增有序。试写一算法,将x 插入到线性表的适当位置上,以保持线性表的有序性。并且分析算法的时间复杂度。
#define arrsize 100
int InsertOrder(int A[], int elenum, int x)
{ int i=elenum-1;
if (elenum==arrsize) //在顺序表上进行插入操作必须先判满
{ printf(“full”);
return 0;
}
while (i>=0&&A[i]>x)
{ A[i+1]=A[i];
i--;
} //从后往前进行比较,比较的同时完成移动
A[i+1]=x;
elenum++;
return elenum; //返回变化之后的表长
} //本题也可以先进行比较,比较的结果就是找到了插入的合适位置,然后再完成插入操作。但这样做比较耗时。
假设n=elenum,则时间复杂度:最坏O(n),最好O(1),平均O(n)
2.4 用向量作存储结构,试设计一个算法,仅用一个辅助结点,实现将线性表中的结点循环右移k位的运算,并且分析算法的时间复杂度。
void MoveKList(int a[],int n,int k)
{ int i, j, temp;
for (i=1; i<=k; i++) //外层for循环控制循环右移的次数i
{ temp=a[n-1]; //把表尾元素保存到辅助结点变量temp中
for (j=n-2; j>=0; j--)
a[j+1]=a[j]; //内层for循环完成一次整体右移一位
a[0]=temp; //把原来的表尾元素移至表头
}
}
时间复杂度T(n) = k*n = O(n)
2.5 已知带头结点的动态单链表L中的结点是按整数值递增排列的,试写一算法将值为x的结点插入表L中,使L仍然有序。
typedef int datatype;
typedef struct node
{ datatype data;
struct node *next;
} linklist; //linklist结构体类型描述
void InsertListOrder(linklist *L, datetype x)
{ linklist *p=L; //对寻位指针p初始化
linklist *s=(linklist *)malloc(sizeof(linklist)); //使用强制类型转换将新结点的地址赋给指针s s->data=x;
while((p->next)&&(p->next->data p=p->next; //后移寻位指针 s->next=p->next; p->next=s; } //本题也可以采用两个寻位指针p和q,让q始终跟随p的后移而后移。 2.6 设计一算法,逆置带头结点的动态单链表L。 typedef int datatype; typedef struct node { datatype data; struct node *next; } linklist; void Reverse(linklist *L) { linklist *p,*q; p=L->next; q=L->next; L->next=NULL; while(q) { q=q->next; p->next=L->next; L->next=p; p=q; } } //用指针q遍历结点,指针p跟随指针q,使用头插法把当前结点*p插入到修改之后的单链表中。 2.7 试编写在带头结点的动态单链表和静态单链表上实现线性表操作Length(L)的算法,并将长度写入头结点的数据域中。 (1) typedef int datatype; typedef struct node { datatype data; struct node *next; } linklist; void Length1(linklist *L) { linklist *p=L-next; int i=0; while(p) { i++; p=p->next; } L->data=i; //按照题目要求,将表长写入头结点的数据域中。 } (2) #define maxsize 1024 typedef int datatype; typedef struct { datatype data; int next; } node; node nodepool[maxsize]; void Length2(int L) { int i=0, p=nodepool[L].next; while(p) { i++; p=nodepool[p].next; } nodepool[L].data=i; } 2.8 假设有两个按元素值递增有序排列的线性表A和B,均以单链表①作存储结构,试编写算法将A表和B表归并成一个按元素值递减有序(即非递增有序,允许值相同)排列的线性表C,并要求利用原表(即A表和B表)的结点空间存放表C。①今后若不特别指明,链表均是指动态链表,且可以带头结点。 typedef int datatype; typedef struct node { datatype data; struct node *next; } linklist; linklist *Connect ( linklist *A, linklist *B ) { linklist *C, *p, *q, *r; C=A; //C为最后返回的链表头指针 p=A->next; //p总是指向链表A中当前正在比较的结点 q=B->next; //q总是指向链表B中当前正在比较的结点 C->next=NULL; //置空链表C while(p&&q) //当链表A和链表B中还有没比较的结点时 { if (p->data { r=p; p=p->next; } else { r=q; q=q->next; } //r总是指向*p和*q二者中数据较小的结点 r->next=C->next; C->next=r; //将*r按照头插法插入到链表C中