1.有头结点的链表
#include <stdio.h>
#include <stdlib.h>
typedef struct Link{
char elem;
struct Link * next;
}link;
link * initLink();
void display(link * p);
int main(){
link * c=initLink();
display(c);
}
link * initLink(){
int i;
link * p=(link*)malloc(sizeof(link));
link * temp=p;
for(i=1;i<=4;i++){
link * a=(link*)malloc(sizeof(link));
temp->next=a;
a->elem=i;
a->next=NULL;
temp=temp->next;
}
return p;
}
//有头结点的链表
(1)
void display(link * p){
int i;
link * a=p;
a=a->next;
while(a->next){
printf("%d ",a->elem);
a=a->next;
}
}
输出结果为 1 2 3
可以把while的条件当做一个句子放在循环的末尾。
当循环遍历到首元结点时,首先输出首元结点的数据域,然后把a赋值为第二结点的地址。最后再进行while语句中的条件判断。While语句中判断的是第二结点的指针域是否是NULL。
当循环到倒数第二个结点的时候,首先输出倒数第二个结点的数据域,然后把a赋值为倒数第一个结点的地址。While语句判断的是倒数第一个结点的指针域是否为NULL。判断结果是NULL。所以跳出循环。输出结果只输出到了倒数第二个结点,倒数第一个结点的数据域还没有输出。每次循环时,应当判断当前结点的指针域是否为NULL。可是上面的那个算法,却判断了下一个结点的指针域。
(2)
void display(link * p){
int i;
link * a=p;
a=a->next;
link * temp=a;
while(temp->next){
printf("%d ",a->elem);
temp=a;
a=a->next;
}
}
输出结果为 1 2 3 4
上面的算法中,temp储存了当前结点的地址。While判断的也是当前结点的指针域是否为NULL。当当前结点的指针域为NULL时,才停止输出。
(3)
void display(link * p){
int i;
link * a=p;
while(a->next){
a=a->next;
printf("%d ",a->elem);
}
}
输出结果为 1 2 3 4
上面的算法中,输出的是当前指针域,while判断的也是当前指针域。所以算法是正确的。
(4)
void display(link * p){
int i;
link * a=p;
a=a->next;
while(a){
printf("%d ",a->elem);
a=a->next;
}
}
上面的算法可以看为是算法(2)的升级版,输出的是当前结点的数据域,while判断的是当前结点的指针域。所以算法正确。
思考循环的判断条件,并想想循环条件有哪些等价
2.不带有头节点的链表
#include <stdio.h>
#include <stdlib.h>
typedef struct Link{
char elem;
struct Link * next;
}link;
link * initLink();
void display(link * p);
int main(){
link * c=initLink();
display(c);
}
link * initLink(){
int i;
link * p=(link*)malloc(sizeof(link));
p->elem=1;
p->next=NULL;
link * temp=p;
for(i=2;i<=4;i++){
link * a=(link*)malloc(sizeof(link));
temp->next=a;
a->elem=i;
a->next=NULL;
temp=temp->next;
}
return p;
}
//没有头结点的链表
(1)
void display(link * p){
link * a=p;
while(a){
printf("%d ",a->elem);
a=a->next;
}
}
输出结果为1 2 3 4
上面的算法中,输出的是当前结点的数据域,while判断的是当前结点的指针域,算法正确
(2)
void display(link * p){
link * a=p;
link * temp=a;
while(temp->next){
printf("%d ",a->elem);
temp=a;
a=a->next;
}
}
输出结果为1 2 3 4
上面的算法中,输出的是当前结点的数据域,temp存储当前结点的地址,while判断的是当前结点的指针域,算法正确。
综合以上的链表遍历算法分析,对于两种链表的遍历,算法:
while(a){
printf("%d ",a->elem);
a=a->next;
}
更便于记忆。有头结点的链表只需将a指针指向首元结点即可。