您的位置:首页 > 编程语言 > C语言/C++

单向链表的建立(C语言)

2016-10-31 11:10 288 查看
貌似有段时间没有做原创文章了,聒噪的很,开始正式学习数据结构啦哈哈,今天先做单向链表的建立,希望和大家一起分享

数组作为存放同类数据的集合,给我们在程序设计时带来很多的方便,增加了灵活性。但数组也同样存在一些弊病。如数组的大小在定义时要事先规定,不能在程序中进行调整,这样一来,在程序设计中针对不同问题有时需要30个大小的数组,有时需要50个数组的大小,难于统一。我们只能够根据可能的最大需求来定义数组,经常会造成一定存储空间的浪费。

我们希望构造动态的数组,随时可以调整数组的大小,以满足不同问题的需要。链表就是我们需要的动态数组。它是在程序的执行过程中根据需要有数据存储就向系统要求申请存储空间,决不构成对存储区的浪费。

链表是一种复杂的数据结构,其数据之间的相互关系使链表分成三种:单链表、循环链表、双向链表。首先介绍单链表

下图(图1)是单链表的结构



单 链表有一个头节点head,指向链表在内存的首地址。链表中的每一个节点的数据类型为结构体类型,节点有两个成员:整型成员(实际需要保存的数据)和指向下一个结构体类型节点的指针即下一个节点的地址(事实上,此单链表是用于存放整型数据的动态数组)。链表按此结构对各节点的访问需从链表的头找起,后续节点的地址由当前节点给 出。无论在表中访问那一个节点,都需要从链表的头开始,顺序向后查找。链表的尾节点由于无后续节点,其指针域为空,写作为NULL。

上图还给出这样一层含义,链表中的各节点在内存的存储地址不是连续的,其各节点的地址是在需要时向系统申请分配的,系统根据内存的当前情况,既可以连续分配地址,也可以跳跃式分配地址。

看一下链表节点的数据结构定义:

struct node
{
int num;
struct node *p;
} ;
在链表节点的定义中,除一个整型的成员外,成员p是指向与节点类型完全相同的指针。

在链表节点的数据结构中,非常非凡的一点就是结构体内的指针域的数据类型使用了未定义成功的数据类型。这是在C中唯一规定可以先使用后定义的数据结构。

链表的创建、输出步骤

单链表的创建过程有以下几步:
1 ) 定义链表的数据结构;
2 ) 创建一个空表;
3 ) 利用malloc ( )函数向系统申请分配一个节点;
4 ) 将新节点的指针成员赋值为空。若是空表,将新节点连接到表头;若是非空表,将新
节点接到表尾;
5 ) 判断一下是否有后续节点要接入链表,若有转到3 ),否则结束;
单链表的输出过程有以下几步
1) 找到表头;
2) 若是非空表,输出节点的值成员,是空表则退出;
3 ) 跟踪链表的增长,即找到下一个节点的地址;
4) 转到2 ).

1.输入链表长度的链表

首先是输入链表长度的链表建立打印,先上代码

#include <stdio.h>
#include <stdlib.h>

typedef struct Node *PtrToNode;
struct Node {
int Data;
PtrToNode   Next;
};

PtrToNode Read(); /* 细节在此不表 */
void Print( PtrToNode L ); /* 细节在此不表;空链表将输出NULL */

int main()
{
PtrToNode L1;
L1 = Read();
Print(L1);

return 0;
}

PtrToNode Read()
{
int len = 0;
int num = 0;
PtrToNode h = NULL;
PtrToNode last = NULL;

h = ( PtrToNode )malloc( sizeof( struct Node ) );//建立头结点
h->Next = NULL;
last = h;

scanf( "%d",&len );
while(len){
scanf( "%d",&num );
PtrToNode node = ( PtrToNode )malloc( sizeof( struct Node ) );
node->Data = num;
node->Next = NULL;
last->Next = node;
last = node;
len--;
}
return h;
}
void Print( PtrToNode L )
{

L=L->Next;
if(L==NULL){
printf("NULL\n");
return;
}
while(L!=NULL){
printf("%d ",L->Data);
L=L->Next;
}
putchar('\n');
}


就是这样的话头结点默认的data值是没有用的,从头结点的next开始,流程如图下



如果希望表头就有数据接入,则代码改为如下

#include <stdio.h>
#include <stdlib.h>

typedef struct Node *PtrToNode;
struct Node {
int Data;
PtrToNode   Next;
};

PtrToNode Read(); /* 细节在此不表 */
void Print( PtrToNode L ); /* 细节在此不表;空链表将输出NULL */

int main()
{
PtrToNode L1;
L1 = Read();
Print(L1);

return 0;
}

PtrToNode Read()
{
int len = 0;
int num = 0;
PtrToNode h = NULL;
PtrToNode last = NULL;
scanf( "%d",&len );

if(len==0)
return NULL;

else{
scanf("%d",&num);
h = ( PtrToNode )malloc( sizeof( struct Node ) );//建立头结点
h->Data=num;
h->Next = NULL;
last = h;
len--;
while(len){
scanf( "%d",&num );
PtrToNode node = ( PtrToNode )malloc( sizeof( struct Node ) );
node->Data = num;
node->Next = NULL;
last->Next = node;
last = node;
len--;
}
return h;
}
}
void Print( PtrToNode L )
{
if(L==NULL){
printf("NULL\n");
return;
}
while(L!=NULL){
printf("%d ",L->Data);
L=L->Next;
}
putchar('\n');
}

2.以一个非负数作为链表的结尾

代码如下

#include <stdio.h>
#include <stdlib.h>

typedef struct Node *PtrToNode;
struct Node {
int Data;
PtrToNode   Ne
c424
xt;
};

PtrToNode Read(); /* 细节在此不表 */
void Print( PtrToNode L ); /* 细节在此不表;空链表将输出NULL */

int main()
{
PtrToNode L1;
L1 = Read();
Print(L1);

return 0;
}

PtrToNode Read()
{
int num = 0;
PtrToNode h = NULL;
PtrToNode last = NULL;
scanf( "%d",&num );

if(num<=0)
return NULL;

else{
h = ( PtrToNode )malloc( sizeof( struct Node ) );//建立头结点
h->Data=num;
h->Next = NULL;
last = h;
scanf( "%d",&num );
while(num>0){
PtrToNode node = ( PtrToNode )malloc( sizeof( struct Node ) );
node->Data = num;
node->Next = NULL;
last->Next = node;
last = node;
scanf( "%d",&num );
}
return h;
}
}
void Print( PtrToNode L )
{
if(L==NULL){
printf("NULL\n");
return;
}
while(L!=NULL){
printf("%d ",L->Data);
L=L->Next;
}
putchar('\n');
}


运行结果如下:



至此,完成链表的创建
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息