C语言中的链表作为一个重要的知识点,我觉得在进行链表的相关操作时首先要理解链表分三种,单向链表、双向链表、循环链表。
虽然说是三种,但其实本质都是一样的,就是在一个结构体里面有数据域和指针域,数据域中用来描述节点的信息,而指针域中用来指向上一个节点或者下一个节点。
分为按值添加和按位置添加
说明:
此添加、删除为按值添加、删除
下面请看代码:
添加分为链表中头节点的插入
在中间插入
尾插入
删除也分为头删除
中间删除
尾删除
一些细节上的处理:
传参时,如果要改变头节点,就传二级指针,不需要改变头节点,就传一级指针
单链表中有很多函数都需要分类导论,要考虑它只有一个节点或没有节点的极端情况
注意在不需要改变头节点时,万万不能随便解引用头节点以及连续写两个->next时,因为这种情况下很容易出现问题
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int id;
char* name;
struct Node* pNext;
}List;
void AddNode(List** pphead, List** ppend, int id, char* name)
{
List* ptemp =(List*) malloc(sizeof(List));
ptemp->id = id;
ptemp->name = name;
ptemp->pNext = NULL;
if (*pphead == NULL)
{
*pphead = ptemp;
}
else
{
(*ppend)->pNext = ptemp;
}
*ppend = ptemp;
}
void InsertNode(List** pphead, List** ppend, List* pNode, int n)
{
List* pmark = *pphead;
if ((*pphead)->id == n)
{
pNode->pNext = *pphead;
*pphead = pNode;
}
while (pmark != *ppend)
{
if (pmark->pNext->id == n)
{
pNode->pNext = pmark->pNext;
pmark->pNext = pNode;
return;
}
pmark = pmark->pNext;
}
(*ppend)->pNext = pNode;
*ppend = pNode;
}
void DeletNode(List** pphead, List** ppend, int n)
{
List* pDel = NULL;
List* pmark = *pphead;
if ((*pphead)->id == n)
{
pDel = *pphead;
(*pphead) = (*pphead)->pNext;
free(pDel);
pDel = NULL;
return;
}
while (pmark != (*ppend))
{
if (pmark->pNext->id == n)
{
pDel = pmark->pNext;
pmark->pNext = pDel->pNext;
free(pDel);
pDel = NULL;
if (pmark->pNext == NULL)
{
*ppend = pmark;
}
return;
}
pmark = pmark->pNext;
}
}
int main()
{
List* phead = NULL;
List* pend = NULL;
AddNode(&phead, &pend, 1, "aa");
AddNode(&phead, &pend, 2, "bb");
AddNode(&phead, &pend, 3, "cc");
AddNode(&phead, &pend, 4, "dd");
AddNode(&phead, &pend, 5, "ee");
List* p =(List*) malloc(sizeof(List));
p->id = 7;
p->name = "gg";
p->pNext = NULL;
/*InsertNode(&phead, &pend, p, 9);*/
DeletNode(&phead, &pend, 5);
while (phead != NULL)
{
printf("%d %s\n", phead->id, phead->name);
phead = phead->pNext;
}
return 0;
}
输出:
1 aa
2 bb
3 cc
4 dd
D:\c++\c语言\结构体 链表\x64\Debug\结构体 链表.exe (进程 15672)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
总结:
链表和数组作为算法中的两个基本数据结构,在程序设计过程中经常用到。尽管两种结构都可以用来存储一系列的数据,但又各有各的特点。
数组的优势,在于可以方便的遍历查找需要的数据。在查询数组指定位置(如查询数组中的第4个数据)的操作中,只需要进行1次操作即可,时间复杂度为O(1)。但是,这种时间上的便利性,是因为数组在内存中占用了连续的空间,在进行类似的查找或者遍历时,本质是指针在内存中的定向偏移。然而,当需要对数组成员进行添加和删除的操作时,数组内完成这类操作的时间复杂度则变成了O(n)。