数据结构之单链表(有表头)
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。
链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象)+指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
C语言实现一个有表头(头节点不存放数据)的单链表
1.首先用一个结构体描述数据的节点
//定义节点结构
struct Node
{
int data; //存储int类型的数据
struct Node*next; //结构体指针
};
2.创建一个表头去表示整个链表
struct Node*createListHead()
{
//1.赋值结构体变量
//2.指针如何变成变量-->动态内存申请
struct Node*listHead = (struct Node*)malloc(sizeof(struct Node));
//为结构体变量初始化
//差异化处理,表头不使用数据,无表头链表就要加上下面的语句
//listHead->data=0;
listHead->next = NULL;
return listHead;
}
3.创建结点,为插入做准备
struct Node*createNewNode(int data)
{
//到后面你会发现单独创建一个节点时有很大好处的
struct Node*NewNode = (struct Node*)malloc(sizeof(struct Node));
NewNode->data = data;
NewNode->next = NULL;
return NewNode;
}
4.链表的插入–头插法
void insertNodeByHead(struct Node*listHeadNode, int data)
{
struct Node*newNode = createNewNode(data);
newNode->next = listHeadNode->next; //这是第一步
listHeadNode->next = newNode; //这是第二步
}
5.链表的插入–尾插法
void insertNodeBytail(struct Node*listHeadNode, int data)
{
struct Node*newNode = createNewNode(data);
struct Node*tailNode = listHeadNode;
//先要找到链表的尾巴
while (tailNode->next != NULL)
{
tailNode = tailNode->next;
}
tailNode->next = newNode;
}
6.链表的插入–指定位置插入
void insertNodeByappion(struct Node*listHeadNode, int data, int posData)
{
struct Node*posNodeFront = listHeadNode; //指定位置前面的结点
struct Node*posNode = listHeadNode->next; //指定位置
if (posNode == NULL)
{
printf("链表为空");
system("pause");
return;
}
else
{
while (posNode->data != posData)
{
posNodeFront = posNode;
posNode = posNodeFront->next;
if (posNode == NULL)
{
printf("指定位置无法删除!");
system("pause");
return;
}
}
struct Node*newNode = createNewNode(data);
newNode->next = posNode;
posNodeFront->next = newNode;
}
}
7.表头删除
void deleteNodeByhead(struct Node*listHeadNode)
{
struct Node*deleteNode = listHeadNode->next;
listHeadNode->next = deleteNode->next;
free(deleteNode);
}
8.表尾删除
void deleteNodebytail(struct Node*listheadNode)
{
struct Node*tailNode = listheadNode;
struct Node*tailNodeFront = NULL;
while (tailNode->next != NULL)
{
tailNodeFront = tailNode;
tailNode = tailNode->next;
}
free(tailNode);
tailNode = NULL;
tailNodeFront->next = NULL;
}
9.指定位置删除
void deleteNodeByAppion(struct Node*listHeadNode, int posData)
{
struct Node*posNodeFront = listHeadNode; //指定位置前面的结点
struct Node*posNode = listHeadNode->next; //指定位置
if (posNode == NULL)
{
printf("链表为空");
system("pause");
return;
}
else
{
while (posNode->data != posData)
{
posNodeFront = posNode; //上一次把posNode写成了posData 导致程序会闪停
posNode = posNodeFront->next;
if (posNode == NULL)
{
printf("未找到相关信息!");
system("pause");
return;
}
}
posNodeFront->next = posNode->next;
free(posNode);
posNode = NULL;
}
}
10.查找函数–>按数据查找
struct Node*serchInfo(struct Node*listHeadNode, int posData)
{
struct Node*pMove = listHeadNode;
while (pMove != NULL&&pMove->data != posData)
{
pMove = pMove->next;
}
return pMove;
}
11.打印链表
void printfList(struct Node*listHeadNode)
{
struct Node*pMove = listHeadNode->next; //从第二个结点开始打印,因为第一个结点的数据是空
while (pMove)
{
printf("%d\t", pMove->data);
pMove = pMove->next;
}
printf("\n");
}
测试代码
int main()
{
struct Node*headNode = createListHead();
printf("这是头插法:\n");
for (int i = 1;i < 4;i++)
{
insertNodeByHead(headNode, i);
}
printfList(headNode);
printf("这是尾插法:\n");
for (int i = 1;i < 4;i++)
{
insertNodeBytail(headNode, i);
}
printfList(headNode);
printf("这是指定位置插入:\n");
insertNodeByappion(headNode, 8, 9);
printfList(headNode);
printf("表头法删除:\n");
deleteNodeByhead(headNode);
printfList(headNode);
printf("表尾法删除:\n");
deleteNodebytail(headNode);
printfList(headNode);
printf("指定位置删除:\n");
deleteNodeByAppion(headNode, 2);
printfList(headNode);
system("pause");
return 0;
}
这是运行结果
以上就是单链表基本的增、删、改、查操作,虽然看起来实现步骤有点多,但是实际应用往往都是几种方法结合使用,所以介绍了多种函数实现一种功能。