通过复习题 对单链表 在进行一下熟悉,巩固。先看看有那些题:
1.设计将单链表L2连接在单链表L1后面的算法;
2.设计无头结点的单链表的删除算法;
3.设计无头结点的单链表的插入算法;
5.设计无头结点的单链表的逆置算法;
6.设计单链表的逆置算法;
在做这些题之前我们需要把单链表创建出来 我们分别创建出 有头结点的单链表和无头结点的单链表,代码如下:
定义单链表结点类型:
/*定义单链表结点*/
typedef struct Node{
int data; //数据域
struct Node * next; //指针域
}Node,*PNode;
创建有头结点的:
//创建带头结点的单链表
PNode Create(int * a,int Length){
PNode head,p,q;
head = (PNode)malloc(sizeof(Node));
head->next = NULL;
p = head;
for(int i = 0;i < Length;i++){
q = (PNode)malloc(sizeof(Node));
q->data = a[i];
q->next = NULL;
p->next = q;
p = q;
}
return head;
}
创建无头结点的:
//创建不带头结点的单链表
PNode nCreate(int * b,int Length){
PNode node,p,q;
if(Length > 0){
node = (PNode)malloc(sizeof(Node));
node->data = b[0];
node->next = NULL;
p = node;
for(int i = 1;i < Length;i++){
q = (PNode)malloc(sizeof(Node));
q->data = b[i];
q->next = NULL;
p->next = q;
p = q;
}
return node;
}
}
1.设计将单链表L2连接在单链表L1后面的算法;
思路:题意就是将两个链表拼接起来。这就很简单了,在生活当中 如果我们想把两条线 连接成一条线,肯定是将一条线的尾部 和一条线的头部进行连接,这种思路在我们这个题中也是管用的。看代码:
//1.设计将单链表L2连接在单链表L1后面的算法
void ConnectList(PNode L1,PNode L2){
PNode p;
p = L1;
while(p->next != NULL){ //循环找到 L1 的尾部
p = p->next;
}
p->next = L2->next; //尾部和头部相连
}
2.设计无头结点的单链表的删除算法;
思路:删除链表中一个元素,我一开始的思路是寻找到 所删结点的前一个结点,然后再把所删结点的前一个结点的指针域设置成 所删结点的指针域。但是这样会遇到一个困难就是删除第一个无法实现,我这个思路适合有头街点的单链表。后来转化了一下思路 ,把删除元素换一种理解就是:你在单链表中找不到 你删除的那个值,怎么让他找不到呢?简单一些就是让 后面结点的数据域覆盖 所删结点的数据域,把所删结点的指针域设置成后面结点的指针域。就很完美的 完成了删除操作。又有一个问题就是遇到最后一个结点怎么办?我们还需要一个临时变量记录前面的结点,当判断是最后一个结点时,直接删除就可以了。代码如下:
//2.设计无头结点的单链表的删除算法;
bool nDelete(PNode node,int i,int *ptr){
PNode p,q,m;
int count = 0;
p = node;
while(p!=NULL && count < i-1){ //遍历到第 i 个结点
m = p; //m 是记录 第 i-1 个结点
p = p->next;
count++;
}
if(p == NULL){
return false;
}else if(p->next == NULL){ //删除最后一个结点时。
*ptr = p->data;
q = p;
m->next = NULL;
}else{
*ptr = p->data;
q = p->next;
p->data = q->data;
p->next = q->next;
}
free(q);
return true;
}
3.设计无头结点的单链表的插入算法;
思路:无头结点的插入算法 麻烦就麻烦在 向第一个位置插入元素了,这里我们采用了和上面删除元素一样的思路,在这里我们可以这样想 :我们向第一个位置插入元素麻烦,我们可不可以向第二个位置插入元素,然后让着两个节点的数据域进行一下交换,是不是也实现在表头插入元素了呢。代码如下:
//3.设计无头结点的单链表的插入算法;
bool nInsert(PNode node,int i,int ndata){
PNode p = node,q;
int count =0;
while(p!=NULL&&count next;
count++;
}
if(p == NULL){
return false;
}else{
q = (PNode)malloc(sizeof(Node));
q->data = p->data; //数据域交换
q->next = p->next;
p->data = ndata; //数据域交换
p->next = q;
return true;
}
}
5.设计无头结点的单链表的逆置算法;
思路:所谓逆置算法就是让调换位置,让第一个和最后一个交换位置,第二个和倒数第二个交换位置 以此类推,但是单链表有个缺点 就是每次都必须从头开始,不像数组 可以通过下标来找到 相应的元素,相对来说寻找第几个元素比较困难费时一些,这里我们可以使用 我们创建 链表时用的 头插法 来实现逆置。就是从头开始遍历,把每个节点提取出来 看做成一个新的结点 ,进行头插 形成一条新链 这就是我们的 逆置链。代码如下:
//5.设计无头结点的单链表的逆置算法
PNode nInverse(PNode node){
PNode p = NULL,q = NULL,m = NULL;
p = q = node;
while(q!=NULL){
q = q->next; //记录本节点的下一个结点
p->next = m; //采用头插法
m = p;
p = q;
// printf("fsf ");
}
return m;
}
6.设计单链表的逆置算法;
思路:这个和无头结点逆置 基本一样,不在傲述,直接看代码:
//6.设计单链表的逆置算法
void Inverse(PNode head){
PNode p = NULL,q = NULL, m = NULL;
p = q = head->next; //第一个结点
while(q!=NULL){
q = q->next;
p->next = m;
m = p;
p = q;
}
head->next = m;
}
好了,这几个复习题基本 讲完,自己在电脑上 练习一下,不理解的地方 拿着笔在纸上写一写,画一画,你就会有思路的。加油
点击源码下载资源