数据结构——单链表

来源:互联网 发布:进出口软件如何报关 编辑:程序博客网 时间:2024/06/08 14:41
#include <stdio.h>#include <stdlib.h>/* 单链表的简单代码 *//* 此步骤为建立对应的表格结构 */struct list {int number;struct list *next;};/* ?若不定义转换,在sizeof(struct list)会报错 */typedef struct list LIST;/* 此步骤为创建链表函数,需要用到head p1,p2三个指针 */ LIST *creat(int n){int i,x;LIST *head,*p1,*p2;head=NULL;for(i=0;i<n;i++){p1=(LIST*)malloc(sizeof(LIST));printf("请输入第%d个数: ",i);scanf("%d",&x);p1->number=x;if(head==NULL){head=p1;p2=p1;} else{p2->next=p1;p2=p1;}p2->next=NULL;}return head;     }/* 此步骤为输出函数 */void output(LIST *p){int i=0;LIST *q;while(p!= NULL){printf("第%d个数是: %d\n",i+1,p->number);q=p->next;p=q;i++;}}/* 此步骤为添加内容函数,为保证可读性,存在问题:输入n为0或者为负时,无改变表头和报错 */void additem(LIST *p){int n,i,x;LIST *q;printf("请输入要插入在第几个数据后:");scanf("%d",&n);printf("请输入要插入的数据:");scanf("%d",&x);//if(n=0)//{//q=(LIST*)malloc(sizeof(LIST));//q->number=x;//q->next=p;//注释:此步未完成,为便于自己理解基本结构//}//if(n<0){//}for(i=0;i<n-1;i++)     /* 此处i=n-1   比如删除第5位数据,即删除a[4],此时i从0遍历,i=0循环完,p指向a[1],i=4循环完,p指向a[5] 下面删除元素同理 */{q=p->next;p=q;}q=(LIST*)malloc(sizeof(LIST));q->number=x;q->next=p->next;p->next=q;}/* 此步骤为删除元素,同样没有健壮性处理 */void del(LIST *p) {int n,i;LIST *q1,*q2;printf("请输入要删除的元素位数:");scanf("%d",&n);for(i=0;i<n-1;i++){q1=p->next;q2=p;p=q1;} q1=p->next;   /* 此步骤完成之后 q1是n+1位置;q2是n-1位置;p则是n的位置 */q2->next =q1;  /* 将p元素删除去 */free(p); /* 此步骤必不可少,易忘 */} /* 此步骤为删除整个函数,必不可少的一步,case 4 case 5均需要 */void free_list(LIST *p) {LIST *q;while(p!=NULL){q=p->next;free(p);p=q;}}/* 补充部分:重组链表,分治为两个链表  */LIST *A_B(LIST *p){LIST *q,*head,*temp;head=p->next;q=p->next;while(p->next!=NULL){temp=p->next;        /*temp为临时节点 */ p->next=temp->next;  /*重新构造p节点,跨过原来的下一位来构筑 */ temp=p->next;/*使临时节点指向q之后的节点,用于连接链2 */ q->next=temp;/* 重新链接链2*/ q=q->next; } q->next =NULL;p->next=NULL;return head;}/* 此步骤为输主函数,链表过程实现全部由子函数完成 */int main(int argc, char *argv[]) {LIST *p;int n,select;remake:printf("请输入链表长度:");scanf("%d",&n);p=creat(n); printf("链表建立完成!\n");selection:printf("=====================================\n");printf("请按以下提示操作:\n""0.退出程序\n""1.顺序输出链表\n" "2.插入数据\n""3.删除数据\n""4.重建链表\n""5.删除链表\n");scanf("%d",&select);printf("=====================================\n\a");switch(select){case 1:output(p);break;case 2:additem(p);break;case 3:del(p);break;case 4:free_list(p);goto remake; break;case 5:free_list(p); break;case 0:return 0;default:printf("你输入了错误的代码!\n\a");}goto selection; return 0;}



 补充:

1.上述代码创建链表采用尾插法——用一个指针始终指向尾部,在尾部构建后续链表。

在此补充另一种建表方式——头插法,即每次新数据在原有前方插入,代码如下:

/* 头插法 */ LIST *creat(int n){int i,x;LIST *q,*p;q=(LIST*)malloc(sizeof(LIST));q->next=NULL;for(i=0;i<n;i++){p=(LIST*)malloc(sizeof(LIST));  printf("请输入第%d个数: ",i); scanf("%d",&x); p->number=x; p->next=q->next;q->next=p;/* 在q与q->next两个之间插入数值,新的q->next变为插入的数 */ }return p;  /*此处也可返回q用来表示空的头结点*/ }


2.关于头结点:

创建头结点,有时候会是删除、插入等各种操作(如上删除操作,如果删除第一个链,没有头结点的时候非常麻烦,还要重新定头等)的时候更加便于理解,特别是在比较复杂的链表中。



 
原创粉丝点击