由于顺序表的存储特点是逻辑关系上相邻的两个元素在物理位置上也相邻,由于这个特点,在插入与删除元素的时候需要移动大量的元素,而链表在插入和删除元素时避免了这种情况。
链表称之为线性结构,是因为链表每一个节点都存储着两部分元素,存放数据的为数据域,存放需要存放的数据,另一部分存放直接后继(下一个节点)的地址,通过指针来依次寻找下一个节点,就好像一根线把一颗颗珠子串起来一样,所以称为线性结构。
用图像表示单链表为:
链表中又有几个概念:头指针、头节点、首节点、尾节点
头节点:在单链表的第一个节点之前附设一个节点
头指针:在指向头节点的指针称为头指针
首节点:存储数据的第一个节点
尾节点:链表的最后一个节点,单链表中尾节点的指针域为空
这里主要介绍的是单链表创建的头插法。
链表头插法:
代码实现:
- 使用C语言结构体来定义每一个节点,代码如下:
//定义每一个节点 typedef struct Node { int data;//用整型数据来代替数据域 struct Node *pNext;//指针域,用来存放下一个节点的地址 }NODE,*PNODE; //使用typedef 来给每个节点起一个别名NODE代表的是struct Node 类型 PNODE代表的是struct Node*类型
- 定义头插法函数
PNODE Create_list() { //首先定义一个带有头节点的单链表 PNODE pHead = (PNODE)malloc(sizeof(NODE));//分配动态内存 if (NULL == pHead)//判断是否分配到内存,若为NULL则分配内存失败,程序终止 { printf("内存分配失败,程序终止\n"); exit(-1); } pHead->pNext = NULL;//将头节点的指针域置空 int flag = 1;//判断条件,通过flag来判断用户是否要继续添加元素 char str;//存放用户输入的数据 printf("请输入要存放的数据,以$结束:");//提示语句 while (flag) { str = getchar();//接受用户输入的数据 if (str != '$') { PNODE pNew = (PNODE)malloc(sizeof(NODE));//创建需要插入的新节点 if (NULL == pNew)//判断内存分配是否成功 { printf("内存分配失败,程序终止\n"); exit(-1); } pNew->data = str;//将用户需要存放的数据存放在新节点的数据域中 pNew->pNext = pHead->pNext;//将新节点的指针域指向原先的第一个节点 pHead->pNext = pNew;//将头指针指向新节点完成头插法 } else//用户输入了结束字符,终止循环 flag = 0; } return pHead; }
- 定义一个遍历链表函数,用来检验头插法是否成功
void Treaverse_list(PNODE pHead) { PNODE p = pHead->pNext;//新定义一个节点存放链表中的第一个节点 while (NULL != p)//如果p不是空的就打印数据域中的数据,否则说明遍历完链表了 { printf("%c", p->data); p = p->pNext;//通过指针域来让节点P移动 依次遍历链表 } printf("\n"); return;//表示函数结束 }
- 在main函数中调用函数
int main(void) { PNODE pList; pList = Create_list(); Treaverse_list(pList); return 0; }
运行结果为
链表创建成功!
源码
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
//定义每一个节点
typedef struct Node
{
char data;//用字符型数据来代替数据域
struct Node *pNext;//指针域,用来存放下一个节点的地址
}NODE,*PNODE;
//使用typedef 来给每个节点起一个别名NODE代表的是struct Node 类型 PNODE代表的是struct Node*类型
PNODE Create_list();
void Treaverse_list(PNODE);//遍历链表
int main(void)
{
PNODE pList;
pList = Create_list();
Treaverse_list(pList);
return 0;
}
PNODE Create_list()
{
//首先定义一个带有头节点的单链表
PNODE pHead = (PNODE)malloc(sizeof(NODE));//分配动态内存
if (NULL == pHead)//判断是否分配到内存,若为NULL则分配内存失败,程序终止
{
printf("内存分配失败,程序终止\n");
exit(-1);
}
pHead->pNext = NULL;//将头节点的指针域置空
int flag = 1;//判断条件,通过flag来判断用户是否要继续添加元素
char str;//存放用户输入的数据
printf("请输入要存放的数据,以$结束:");//提示语句
while (flag)
{
str = getchar();//接受用户输入的数据
if (str != '$')
{
PNODE pNew = (PNODE)malloc(sizeof(NODE));//创建需要插入的新节点
if (NULL == pNew)//判断内存分配是否成功
{
printf("内存分配失败,程序终止\n");
exit(-1);
}
pNew->data = str;//将用户需要存放的数据存放在新节点的数据域中
pNew->pNext = pHead->pNext;//将新节点的指针域指向原先的第一个节点
pHead->pNext = pNew;//将头指针指向新节点完成头插法
}
else//用户输入了结束字符,终止循环
flag = 0;
}
return pHead;
}
void Treaverse_list(PNODE pHead)
{
PNODE p = pHead->pNext;//新定义一个节点存放链表中的第一个节点
while (NULL != p)//如果p不是空的就打印数据域中的数据,否则说明遍历完链表了
{
printf("%c", p->data);
p = p->pNext;//通过指针域来让节点P移动 依次遍历链表
}
printf("\n");
return;//表示函数结束
}
欢迎各位大佬批评指正!