引言:C语言链表在开发过程十分重要,以下为详细的实现过程,包括单向链表、双向链表,含头节点链表,不含头节点链表。
1 单向链表实现(有表头,表头未存储数据)
1.1 单项链表构造
typedef struct Node //单链表定义
{
int data;//先以基本数据类型为例,后再分析复杂数据类型
struct Node *next;
} Node;
1.2 创建单链表表头,此表头不含有效数据
Node *headNode() //单链表创建表头(不存储有效数据)
{
Node *node = (Node *)malloc(sizeof(Node)); //向堆区申请内存
node->data = 0;
node->next = NULL; // next指向下一个节点,node指向的是当前节点
return node; //返回头节点
}
1.3 根据数据创建节点
Node *createSingleNode(int data) //单链表创建节点
{
Node *node = (Node *)malloc(sizeof(Node));
node->data = data;
node->next = NULL;
return node;
}
1.4-1 头插插入节点,即新插入的节点链接在head后面
Node *insertSingleNodeByHead(int data, Node *headNode) //单链表有表头头插法
{
Node *node = createSingleNode(data);
node->next = headNode->next;
headNode->next = node;
return node;
}
1.4-2 尾插插入节点,即新插入的节点链接在最后一个节点之后
Node *insertSingleNodeByTail(int data, Node *headNode) //单链表尾插法
{
Node *node = createSingleNode(data);
Node *pointer = headNode;
while (pointer->next)
pointer = pointer->next;
pointer->next = node;
node->next = NULL;
return node;
}
1.5 删除data对应的首个节点
int deleteSingleNode(int deleteData, Node *headNode) //单链表删除节点
{
Node *pointer = headNode;
while (pointer->next)
{
if (pointer->next->data == deleteData)
{
Node *deleteNode = pointer->next;
pointer->next = pointer->next->next;
free(deleteNode);//释放删除节点占用的堆内存
return 1;
}
pointer = pointer->next;
}
return 0;//删除失败返回0
}
1.6 单链表遍历
void printfList(void *list)//为方便函数回调,写此函数方便提供程序的可扩展性
{
Node *node = (void *)list;
printf("%d->\t", node->data);
}
void listNode(Node *headNode, int withEmptyHeadNode, void (*printfList)(void *)) //节点遍历
{
Node *pointer = (withEmptyHeadNode == 1 ? headNode->next : headNode);//头节点data是否有效,无效为1
while (pointer)
{
printfList(pointer);
pointer = pointer->next;
}
puts("\n");
}
1.7 代码运行
#include <stdio.h>
#include <stdlib.h>
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6};
Node *head = headNode();//头节点创建
for (int i = 0; i < 3; i++)
insertSingleNodeByHead(arr[i], head);//头插节点
listNode(head, 1, printfList);
for (int i = 3; i < 6; i++)
insertSingleNodeByTail(arr[i], head);//尾插节点
listNode(head, 1, printfList);
for (int i = 2; i < 4; i++)
deleteSingleNode(arr[i], head);//删除节点
listNode(head, 1, printfList);//遍历节点
return 0;
}
结果如下:
2 单向链表实现(未创建不含数据的表头,首节点直接存储了数据)
2.1 单项链表的构造,与节点创建,及尾插节点,和含空数据标头的链表创建一致,代码如下
typedef struct Node//结构体构造单链表
{
int data;
struct Node *next;
} Node;
Node *createSingleNode(int data)//创建data的单链表节点
{
Node *node = (Node *)malloc(sizeof(Node));
node->data = data;
node->next = NULL;
return node;
}
void insertSingleNodeByTail(int data, Node *firstNode)//尾插节点,因为首地址不变,传一级指针即可
{
Node *node = createSingleNode(data);
Node *pointer = firstNode;
while (pointer->next)
pointer = pointer->next;
pointer->next = node;
node->next = NULL;
}
2.2 头插节点,由于头插导致链表首节点地址在不断变化,即Node *head变化,需要传一级指针的地址Node **firstNode作为入参
void insertSingleNodeByHead(int data, Node **firstNode)
{
Node *node = createSingleNode(data);
node->next = *firstNode;
*firstNode = node;
}
2.3 节点删除,考虑到首节点可能被删除,入参需为二级指针
int deleteSingleNode(int data, Node **firstNode)//首节点存在删除可能,因此需要传址
{
if (firstNode == NULL)
return 0;
if ((*firstNode)->data == data)
{
Node *deleteNode = *firstNode;
*firstNode = (*firstNode)->next;
free(deleteNode);
return 1;
}
Node *pointer = *firstNode;
while (pointer->next)
{
if (pointer->next->data == data)
{
Node *deleteNode = pointer->next;//pointer->next为需要删除的节点
pointer->next = pointer->next->next;
free(deleteNode);
return 1;
}
pointer = pointer->next;
}
return 0;
}
2.4 链表遍历及代码实现和含空数据头节点链表一致
#include <stdio.h>
#include <stdlib.h>
void printfList(void *list) //为方便函数回调,写此函数方便提供程序的可扩展性
{
Node *node = (void *)list;
printf("%d->\t", node->data);
}
void listNode(Node *headNode, int withEmptyHeadNode, void (*printfList)(void *)) //节点遍历
{
Node *pointer = (withEmptyHeadNode == 1 ? headNode->next : headNode); //头节点data是否有效,无效为1
while (pointer)
{
printfList(pointer);
pointer = pointer->next;
}
puts("\n");
}
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6};
Node *firstNode = createSingleNode(arr[0]);//创建含有效数据的首节点
for (int i = 1; i < 4;i++)
insertSingleNodeByHead(arr[i], &firstNode);//头插
listNode(firstNode, 0, printfList);//遍历
for (int i = 4; i < 6;i++)
insertSingleNodeByTail(arr[i], firstNode);//尾插
listNode(firstNode, 0, printfList);
for (int i = 4; i < 6;i++)
deleteSingleNode(arr[i], &firstNode);//删除后两个节点
listNode(firstNode, 0, printfList);
for (int i = 2; i < 4;i++)
deleteSingleNode(arr[i], &firstNode);//删除前两个节点(arr[2]和arr[3])
listNode(firstNode, 0, printfList);
return 0;
}
结果如下
3 双向链表实现(有表头,表头未存储数据)
3.1 双向链表构造
typedef struct Node
{
int data;
struct Node *pre; //前驱节点
struct Node *next; //后继节点
} Node;
3.2 创建双向链表表头
Node *headNode()
{
Node *node = (Node *)malloc(sizeof(Node));
node->next = node; //头节点的前后指向均为自身
node->pre = node;
node->data = 0; //仅为初始化,非有效数据
return node;
}
3.3 根据data创建节点
Node *createSingleNode(int data)
{
Node *node = (Node *)malloc(sizeof(Node));
node->data = data;
node->next = NULL;
node->pre = NULL;
return node;
}
3.4 向双向链表插入节点,分为头插和尾插
void insertSingleNodeByTail(int data, Node *head)//尾插节点
{
Node *node = createSingleNode(data);
Node *pointer = head;
while (pointer.next != head) //最后一个节点next指向head
pointer = pointer->next;
node->next = head; // node作为尾节点,next指向head
head.pre = node;
pointer.next = node; // pointer为原链表最后一个节点,next应指向新节点
node.pre = pointer;
}
void insertSingleNodeByHead(int data, Node *head)//头插节点
{
Node *node = createSingleNode(data);
Node *headPointer = head;
node.pre = headPointer;
node->next = headPointer.next;//新节点next指向原head后的首个节点
headPointer->next->pre = node;
headPointer->next = node;//头节点next指向新节点
}
3.5 删除data对应的首个节点
int deleteSingleNode(int data, Node *head)
{
Node *pointer = head.next;
while (pointer!= head)
{
if (pointer->data == data)//pointer即为需要删除的节点
{
pointer.pre.next = pointer.next;
pointer.next.pre = pointer.pre;
free(pointer);//释放pointer占用的堆内存
return 1;
}
pointer = pointer.next;
}
return 0;//删除失败返回0
}
双向链表的实现比较简单,不再写主函数。