C语⾔——结构体链表,附完整⽰例
引⽤⾃⾝的结构体,⼀个结构体中有⼀个或多个成员的基类型就是本结构体类型时,说明这个结构体可以引⽤⾃⼰,所以称作引⽤⾃⾝的结构体。
例如下⾯的结构体:
struct link{ char ch; struct link *p} a;
p是⼀个可以指向struct link类型变量的指针成员,这样,a.p=&a就是合法的表达式。那么,这有什么意义呢?
这样的意义就是我们可以把分散存储的数据项,⽤⼀个结构体成员链接起来(当然这也耗费了那个存储指针的内存空间)看下⾯的程序
#include
struct node{
int data;
struct node *next;
};
main(){
struct node a,b,c,*p;//我们假设,这样声明的结构体变量a 、b、c在内存中并不是相临的
a.data=10;
b.data=20;
c.data=30;
<=&b;
<=&c;
<='\0';
p=&a;
/
/结构体变量a地址赋给p
while(p){
printf(" %d ",p->data);
//每输出⼀个值后,p⾃动指向本项的链接项
/*这样有了⼀个单独保持链接的成员就把不相临的存储单元在逻辑上存储在了⼀起*/
p=p->next;
}
printf("\n");
}
这样的相链的数据存储形式称为链表!上⾯形成链表的⽅法是⼈为定义的,在程序执⾏过程中,不会⽣成新的存储单元,所以也称为“静态链表”
下⾯看⼀种更⽅法使⽤的“动态链表”
前⾯的⽇志中提到了C语⾔动态存储分配提供了“按需分配内存”的实现⽅法,有⼀个问题是,如果多次动态分配存储单元,各存储单元的地址不是⼀定是连续的,⽽所需要处理的批量数据往往是⼀个整体,各数据之间存在着顺序关系,这样,我们可以利⽤上⾯的链表把动态得到的存储单元在逻辑上(⽽不是在物理上)连接起来,就可以实现我们需要的顺序关系了。这时,是把链表技术与动态存储分配结合了起来,所以这⾥我们给了链表⼀个新的名词叫做“动态链表”
很⾃然,我们上⾯例⼦中的链表只有⼀个指向后⾯数据项的指针,如果有两个呢?⼀个指后,⼀个指前,这样就会出现“双向链表”与“单向链表”的区别
下⾯我们主要看单向链表
事实上,单⾝链表中的每个存储单元的数据(也就是结构体)的格式类型是相同的(包括数据成员和指针成员)
如下:struct abc{int data,……struct abc *next;};
与单向链表有关的算法有以下⼏类:
建⽴链表 输出结点数据 插⼊结点数据 删除结点数据
下⾯这个程序是⽰例
#include
#include
struct slist{ int data; struct slist *next;};
struct slist{ int data; struct slist *next;};
typedef struct slist SLIST;
SLIST *creat_slist(){
/*该函数的作⽤是创建动态链表,函数的返回值是结构体指针变量,也就是新创建的动态链表的头结点,需要注意的是,这⾥的头结点没有数据data,只有指针next指向 int c;
/*⽤来临时存储结构体中的data*/
SLIST *h,*s,*r;
/*声明⼯作指针*/
h=(SLIST *)malloc(sizeof(SLIST));
/*动态获取⼀个结构体的存储空间*/
r=h;
/*结构体指针r⽤来在下⾯的循环中使⽤h指针不变*/
scanf("%d",&c);
/*得到⼀个结构体成员int data数据*/
while(c!=-1){
/*如果上⾯得到的int data数据不为-1就进⼊循环 */
s=(SLIST *)malloc(sizeof(SLIST));
/*循环中⽤结构体指针s获取结点*/
s->data=c;
/*s成员data为c注意第⼀次进⼊循环时,这个c是在循环外部上⾯输⼊的*/
r->next=s;
/*r指针本来与h相同,r的成员next在进⼊循环前是没有指向的现在进⼊了循环得到了⼀个结点,就把r的next指向新的结点,这样就使h头结点指向了s*/
r=s;
/*r依次与最新的结点相同,为了依次⽤最新的存储空间的next指向下⼀个获得的结点*/
scanf("%d",&c);
}
r->next='\0';
/*退出循环后,r指向最后⼀个结点,⽽这个最后结点的成员next要指向'\0'*/
return h;
/*返回动态链表的头结点指针*/
}
void print_slist(SLIST *head){
/*该函数是依次输出动态链表的结点,参数是结构体指针变量,也就是
动态链表的头结点*/
SLIST *p;
/*声明⼀个⼯作指针,因为head不能⾃⼰往后依次移动,所以⽤指针
p实现*/
p=head->next;
if(p=='\0')printf("linklist is null!\n");/*空链表*/
else{printf("head");/*⾮空链表*/
do{ printf("->%d",p->data);
p=p->next;}while(p!='\0');
printf("->end\n");
}
}
SLIST *insert_snode(SLIST *head,int x,int y){
c语言listinsert函数/*该函数实现在链表值为x的结点前⾯插⼊⼀个结点,值为y参数有三个链表头结点,值x,y*/
SLIST *s,*p,*q;
/*定义⼯作指针*/
s=(SLIST *)malloc(sizeof(SLIST));
s->data=y;
/*上⾯这两句先获取了⼀个结构体动态存储空间,并给其成员data赋值为y,但此时该空间并未成为链表的⼀个结点*/
q=head;
p=head->next;
/*上⾯两句初始化⼯作指针,就是把⼯作指针q与head相同,p指向head的next*/
while((p!='\0')&&(p->data!=x)){
/*这个循环是供查到值为x的结点所在位置的,需要注意的是这⾥的并的两个条件位置不能变,因为只有在p指向不为空的时候才能讨论其data成员值是否为x,否则 q=p;p=p->next;
/*满⾜循环条件的话,p与q依次后移直到到值为x的结点或到了链表的尾部*/
/*满⾜循环条件的话,p与q依次后移直到到值为x的结点或到了链表的尾部*/
}
s->next=p;
/*在p指向的结点前⾯插⼊,所以新的结点的next指向p*/
q->next=s;
/*q-next本指向p结点,现在令其指向s结点,实现了插⼊*/
return head;/*头指针并未变化,返回即可*/
}
SLIST *insert_bnode(SLIST *head,int x,int y){
/*该函数实现在链表值为x的结点后⾯插⼊⼀个结点,值为y参数有三个链表头结点,值x,y*/
SLIST *s,*p,*q;
/*定义⼯作指针*/
s=(SLIST *)malloc(sizeof(SLIST));
s->data=y;
/*上⾯这两句先获取了⼀个结构体动态存储空间,并给其成员data赋值为y,但此时该空间并未成为链表的⼀个结点*/
q=head;
p=head->next;
/*上⾯两句初始化⼯作指针,就是把⼯作指针q与head相同,p指向head的next*/
while((p!='\0')&&(p->data!=x)){
/*这个循环是供查到值为x的结点所在位置的,需要注意的是这⾥的并的两个条件位置不能变,因为只有在p指向不为空的时候才能讨论其data成员值是否为x,否则 q=p;p=p->next;
/*满⾜循环条件的话,p与q依次后移直到到值为x的结点或到了链表的尾部*/
}
s->next=p->next;
/*在p指向的结点后⾯插⼊,所以新的结点的next指向p*/
p->next=s;
/*p-next本指向p后⾯的结点,现在令其指向s结点,实现了后插⼊*/
return head;/*头指针并未变化,返回即可*/
}
SLIST *del_node(SLIST *head,int x){
/*该函数实现删除链表值为x的结点,参数有两个链表头结点,值x */
SLIST *s,*p,*q;
/*定义⼯作指针*/
q=head;
p=head->next;
/*上⾯两句初始化⼯作指针,就是把⼯作指针q与head相同, p指向head的next*/
while((p!='\0')&&(p->data!=x)){
/*这个循环是供查到值为x的结点所在位置的,需要注意的是这⾥的并的两个条件位置不能变,因为只有在p指向不为空的时候才能讨论其data成员值是否为x,否则 q=p;p=p->next;
/*满⾜循环条件的话,p与q依次后移直到到值为x的结点或到了链表的尾部*/
}
q->next=p->next;
/*把q->next置成p->next,*/
free(p);
/*释放p的存储空间,实现删除*/
return head;
/*头指针并未变化,返回即可*/
}
//在【C语⾔中⽂社区】回复“C语⾔”,免费领取200G编程资料
main(){
SLIST *head; int x,y;
head=creat_slist();//创建链表函数
print_slist(head);
printf("please input x\n"); scanf("%d",&x);
printf("please input y\n"); scanf("%d",&y);
head=insert_snode(head,x,y);//结点前插⼊函数
print_slist(head);
printf("please input x\n"); scanf("%d",&x);
printf("please input y\n"); scanf("%d",&y);
head=insert_bnode(head,x,y);//结点后插⼊函数
print_slist(head);
print_slist(head);
printf("please input x\n"); scanf("%d",&x);
head=del_node(head,x);//删除结点函数
print_slist(head);
}
声明:
本⽂于⽹络整理,版权归原作者所有,如来源信息有误或侵犯权益,请删除或授权事宜。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论