转载自:http://blog.csdn.NET/xubin341719/article/details/7091583/node
最近不是太忙,整理些东西,工做也许用获得。算法
1,为何要用到链表数组
数组做为存放同类数据的集合,给咱们在程序设计时带来不少的方便,增长了灵活性。但数组也一样存在一些弊病。如数组的大小在定义时要事先规定,不能在程序中进行调整,这样一来,在程序设计中针对不一样问题有时须要3 0个大小的数组,有时须要5 0个数组的大小,难于统一。咱们只可以根据可能的最大需求来定义数组,经常会形成必定存储空间的浪费。数据结构
咱们但愿构造动态的数组,随时能够调整数组的大小,以知足不一样问题的须要。链表就是咱们须要的动态数组。它是在程序的执行过程当中根据须要有数据存储就向系统要求申请存储空间,决不构成对存储区的浪费。函数
链表是一种复杂的数据结构,其数据之间的相互关系使链表分红三种:单链表、循环链表、双向链表,下面将逐一介绍。spa
2,单向链表.net
单链表有一个头节点head,指向链表在内存的首地址。链表中的每个节点的数据类型为结构体类型,节点有两个成员:整型成员(实际须要保存的数据)和指向下一个结构体类型节点的指针即下一个节点的地址(事实上,此单链表是用于存放整型数据的动态数组)。链表按此结构对各节点的访问需从链表的头找起,后续节点的地址由当前节点给出。不管在表中访问那一个节点,都须要从链表的头开始,顺序向后查找。链表的尾节点因为无后续节点,其指针域为空,写做为NULL。设计
如图所示指针
上图还给出这样一层含义,链表中的各节点在内存的存储地址不是连续的,其各节点的地址是在须要时向系统申请分配的,系统根据内存的当前状况,既能够连续分配地址,也能够跳跃式分配地址。code
3,单向链表程序的实现
(1),链表节点的数据结构定义
struct node { int num; struct node *p; } ;
在链表节点的定义中,除一个整型的成员外,成员p是指向与节点类型彻底相同的指针。
在链表节点的数据结构中,很是特殊的一点就是结构体内的指针域的数据类型使用了未定义成功的数据类型。这是在C中惟一规定能够先使用后定义的数据结构。
(2),链表的建立、输出步骤
单链表的建立过程有如下几步:
1 ) 定义链表的数据结构;
2 ) 建立一个空表;
3 ) 利用malloc ( )函数向系统申请分配一个节点;
4 ) 将新节点的指针成员赋值为空。如果空表,将新节点链接到表头;如果非空表,将新
节点接到表尾;
5 ) 判断一下是否有后续节点要接入链表,如有转到3 ),不然结束;
单链表的输出过程有如下几步
1) 找到表头;
2) 如果非空表,输出节点的值成员,是空表则退出;
3 ) 跟踪链表的增加,即找到下一个节点的地址;
4) 转到2 ).
(3),程序代码例子:
建立一个存放正整数单链表,输入0或小于0的数,结束建立链表,并打印出链表中的值,程序以下:
#include <stdlib.h> /*含ma l l o c ( ) 的头文件*/ #include <stdio.h> //①定义链表数据结构 struct node { int num; struct node *next; }; //函数声明 struct node *creat(); void print(); main( ) { struct node *head; head=NULL; //②建一个空表 head=creat(head);/*建立单链表*/ print(head);/*打印单链表*/ } /******************************************/ struct node*creat(struct node *head)/*返回的是与节点相同类型的指针*/ { struct node*p1,*p2; int i=1; //③利用malloc ( )函数向系统申请分配一个节点 p1=p2=(struct node*)malloc(sizeof(struct node));/*新节点*/ printf("请输入值,值小于等于0结束,值存放地址为:p1_ADDR= %d\n",p1); scanf("%d",&p1->num);/*输入节点的值*/ p1->next=NULL;/*将新节点的指针置为空*/ while(p1->num>0)/*输入节点的数值大于0*/ { //④将新节点的指针成员赋值为空。如果空表,将新节点链接到表头;如果非空表,将新节点接到表尾; if(head==NULL) head=p1;/*空表,接入表头*/ else p2->next=p1;/*非空表,接到表尾*/ p2=p1; p1=(struct node*)malloc(sizeof(struct node));/*下一个新节点*/ i=i+1; printf("请输入值,值小于等于0结束,值存放地址为:p%d_ADDR= %d\n",i,p2); scanf("%d",&p1->num);/*输入节点的值*/ //⑤判断一下是否有后续节点要接入链表,如有转到3 ),不然结束; } //==============原来程序更正部分:(多谢@daling_datou提醒)================================ free(p1); //申请到的没录入,因此释放掉 p1=NULL; //使指向空 p2->next = NULL; //到表尾了,指向空 printf("链表输入结束(END)\n"); //============================================== return head;/*返回链表的头指针*/ } /*******************************************/ void print(struct node*head)/*出以head为头的链表各节点的值*/ { struct node *temp; temp=head;/*取得链表的头指针*/ printf("\n\n\n链表存入的值为:\n"); while(temp!=NULL)/*只要是非空表*/ { printf("%6d\n",temp->num);/*输出链表节点的值*/ temp=temp->next;/*跟踪链表增加*/ } printf("链表打印结束!!"); }
在链表的建立过程当中,链表的头指针是很是重要的参数。由于对链表的输出和查找都要从链表的头开始,因此链表建立成功后,要返回一个链表头节点的地址,即头指针。