转载自https://blog.csdn.net/weixin_43866583/article/details/127069907?spm=1001.2014.3001.5502
链表是什么
链表是编程语言中常见的一种数据结构,它可以实现动态的创建和删除,只要内存足够,链表的数量和长度是可以无限多和无限长的。
链表顾名思义是一种链式的数据结构,它由一个个节点组成,并通过节点之间的互相关联链接,形成了类似一条链式的结构。
链表的节点一般可以分为数据域和指针域。数据域中是存放节点数据的,往往链表的节点都是结构体类型的,可以方便定义多种不同的数据类型,便于使用。指针域是存放节点的指针的,是链表中每个节点能互相串联起来的关键,这个至关重要!

单向链表
单向链表根据使用情况还分为单向不循环链表、单向循环链表两种。
单向不循环链表
单向不循环链表是一种单向的链式结构,节点之间通过指针域互相关联,最后一个节点的指针域为空(NULL)

*先定义一个链表的节点*
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| typedef struct LinkData_struct { int weight; int hight; }LinkData_t;
typedef struct LinkNode_Struct { LinkData_t data; struct LinkNode_Struct *Next; }LinkNode_t;
|
*定义一个单向链表的头结点*
1 2
| LinkNode_t AppleInfo_head;
|
*初始化单向链表*
1 2 3 4 5
| void Init_LinkNode(LinkNode_t * HeadNode) { HeadNode->Next = NULL; }
|
*创建链表节点并接入到链表中*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| LinkNode_t * LinkNode_Create(LinkNode_t * HeadNode, LinkData_t *InsetData) { LinkNode_t *Node,*pf; LinkNode_t *xReturn = NULL; Node = (LinkNode_t *)malloc(sizeof(LinkNode_t)); if (Node == NULL) { printf("节点创建失败!!!\r\n"); return NULL; } pf = HeadNode; while(pf->Next != NULL) { pf = pf->Next; } pf->Next = Node; Node->Next = NULL; Node->data.hight = InsetData->hight; Node->data.weight = InsetData->weight; xReturn = Node; printf("完成一个链表节点的创建,地址 = 0x%X\r\n",xReturn); return xReturn; }
|
*删除链表中的节点*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| void destroy_LinkNode(LinkNode_t * HeadNode, int weight) { int deleteFlag = 0; LinkNode_t *pf,*preStre; pf = preStre = HeadNode; do { if (pf->data.weight == weight){ deleteFlag = 1; break; } preStre = pf; pf = pf->Next; }while (pf->Next != NULL); if (!deleteFlag) { printf("找不到这个节点!!!\r\n"); } else { if(pf->Next == NULL) { preStre->Next = NULL; } else { preStre->Next = pf->Next; } free(pf); printf("节点weight = %d 销毁成功!\r\n",weight); } }
|
*输出整条链表的数据*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void print_LinkNode_Info(LinkNode_t * HeadNode) { int length = 0; LinkNode_t *pf = HeadNode; if (pf->Next == NULL) { printf("该链表长度为零,不能输出结果!\r\n"); return; } do { pf = pf->Next; printf("weight = %d\r\n", (int)pf->data.weight); printf("height = %d\r\n", (int)pf->data.hight); printf("\r\n"); length++; }while (pf->Next != NULL); printf("链表输出完成。长度为:%d\r\n",length); }
|
*按条件查询链表中某个节点的数据*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| void search_LinkNode_Info(LinkNode_t * HeadNode, int weight) { int length = 0; char search_flag = 0; LinkNode_t *pf = HeadNode; if (pf->Next == NULL) { printf("该链表长度为零,不能输出结果!\r\n"); return; } do { pf = pf->Next; if(pf->data.weight == weight) { search_flag = 1; printf("weight = %d\r\n", (int)pf->data.weight); printf("height = %d\r\n", (int)pf->data.hight); printf("\r\n"); } length++; }while (pf->Next != NULL); if(search_flag) { printf("链表查找结束。所在节点位置为:%d\r\n",length); } else { printf("整个链表中无满足此条件的节点!\r\n"); } }
|
单向循环链表
单向循环链表是一种单向的可回头的链表,节点之间通过指针域互相关联,最后一个节点的指针域为头结点的地址。

*先定义一个链表的节点*
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| typedef struct LinkData_struct { int weight; int hight; }LinkData_t;
typedef struct LinkNode_Struct { LinkData_t data; struct LinkNode_Struct *Next; }LinkNode_t;
|
*定义一个单向链表的头结点*
1 2
| LinkNode_t AppleInfo_head;
|
*初始化单向链表*
1 2 3 4 5
| void Init_LinkNode(LinkNode_t * HeadNode) { HeadNode->Next = HeadNode; }
|
*创建链表节点并接入到链表中*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| LinkNode_t * LinkNode_Create(LinkNode_t * HeadNode, LinkData_t *InsetData) { LinkNode_t *Node,*pf; LinkNode_t *xReturn = NULL; Node = (LinkNode_t *)malloc(sizeof(LinkNode_t)); if (Node == NULL) { printf("节点创建失败!!!\r\n"); return NULL; } pf = HeadNode; while(pf->Next != HeadNode) { pf = pf->Next; } pf->Next = Node; Node->Next = HeadNode; Node->data.hight = InsetData->hight; Node->data.weight = InsetData->weight; xReturn = Node; printf("完成一个链表节点的创建,地址 = 0x%X\r\n",xReturn); return xReturn; }
|
*删除链表中的节点*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| void destroy_LinkNode(LinkNode_t * HeadNode, int weight) { int deleteFlag = 0; LinkNode_t *pf,*preStre; pf = preStre = HeadNode; do { preStre = pf; pf = pf->Next; if (pf->data.weight == weight){ deleteFlag = 1; break; } }while (pf->Next != HeadNode); if (!deleteFlag) { printf("找不到这个节点!!!\r\n"); } else { if(pf->Next == HeadNode) { preStre->Next = HeadNode; } else { preStre->Next = pf->Next; } free(pf); printf("节点weight = %d 销毁成功!\r\n",weight); } }
|
*输出整条链表的数据*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void print_LinkNode_Info(LinkNode_t * HeadNode) { int length = 0; LinkNode_t *pf = HeadNode; if (pf->Next == HeadNode) { printf("该链表长度为零,不能输出结果!\r\n"); return; } do { pf = pf->Next; printf("weight = %d\r\n", (int)pf->data.weight); printf("height = %d\r\n", (int)pf->data.hight); printf("\r\n"); length++; }while (pf->Next != HeadNode); printf("链表输出完成。长度为:%d\r\n",length); }
|
*按条件查询链表中某个节点的数据*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| void search_LinkNode_Info(LinkNode_t * HeadNode, int weight) { int length = 0; char search_flag = 0; LinkNode_t *pf = HeadNode; if (pf->Next == HeadNode) { printf("该链表长度为零,不能输出结果!\r\n"); return; } do { pf = pf->Next; if(pf->data.weight == weight) { search_flag = 1; printf("weight = %d\r\n", (int)pf->data.weight); printf("height = %d\r\n", (int)pf->data.hight); printf("\r\n"); } length++; }while (pf->Next != HeadNode); if(search_flag) { printf("链表查找结束。所在节点位置为:%d\r\n",length); } else { printf("整个链表中无满足此条件的节点!\r\n"); } }
|
单向不循环链表和单向循环链表基本是相同的,不同之处主要在于尾节点的指针域不同。单向不循环链表的尾节点的指针域为空,到尾节点的位置链表就结束了;单向循环链表的尾节点保存的是头节点的地址,从尾节点可以知道首节点的位置,形成一种循环的链式结构。