在初学数据结构时,我第一次接触链表。作为一个初学C语言的小白,在我的认知里链表是一个可以被数组取代的鸡肋的东西。然而在深度学习链表之后,我发现链表在对数据的一些操作处理的时候会比数据更加方便,更有效率。现在我将我所了解的链表的功能分享出来供大家参考讨论,如有错误或补充,还请大家指出批评,我会积极学习并更改。
链表是一种存储结构,用来存储数据元素。它是由若干个节点组成,而所存数据的逻辑顺序是和节点顺序一样的。在链表中,每一个节点都是由数据域和指针域所构成,数据域存放的是该节点的数据元素,指针域存放的是该节点后一个节点的地址。这样做的好处是,相邻的数据在存储单元可以是连续的,也可以是不连续的,在查找数据元素时,也比顺序表效率高了很多。
typedef int datatype;
typedef struct Node //结点类型的创建
{
datatype data;
struct Node* next;
}Node,*pNode,List,*pList;
链表一些常见的使用如下
- void InitLinkList(pList* pplist); //初始化链表
void InitLinkList(pList* pplist)
{assert(pplist != NULL);
if (*pplist = NULL)
{
return;
}
else
{
pList cur = *pplist;
pList cur2 = NULL;
while (cur)
{
cur2 = cur->next;
free(cur);
cur = cur2;
}
*pplist = NULL;
}
return;
}
- pNode BuyNode(datatype d); //在链表中创建一个新节点
pNode BuyNode(datatype d)
{
pNode newnode;
newnode = malloc(sizeof(Node));
newnode->data = d;
newnode->next = NULL;
return newnode;
}
- void DestroyLinkList(pList* pplist); //注销一个链表
void DestroyLinkList(pList* pplist)
{
assert(pplist != NULL);
pList cur = *pplist;
pList cur2 = NULL;
while (cur)
{
cur2 = cur->next;
free(cur);
cur = cur2;
}
*pplist = NULL;
return;
}
- void PushBack(pList* pplist, datatype d); //尾部插入一个新节点
void PushBack(pList* pplist, datatype d)
{
assert(pplist != NULL);
pList cur = *pplist;
if (cur == NULL)
{
*pplist = BuyNode(d);
return;
}
while (cur->next)
{
cur = cur->next;
}
cur->next = BuyNode(d);
return;
}
- void printLinkList(pList* pplist); //打印一个链表
void printLinkList(pList* pplist)
{
assert(pplist != NULL);
pList cur = *pplist;
while (cur)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
return;
}
- void PopBack(pList* pplist); //尾部弹出一个节点
void PopBack(pList* pplist)
{
assert(pplist!= NULL);
pList cur = *pplist;
if (cur == NULL)
{
return;
}
else if (cur->next == NULL)
{
free(cur);
*pplist = NULL;
return;
}
else
{
while (cur->next->next)
{
cur = cur->next;
}
free(cur->next);
cur->next = NULL;
}
return;
}
- void PushFront(pList* pplist, datatype d); //头部插入一个新节点
void PushFront(pList* pplist, datatype d)
{
assert(pplist != NULL);
pList cur = *pplist;
if (cur == NULL)
{
*pplist = BuyNode(d);
return;
}
else
{
*pplist = BuyNode(d);
(*pplist)->next = cur;
}
return;
}
- void PopFront(pList* pplist); //头部弹出一个节点
void PopFront(pList* pplist)
{
assert(pplist != NULL);
if (*pplist == NULL)
{
return;
}
else if ((*pplist)->next == NULL)
{
free(*pplist);
*pplist = NULL;
}
else
{
pList cur = (*pplist)->next;
free(*pplist);
*pplist = cur;
}
return;
}
- pNode find(pList plist, datatype d); //根据数据找到节点
pNode find(pList plist, datatype d)
{
pList cur = plist;
while (cur != NULL)
{
if (cur->data == d)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
- void Insert(pList* pplist, pNode pos, datatype d); //在给定数据前加入一个新节点
void Insert(pList* pplist, pNode pos, datatype d)
{
assert(pplist != NULL);
pNode new = BuyNode(pos->data);
if (pos == NULL)
{
free(new);
return;
}
new->next = pos->next;
pos->next = new;
pos->data = d;
return;
}
- void Erase(pList* pplist, pNode pos); //删除一个给定位置的节点
void Erase(pList* pplist, pNode pos)
{
assert(pplist != NULL);
if (pos == NULL)
return;
pNode cur = pos;
while (cur->next->next != NULL)
{
cur->data = cur->next->data;
cur = cur->next;
}
cur->data = cur->next->data;
free(cur->next);
cur->next = NULL;
return;
}
- void Remove(pList* pplist, datatype d); //移除给定数据的节点(1个)
void Remove(pList* pplist, datatype d)
{
assert(pplist != NULL);
pList cur = *pplist;
while (cur != NULL)
{
if (cur->data == d)
{
Erase(pplist, cur);
return;
}
cur = cur->next;
}
return;
}
- void RemoveAll(pList* pplist, datatype d); //移除给定数据的节点(全部)
void RemoveAll(pList* pplist, datatype d)
{
assert(pplist != NULL);
pList cur = *pplist;
while (cur != NULL)
{
if (cur->data == d)
{
Erase(pplist, cur);
continue;
}
cur = cur->next;
}
return;
}
- void EraseNotTailNode(pNode pos); //移除一个非头节点
void EraseNotTailNode(pNode pos)
{
assert(pos->next != NULL);
pList cur = pos->next;
pos->data = cur->data;
pos->next = cur->next;
free(cur);
cur = NULL;
return;
}
- int GetListLength(pList plist); //链表的长度
int GetListLength(pList plist)
{
int i = 0;
pList cur = plist;
while (cur)
{
i++;
cur = cur->next;
}
return i;
}
- void PrintTailToHead(pList plist); //倒序打印链表
void PrintTailToHead(pList plist) // 从未到头打印单链表(递归)
{
if (plist == NULL)
return;
pList cur = plist;
if (cur->next != NULL)
PrintTailToHead(cur->next);
printf("%d ", cur->data);
return;
}
- void InsertNode(pList* pplist, pNode pos, datatype d);
- pNode JC(pList* pplist, int num); //用链表解决约瑟夫环问题
pNode JC(pList* pplist, int num) //单链表实现约瑟夫环
{
int i = 0;
assert(pplist != NULL);
pList cur = *pplist;
pList cur1 = *pplist;
while (cur->next != NULL)
{
cur = cur->next;
}
cur->next = cur1;
while (cur1->next != cur1)
{
i = num;
cur = cur1;
while (--i)
{
cur = cur->next;
}
cur1 = cur;
cur= cur1->next;
cur1->data = cur->data;
cur1->next = cur->next;
free(cur);
}
return cur1;
}
- void ReverseList(pList* pplist); //让链表倒序
void ReverseList(pList* pplist) //逆置单链表
{
assert(pplist != NULL);
if ((*pplist == NULL) && ((*pplist)->next == NULL))
return;
pList cur1 = *pplist;
pList cur2 = cur1->next;
pList cur = NULL;
cur1->next = NULL;
while (cur2 != NULL)
{
cur = cur2->next;
cur2->next = cur1;
cur1 = cur2;
cur2 = cur;
}
*pplist = cur1;
return;
}
- void BubbleSort(pList * pplist); //链表数据的有序排列
void BubbleSort(pList * pplist) // 单链表排序(冒泡)
{
assert(pplist != NULL);
pList cur1 = *pplist;
pList cur = *pplist;
while (cur->next != NULL)
{
cur = cur->next;
}
while (cur1->next != cur)
{
pList cur2 = cur1;
while (cur2->next != cur)
{
if ((cur2->data) > (cur2->next->data))
{
datatype a = cur2->data;
cur2->data = cur2->next->data;
cur2->next->data = a;
}
cur2 = cur2->next;
}
cur = cur2;
}
return;
}
- pNode Merge(pList* list1, pList* list2); //有序排列两个有序链表
pNode Merge(pList* list1, pList* list2) //合并两个有序单链表
{
pList cur = NULL;
pList cur1 = NULL;
pList cur2 = NULL;
pList cur11 = NULL;
if (((*list1)->data) < ((*list2)->data))
{
cur1 = *list1;
cur2 = *list2;
}
else
{
cur1 = *list2;
cur2 = *list1;
}
cur11 = cur1->next;
cur = cur1;
while (cur2 != NULL && cur11 != NULL)
{
if (cur2->data <= cur11->data)
{
pList cur22 = cur2->next;
cur1->next = cur2;
cur2->next = cur11;
cur1 = cur2;
cur2 = cur22;
}
else
{
cur1 = cur1->next;
cur11 = cur11->next;
}
}
if (cur1->next == NULL)
{
cur1->next = cur2;
}
return cur;
}
- pNode FindMidNode(pList* head); //找到链表的中间数据
pNode FindMidNode(pList* head) //查找单链表的中间节点,遍历一遍
{
assert(head != NULL);
pList cur1 = * head;
pList cur2 = * head;
while (cur2->next != NULL && cur2 != NULL)
{
cur1 = cur1->next;
cur2 = cur2->next->next;
}
return cur1;
}
- pNode CheckCycle(pList plist); //判断是否为带环链表以及找到环入口
pNode CheckCycle(pList plist)
{
pList cur1 = plist;
pList cur2 = plist;
if (plist->next == NULL && plist->next->next == NULL)
{
return NULL;
}
cur1 = plist->next;
cur2 = plist->next->next;
while (cur1 != cur2)
{
if (cur1->next == NULL && cur2->next == NULL && cur2->next->next == NULL)
{
return NULL;
}
cur1 = cur1->next;
cur2 = cur2->next->next;
}
cur1 = plist;
while (cur1 != cur2)
{
cur1 = cur1->next;
cur2 = cur2->next;
}
return cur1;
}