链表
链表的建立:
两种思路——(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。
感谢阅读!