单链表的插入与删除

参考:http://www.itxyz.net/3jk/c/2010/0820/11016.html

最近不是太忙,整理些东西,工作也许用得到。

在链表这种特殊的数据结构中,链表的长短需要根据具体情况来设定,当需要保存数据时向系统申请存储空间,并将数据接入链表中。对链表而言,表中的数据可以依此接到表尾或连结到表头,也可以视情况插入表中;对不再需要的数据,将其从表中删除并释放其所占空间,但不能破坏链表的结构。这就是下面将介绍的链表的插入与删除。

1. 链表的删除

如创建一个学生学号及姓名的单链表,即节点包括学生学号、姓名及指向下一个节点的指针,链表按学生的学号排列。再从键盘输入某一学生姓名,将其从链表中删除。

首先定义链表的结构:

从链表中删除一个节点有三种情况,即删除链表头节点、删除链表的中间节点、删除链表的尾节点。题目给出的是学生姓名,则应在链表中从头到尾依此查找各节点,并与各节点的学生姓名比较,若相同,则查找成功,否则,找不到节点。由于删除的节点可能在链表的头,会对链表的头指针造成丢失,所以定义删除节点的函数的返回值定义为

返回结构体类型的指针。

struct node *delet(head,pstr)/*以head为头指针,删除pstr所在节点*/ struct node *head; char *pstr; { struct node*temp,*p; temp = head; /* 链表的头指针*/ if (head==NULL)/*链表为空*/ printf("\nListis null!\n"); else /*非空表*/ { temp = head; while (strcmp(temp->str,pstr)!=0&&temp->next!=NULL)/* 若节点的字符串与输入字符串不同,并且未到链表尾*/ { p = temp; temp = tmep->next;/* 跟踪链表的增长,即指针后移*/ } if(strcmp(temp->str,pstr)==0) /*找到字符串*/ { if(temp==head) { /* 表头节点*/ printf("delete string :%s\n",temp->str); head = head->next; free(temp);/*释放被删节点*/ } else { p->next=temp->next; /*表中节点*/ printf("delete string :%s\n",temp->str); free(temp); } } else printf("\nno find string!\n");/*没找到要删除的字符串*/ } return(head); }

2. 链表的插入

首先定义链表的结构:

struct { int num; /*学生学号* / char str[20]; /*姓名* / struct node *next; } ;

在建立的单链表中,插入节点有三种情况,如图所示;



插入的节点可以在表头、表中或表尾。假定我们按照以学号为顺序建立链表,则插入的节点依次与表中节点相比较,找到插入位置。由于插入的节点可能在链表的头,会对链表的头指针造成修改,所以定义插入节点的函数的返回值定义为返回结构体类型的指针。节点的插入函数如下:

struct node *insert(head,pstr,n) /*插入学号为n、姓名为p s t r 的节点*/ struct node *head; /*链表的头指针*/ char *pstr; int n; { struct node *p1,*p2,*p3; p1=(struct node*)malloc(sizeof(struct node))/*分配一个新节点*/ strcpy(p1->str,pstr); /*写入节点的姓名字串*/ p1->num = n; /* 学号*/ p2 = head; if(head==NULL) /* 空表*/ { head=p1; p1->next=NULL;/*新节点插入表头*/ } else/*非空表*/ { while(n>p2->num&&p2->next!=NULL) /*输入的学号小于节点的学号,并且未到表尾*/ { p3 = p2; p2 = p2->next;/* 跟踪链表增长*/ } if(n<=p2->num) /*找到插入位置*/ if(head==p2) /* 插入位置在表头*/ { head = p1; p1->next = p2; } else { /*插入位置在表中*/ p3->next = p1; p1->next = p2; } else { /*插入位置在表尾*/ p2->next = p1; p1->next = NULL; } } return(head); /* 返回链表的头指针*/ }
实例:

创建包含学号、姓名节点的单链表。其节点数任意个,表以学号为序,低学号的在前,高学号的在后,以输入姓名为空作结束。在此链表中,要求删除一个给定姓名的节点,并插入一个给定学号和姓名的节点。

# include <stdlib.h> # include <malloc.h> struct node /*节点的数据结构*/ { int num; char str[20]; struct node *next; }; /* * * * * * * * * * * * * * * * * * * * * * * * * * * */ main( ) { /*函数声明*/ struct node *creat(); struct node *insert(); struct node *delet(); void print( ); struct node *head; char str[20]; int n; head=NULL; /*做空表*/ head=creat(head); /*调用函数创建以head 为头的链表*/ print(head);/*调用函数输出节点*/ printf("\n input inserted num,name:\n"); gets(str); /*输入学号*/ n=atoi(str); gets(str); /*输入姓名*/ head=insert(head, str, n); /*节点插入链表*/ print(head); printf("\n input deleted name:\n"); gets(str); /*输入被删姓名*/ head=delet(head,str); /*用函数删除节点*/ print(head); /*调用函数输出节点*/ return; } /* * * * * * * * * * * * * * * * * * * * * */ /* * * 创建链表* * * * * * * * * * * */ struct node *creat(struct node *head) { char temp[30]; struct node *pl,*p2; pl=p2=(struct node*)malloc(sizeof(struct node)); printf("input num, name: \n"); printf("exit:double times Enter!\n"); gets(temp); gets(pl->str); pl->num=atoi(temp); pl->next = NULL ; while(strlen(pl->str)>0) { if(head==NULL)//if the chain is null head= pl;// else p2->next=pl;//set the p2->next NULL p2 = pl;// pl=(struct node*)malloc(sizeof(struct node)); printf ("input num, name: \n"); printf("exit:double times Enter!\n"); gets(temp); gets(pl->str); pl->num=atoi(temp); pl->next= NULL; } return head; } /* * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * 插入节点* * * * * * * * * */ struct node *insert(head, pstr,n) struct node *head; char *pstr; int n; { struct node *pl,*p2,*p3; pl=(struct node*)malloc(sizeof(struct node)); strcpy (pl->str, pstr); pl->num = n; p2 = head; if(head == NULL) { head = pl; pl->next = NULL; } else { while (n>p2->num&&p2->next!=NULL) { p3 = p2; p2= p2->next; } if (n<=p2->num) if (head==p2) { head = pl; pl->next = p2; } else { p3->next = pl; pl->next= p2; } else { p2->next= pl; pl->next = NULL; } } return(head); } /* * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * 删除节点* * * * * * * * * * * * */ struct node *delet (head, pstr) struct node *head; char *pstr; { struct node *temp,*p; temp =head; if (head==NULL) printf("\nList is null!\n"); else { temp = head; while(strcmp(temp->str,pstr)!= 0 && temp->next!=NULL) { p = temp; temp= temp->next; } if(strcmp(temp->str,pstr)== 0) { if (temp== head) { head = head->next; free(temp); } else { p->next =temp->next; printf("delete string :%s\n",temp->str); free(temp); } } else printf("\nno find string!\n"); } return(head); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * 链表各节点的输出* * * * * * * * * */ void print(struct node *head) { struct node *temp; temp = head; printf("\n output strings:\n"); while (temp!=NULL) { printf("\n%d-----%s\n",temp->num,temp->str); temp= temp->next; } return; }
运行结果:

root@android-virtual-machine:/uniteq_smb/test# ./test1 input num, name: exit:double times Enter! 11 aa input num, name: exit:double times Enter! 12 bb input num, name: exit:double times Enter! output strings: 11-----aa 12-----bb input inserted num,name: 13 cc output strings: 11-----aa 12-----bb 13-----cc input deleted name: aa output strings: 12-----bb 13-----cc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值