单链表的创建(静态链表,动态链表)

来源:互联网 发布:淘宝app框架 编辑:程序博客网 时间:2024/05/19 01:11

       链表是一种很重要的数据结构,在实际工作中也有着很多的应用,这次我们先讨论一下最简单的单链表

       关于单链表的操作有很多,当然最基本的就是要创建一个单链表,对于单链表来说,可以按照类型分为静态链表动态链表

1.静态链表

静态链表指的是先确定节点个数,然后根据指定个数而创建的链表。既然是确定节点个数,我们首先要在程序中输入一个需要创建的节点个数,然后根据这个需要创建的节点个数,来创建一个单链表。当然,为了验证创建的链表的正确性,我们还需要再编写一个遍历打印链表节点的函数TraversalList。程序如下:

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

typedef struct Node
{
int member; //节点中的成员
struct Node *next;//指向下一个节点的指针
};

//创建单链表的函数
Node* CreateSList()
{
int i = 0; //循环计数
int length = 0;//链表长度
int value = 0;//存储输入的节点成员值

//创建链表头节点并分配空间
Node* pHead = (Node*)malloc(sizeof(Node));
assert(pHead != NULL);

//创建临时节点并分配空间,用于循环控制
Node* pTemp = (Node*)malloc(sizeof(Node));
assert(pHead != NULL);

//输入需要创建的链表节点个数
printf("请输入要创建的节点个数:");
scanf_s("%d", &length);

//循环创建链表节点
for (i = 0; i < length; i++)
{
//输入每个节点的成员
printf("请输入第%d个节点的成员:",i + 1);
scanf_s("%d", &value);

//创建一个新节点,并分配空间
Node* pNew = (Node*)malloc(sizeof(Node));


//将刚才输入的节点成员赋给pNew节点
pNew->member = value;
//将pNew的下一个节点设置为NULL
pNew->next = NULL;


//如果是第一个链表节点
if (0 == i)
{
pHead = pNew; //将pNew节点赋给头节点
pHead->next = NULL;//设置头节点的下一个节点为NULL
pTemp = pHead;//将头结点赋给临时节点,用于后面的循环控制
}
//不是第一个节点
else
{
pTemp->next = pNew;//将pNew赋给pTemp节点的下一个节点
pTemp = pTemp->next;//将pTemp指向pTemp的下一个节点
pTemp->next = NULL; //将pTemp的下一个节点的下一个节点设置为NULL
}
}
return pHead;//返回头节点
}

//遍历打印链表的函数
void TraversalSList(Node* pHead)
{
Node* pTemp = pHead;//将头节点的指针赋给临时节点pTemp
int i = 0; //循环时打印节点个数的控制变量
while (NULL != pTemp)   //若节点pTemp不为空,则循环
{
printf("第%d个节点信息:\n", i + 1);
printf("第%d个节点的成员值为:%d\n",i + 1,pTemp->member);
//节点数累加
i++;
//将pTemp指向pTemp的下一个节点
pTemp = pTemp->next;
}
return;
}

//主函数
int main()
{
Node* pHead = NULL;//创建链表的头结点,并初始化为NULL
pHead = CreateSList();//调用CreateSList函数创建单链表
printf("\n开始打印全部节点:\n");
TraversalSList(pHead);//调用TraversalSList函数遍历打印单链表
return 0;
}


      编译结果如下(编译环境是Visual Studio 2013):


       通过结果可以看到,我们需要首先输入一个节点个数(5),然后根据这个个数进行for循环,来依序创建各个节点,通过TraversalSList函数来遍历打印,验证创建的正确性。


2.动态链表

       相对于静态链表的“确定节点个数”,动态链表则是没有确定的节点个数,需要在创建过程中根据一些特定条件(例如节点中成员的值为空则不再创建)而控制创建。这种形式的使用场景包括播放器的播放列表管理(例如Ubuntu操作系统自带的totem视频播放器的播放列表就是通过动态单链表管理的,当文件名称为空时,则不再创建)。创建动态链表时,就无需再先输入一个节点个数了,而是在创建过程中根据创建条件创建,只要符合条件,则是一直创建,否则退出创建并打印。这次我们在程序中设定的创建节点条件是节点的成员不为0。程序如下:

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

typedef struct Node
{
int member; //节点中的成员
struct Node *next;//指向下一个节点的指针
};

//创建单链表函数
Node* CreateSList()
{
int i = 0;
int length = 0;
int value = 0;
Node* pHead = (Node*)malloc(sizeof(Node));
Node* pTemp = (Node*)malloc(sizeof(Node));
Node* pNew = (Node*)malloc(sizeof(Node));
printf("请输入第1个节点的成员:");
scanf_s("%d", &pNew->member);
if (0 == pNew->member)
{
printf("第一个节点的成员就是0,故无法创建该链表!\n");
return NULL;
}
 

//while循环,当节点成员不为0时创建
while (0 != pNew->member)
{
if (0 == i)
{
pHead = pNew;
pHead->next = NULL;
pTemp = pHead;
}
else
{
pTemp->next = pNew;
pTemp = pTemp->next;
pTemp->next = NULL;
}

i++;

pNew = (Node*)malloc(sizeof(Node));

printf("请输入第%d个节点的成员:", i + 1);
scanf_s("%d", &pNew->member);
}

printf("第%d个节点的成员为0,故该链表长度为%d\n", i + 1, i);


return pHead;
}

void TraversalSList(Node* pHead)
{
Node* pTmp = pHead;//将头节点的指针赋给临时节点pTemp
int i = 0; //循环时打印节点个数的控制变量
while (NULL != pTmp)   //节点p不为空,循环
{
printf("第%d个节点信息:\n", i + 1);
printf("第%d个节点的成员值为:%d\n", i + 1, pTmp->member);
i++;
pTmp = pTmp->next;
}
return;
}

int main()
{
Node* pHead = NULL;
pHead = CreateSList();
printf("\n开始打印全部节点:\n");
TraversalSList(pHead);
return 0;
}

      编译结果如下(编译环境是Visual Studio 2013):


        通过结果可以看到,由于动态链表创建时事先不知道节点个数,所以需要使用while循环,条件是节点的成员不为0,来依序创建各个节点,当输入节点成员为0时,则跳出while循环创建,然后通过TraversalSList函数来遍历打印,验证创建的正确性。

        以上只是个人的一些意见和理解,还请各位多多指教。

0 0