链表
链表的建立:
两种思路——(1)顺序建立:在后面添加结点,定义一个head指针,head->next指向的是第一个结点的地址,
p=head;
q=(...) malloc ( sizeif (...) );
……
p->next=q;
p=q;
利用for循环不断向后建立若干个结点
最后把p->next=NULL;
(2)逆序建立:即在前面添加结点,过程:建立一个结点,next指向NULL,再定义一个结点,next指向前一个定义的结点,以此类推,最后得到的是第一个结点的地址。
结点的删除:p指向前一个结点,q指向后一个。p->next=q->next; 这样q指向的结点就被删除了。
结点的后移:p=p->next; 结点无法前移。
结点的插入:pp指向新结点,p指向前一个结点,q指向后一个。 p->next=pp ; pp->next=q; 这样pp指向的结点就被插入在p和q指向的结点中间。
下面是有两个例子
例一:顺序建立链表
#include
#include
struct StuNode
{
int num;
char name[20];
char sex[5];
int age;
struct StuNode *next;
}*head,*p,*q;
int main()
{
int i,n,ag,flag;
printf("input n=?"); //录入信息的学生个数
scanf("%d",&n);
head=(struct StuNode *)malloc(sizeof(struct StuNode)); //记下表头地址 注意 *
head->next=NULL; //??? 答:相当于给head->next 初始化了,之后还可以指向别的地方
p=head; //p指向了head——空头结点地址
printf("\ninput student's data\n");
for(i=0;i<n;i++)
{
q=(struct StuNode *)malloc(sizeof(struct StuNode));
scanf("%d%*c",&q->num);
gets(q->name);
gets(q->sex);
scanf("%d",&q->age);
p->next=q; //p->next指向了q——下一个结点的地址,
p=q; //顺序建立结点
}
// free(q);
p->next=NULL;
p=head->next; //p回到第一个结点(head的作用是引出第一结点的地址,即head->next)
printf("\ndisplay linklist\n");
for(i=0;i<n;i++) //打印链表内容
{
printf("%d\t",p->num);
printf("%s\t",p->name);
printf("%s\t",p->sex);
printf("%d\n",p->age);
p=p->next;
}
printf("\ninput age to be deleted:");
while(scanf("%d",&ag)&&ag!=0) //scanf,正确读取则返回数据个数,出错返回0
{
flag=0;
p=head; //p在前,q在后
q=p->next; //p->next指向第一结点地址 ,即q指向
while(q) //循环直到q=NULL,即指向最后一个结点
{
if(ag==q->age)
{
flag=1;
if(q->next!=NULL)
p->next=q->next; //删除结点
else
p->next=NULL; //q->next=NULL说明这是最后一个结点
printf("delete success!\n");
break;
}
else{
p=p->next;
q=q->next;
} //结点后移
}
if(flag==0)
printf("can't find!\n");
else{ //输出删除结点后的单链表
p=head->next;
printf("\ndisplay linklist after one node was deleted\n");
for(i=0;i<n;i++){
printf("%d\t",p->num);
printf("%s\t",p->name);
printf("%s\t",p->sex);
printf("%d\n",p->age);
p=p->next;
}
}
}
free(p);
free(q);
free(head);
return 0;
}
例二,逆序建立链表
#include
#include
#include
struct Node
{
char nu[5],name[10],sex[5],age[5];
struct Node *next;
};
struct Node *input();
void del(struct Node *f);
void output(struct Node *f);
int main()
{
struct Node *f=NULL;
f=input(); //信息录入,在前加,返回的是第一节点的地址
printf("======删除前======\n");
output(f);
del(f); //信息删除,
printf("======删除后======\n");
output(f);
return 0;
}
struct Node *input()
{
int i;
struct Node *f=NULL,*s=NULL;
for(i=0;i<5;i++){
s=(struct Node*)malloc(sizeof(struct Node));
printf("第%d位学生:",i);
// scanf("%s/%s/%s/%s",s->nu,s->name,s->sex,s->age);
gets(s->nu);
gets(s->name);
gets(s->sex);
gets(s->age);
s->next=f;
f=s;
}
// free(s);
return f; //s为最后一个节点的首地址
}
void del(struct Node *f)
{
char a[5]; //年龄值
struct Node *p=f,*s=f;
gets(a);
while(p!=NULL){
if(strcmp(a,f->age)==0){ //如果第一个就是
f=s->next;
p=f;
s=f;
}
else if(strcmp(a,p->age)==0){
s->next=p->next;
}
s=p;
p=p->next;
}
}
void output(struct Node *f)
{
struct Node *r=f;
while(r!=NULL){
printf("number:%s\t",r->nu);
printf("name:%s\t",r->name);
printf("sex:%s\t",r->sex);
printf("age:%s\n",r->age);
r=r->next;
}
}
两个代码,前一个是按书上的敲的,后一个是自己敲得,开始的时候对书上的哪些内容看不太懂,经过反复推敲,总算有了些眉目,全都写在注释里了,下面再来总结一下吧:
(1)顺序建立链表必须有一个“head”来指引第一个结点;
(2)指针指向NULL,相当于初始化,也是避免野指针造成的风险;
(3)哪怕是数字,也可以用字符串表示,用字符串格式输出,如例二的age。
感谢阅读!

浙公网安备 33010602011771号