链表:一种链式存储的线性表,用一组地址任意的存储单元存放线性表的数据元素,称存储单元为一个字节。
链表分类:
- 单链表
- 双链表
- 双向循环链表
单链表
实现代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int DataType;
typedef struct ListNode{
DataType data;
struct ListNode *next;
} ListNode;
//初始化
void ListInit(ListNode **ppFirst)
{
assert(ppFirst != NULL);
*ppFirst = NULL;
}
//销毁
void ListDestroy(ListNode **ppFirst)
{
*ppFirst = NULL;
}
/*
增删查改
*/
struct ListNode *CreateNode(DataType data)
{
ListNode *newNode = (ListNode*)malloc(sizeof(ListNode));
assert(newNode);
newNode->data = data;
newNode->next = NULL;
return newNode;
}
//头插
void ListPushFront(ListNode **ppFirst,DataType data)
{
assert(ppFirst != NULL);
ListNode *newNode = CreateNode(data);
newNode->data = data;
newNode->next = *ppFirst;
*ppFirst = newNode;
}
// 尾插
void LisstPushBack(ListNode **ppFirst, DataType data)
{
ListNode *newNode = CreateNode(data);
// 特殊情况,链表为空
if (*ppFirst == NULL)
{
*ppFirst = newNode;
return;
}
// 通常情况
ListNode *cur = *ppFirst;
while (cur->next != NULL)
{
cur = cur->next;
}
// cur 就是最后一个结点
cur->next = newNode;
}
//头删
void ListPopFront(ListNode **ppFirst)
{
assert(ppFirst != NULL);
assert(*ppFirst != NULL);
ListNode *del = *ppFirst;
*ppFirst = (*ppFirst)->next;
free(del);
}
// 尾删
void ListPopBack(ListNode **ppFirst)
{
assert(ppFirst != NULL); // 变量地址不为空
assert(*ppFirst != NULL); // 不能是空链表
// 链表中只有一个结点
if ((*ppFirst)->next == NULL)
{
free(*ppFirst);
*ppFirst = NULL;
return;
}
// 正常情况
ListNode *del;
ListNode *cur = *ppFirst;
while (cur->next->next != NULL)
{
cur = cur->next;
}
del = cur->next;
cur->next = NULL;
free(del);
}
//查找
ListNode *ListFind(ListNode *first, DataType data)
{
//顺序查找,去遍历
for (ListNode *cur = first; cur != NULL; cur = cur->next){
if (cur->data == data){
return cur;
}
}
return NULL;
}
//在结点前做插入(结点 pos 肯定在链表中 && pos 不是空【链表不是空】)
void ListInsert(ListNode **ppFirst, ListNode *pos, DataType data)
{
//头插
if (*ppFirst == pos){
ListPushFront(ppFirst, data);
return;
}
ListNode *cur = *ppFirst;
//找到 pos 前一个结点
while (cur->next != pos){
cur = cur->next;
}
//插入新结点
ListNode *newNode = CreateNode(data);
newNode->next = pos;
cur->next = newNode;
}
//删除指定结点(结点 pos 肯定在链表中 && pos 不是空【链表不是空】)
void ListErase(ListNode **ppFirst, ListNode *pos)
{
//头删
if (*ppFirst == pos){
ListPopFront(ppFirst);
return;
}
ListNode *cur = *ppFirst;
//找到 pos 前一个结点
while (cur->next != pos){
cur = cur->next;
}
//删除结点
cur->next = pos->next;
free(pos);
}
// 打印链表
void ListPrint(ListNode *first)
{
for (ListNode *cur = first; cur != NULL; cur = cur->next) {
printf("%d -> ", cur->data);
}
printf("NULL\n");
}
测试函数与主函数:
void TestList()
{
ListNode *first = NULL;
ListInit(&first);
printf("头插:\n");
ListPushFront(&first, 4);
ListPushFront(&first, 3);
ListPushFront(&first, 2);
ListPushFront(&first, 1);
ListPrint(first);
printf("尾插:\n");
LisstPushBack(&first, 5);
LisstPushBack(&first, 6);
LisstPushBack(&first, 7);
ListPrint(first);
printf("头删:\n");
ListPopFront(&first);
ListPrint(first);
printf("尾删:\n");
ListPopBack(&first);
ListPrint(first);
printf("查找:\n");
ListFind(first, 5);
ListPrint(first);
ListFind(first, 100);
ListPrint(first);
printf("在指定定位置插入删除:\n");
ListNode *result = ListFind(first, 2);
ListInsert(&first, result, 0);
ListPrint(first);
ListErase(&first, result);
ListPrint(first);
}
int main()
{
TestList();
return 0;
}
双向循环链表
实现代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct DListNode
{
int data;
struct DListNode *prev;
struct DListNode *next;
} DListNode;
// 初始化
void DListInit(DListNode **ppHead)
{
assert(ppHead != NULL);
DListNode *pHead = (DListNode *)malloc(sizeof(DListNode));
pHead->next = pHead;
pHead->prev = pHead;
*ppHead = pHead;
}
// 保留头结点
void DListClear(DListNode *pHead)
{
DListNode *cur = pHead->next;
DListNode *next;
while (cur != pHead)
{
next = cur->next;
free(cur);
}
pHead->next = pHead;
pHead->prev = pHead;
}
// 销毁头结点
void DListDestroy(DListNode **ppHead)
{
DListClear(*ppHead);
free(*ppHead);
*ppHead = NULL;
}
void DListInsert(DListNode *pHead, DListNode *pos, int data)
{
DListNode *node = (DListNode *)malloc(sizeof(DListNode));
node->data = data;
node->prev = pos->prev;
node->next = pos;
pos->prev->next = node;
pos->prev = node;
}
// 头插
void DListPushFront(DListNode *pHead, int data)
{
DListInsert(pHead, pHead->next, data);
}
// 尾插
void DListPushBack(DListNode *pHead, int data)
{
DListInsert(pHead, pHead, data);
}
void DListErase(DListNode *pHead, DListNode *pos)
{
(void)pHead;
assert(pos != pHead);
pos->prev->next = pos->next;
pos->next->prev = pos->prev;
free(pos);
}
// 头删
void DListPopFront(DListNode *pHead)
{
// 链表为空,pHead->next == pHead;
DListErase(pHead,pHead->next);
}
// 尾删
void DListPopBack(DListNode *pHead)
{
DListErase(pHead, pHead->prev);
}