链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。在逻辑结构上,也就是我们通过画图的方式画出链表,从大体上来看像一条链子。
实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:
头指针不存储数据
虽然有那么多链表的结构,但是我们在实际中最常用还是下面这两种结构:
因为无头单向非循环链表实现增删查改的函数与用带头双向循环链表实现的原理差不多,所以在这里只是讲解用带头双向循环链表实现增删查改的函数,而用无头单向非循环链表实现的代码在文章的末尾有展现,带头双向循环链表实现的代码在文章的末尾也有展现
typedef int LTDataType;
typedef struct ListNode
{
LTDataType _data;
struct ListNode* _next;
struct ListNode* _prev;
}ListNode;
// 创建返回链表的头结点.
ListNode* ListCreate();
// 双向链表销毁
void ListDestory(ListNode* pHead);
// 双向链表打印
void ListPrint(ListNode* pHead);
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* pHead);
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);
ListNode* ListCreate()
{
ListNode* head = (ListNode*)malloc(sizeof(ListNode));
head->next = head;
head->prev = head;
return head;
}
ListNode* BuyListNode(LTDataType x)
{
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
node->data = x;
node->next = NULL;
node->prev = NULL;
return node;
}
void ListPushBack(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListNode* newnode = BuyListNode(x);
ListNode* tail = pHead->prev;
tail->next = newnode;
newnode->prev = tail;
newnode->next = pHead;
pHead->prev = newnode;
}
void ListPrint(ListNode* pHead)
{
assert(pHead);
ListNode* cur = pHead->next;
while (cur != pHead)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("\n");
}
void ListPopBack(ListNode* pHead)
{
assert(pHead);
ListNode* tail = pHead->prev;
ListNode* tailPrev = tail->prev;
tailPrev->next = pHead;
pHead->prev = tailPrev;
free(tail);
//下方代码可读性较差
/*ListNode* tail = pHead->prev;
pHead->prev = tail->prev;
tail->prev->next = pHead;
free(tail);*/
ListErase(pHead->prev);
}
void ListPushFront(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListNode* newnode = BuyListNode(x);
ListNode* first = pHead->next;
pHead->next = newnode;
newnode->prev = pHead;
newnode->next = first;
first->prev = newnode;
//下方代码可读性较差
/*ListNode* newNode = BuyListNode(x);
newNode->next = pHead->next;
pHead->next->prev = newNode;
pHead->next = newNode;
newNode->prev = pHead;*/
}
void ListPopFront(ListNode* pHead)
{
assert(pHead && pHead->next != pHead);
ListNode* del = pHead->next;
ListNode* delnext = del->next;
pHead->next = delnext;
delnext->prev = pHead;
free(del);
del = NULL;
}
ListNode* ListFind(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListNode* cur = pHead->next;
while (cur != pHead)
{
if (cur->data == x)
return cur;
cur = cur->next;
}
return NULL;
}
void ListInsert(ListNode* pos, LTDataType x)
{
assert(pos);
ListNode* prev = pos->prev;
ListNode* newnode = BuyListNode(x);
// prev newnode pos
prev->next = newnode;
newnode->prev = prev;
newnode->next = pos;
pos->prev = newnode;
}
void ListErase(ListNode* pos)
{
assert(pos);
ListNode* prev = pos->prev;
ListNode* next = pos->next;
prev->next = next;
next->prev = prev;
free(pos);
}
void ListDestroy(ListNode* pHead)
{
ListNode* cur = pHead->next;
while (cur != pHead)
{
ListNode* next = cur->next;
free(cur);
cur = next;
}
free(pHead);
}
typedef int SLTDateType;
typedef struct SListNode
{
SLTDateType data;
struct SListNode* next;
}SListNode;
// 动态申请一个节点
SListNode* BuySListNode(SLTDateType x);
// 单链表打印
void SListPrint(SListNode* plist);
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x);
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x);
// 单链表的尾删
void SListPopBack(SListNode** pplist);
// 单链表头删
void SListPopFront(SListNode** pplist);
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x);
// 单链表在pos位置之后插入x
//单链表没有prev指针,但有next指针,故而找到pos位置的下一节点的地址较为简单
void SListInsertAfter(SListNode* pos, SLTDateType x);
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos);
// 单链表的销毁
void SListDestroy(SList* plist);
#include "SList.h"
SListNode* BuySListNode(SLTDateType x)
{
SListNode* node = (SListNode*)malloc(sizeof(SListNode));
node->data = x;
node->next = NULL;
return node;
}
void SListPrint(SListNode* plist)
{
SListNode* cur = plist;
while (cur)
//while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
void SListPushBack(SListNode** pplist, SLTDateType x)
{
SListNode* newnode = BuySListNode(x);
if (*pplist == NULL)
{
*pplist = newnode;
}
else
{
SListNode* tail = *pplist; //赋值不能是(*pplist)->next,因为(*pplist)->next可能为空
while (tail->next != NULL)
{
tail = tail->next;
}
tail->next = newnode;
}
}
void SListPopBack(SListNode** pplist)
{
SListNode* prev = NULL;
SListNode* tail = *pplist;
// 1.空、只有一个节点
// 2.两个及以上的节点
if (tail == NULL || tail->next == NULL)
{
free(tail);
*pplist = NULL;
}
else
{
while (tail->next)
{
prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;
}
}
void SListPushFront(SListNode** pplist, SLTDateType x)
{
assert(pplist);
// 1.空
// 2.非空
SListNode* newnode = BuySListNode(x);
if (*pplist == NULL)
{
*pplist = newnode;
}
else
{
newnode->next = *pplist; //pplist前需加'*'
*pplist = newnode;
}
}
void SListPopFront(SListNode** pplist)
{
// 1.空
// 2.一个
// 3.两个及以上
SListNode* first = *pplist;
if (first == NULL)
{
return;
}
else if (first->next == NULL)
{
free(first);
*pplist = NULL;
}
else
{
SListNode* next = first->next;
free(first);
*pplist = next;
}
}
SListNode* SListFind(SListNode* plist, SLTDateType x)
{
SListNode* cur = plist;
while (cur)
{
if (cur->data == x)
return cur;
cur = cur->next;
}
return NULL;
}
void SListInsertAfter(SListNode* pos, SLTDateType x)
{
assert(pos);
SListNode* next = pos->next;
// pos newnode next
SListNode* newnode = BuySListNode(x);
pos->next = newnode;
newnode->next = next;
}
void SListEraseAfter(SListNode* pos)
{
assert(pos);
// pos next nextnext
SListNode* next = pos->next;
if (next != NULL)
{
SListNode* nextnext = next->next;
free(next);
pos->next = nextnext;
}
}
void SListDestroy(SListNode* plist)
{
assert(plist);
SListNode* next = plist->next;
while (next != NULL)
{
free(plist);
plist = next;
next = next->next;
}
free(plist);
}
#define _CRT_SECURE_NO_WARNINGS
#include"SList.h"
//尾插测试
void test1()
{
SListNode* sl = NULL;
SListPushBack(&sl, 1);
SListPrint(sl);
SListPushBack(&sl, 2);
SListPrint(sl);
SListPushBack(&sl, 3);
SListPrint(sl);
SListPushBack(&sl, 4);
SListPrint(sl);
SListPushBack(&sl, 5);
SListPrint(sl);
}
//头插测试
void test2()
{
SListNode* sl = NULL;
SListPushFront(&sl, 1);
SListPrint(sl);
SListPushFront(&sl, 2);
SListPrint(sl);
SListPushFront(&sl, 3);
SListPrint(sl);
SListPushFront(&sl, 4);
SListPrint(sl);
SListPushFront(&sl, 5);
SListPrint(sl);
}
//尾删测试
void test3()
{
SListNode* sl = NULL;
SListPushFront(&sl, 1);
SListPushFront(&sl, 2);
SListPushFront(&sl, 3);
SListPushFront(&sl, 4);
SListPushFront(&sl, 5);
SListPrint(sl);
SListPopBack(&sl);
SListPrint(sl);
SListPopBack(&sl);
SListPrint(sl);
SListPopBack(&sl);
SListPrint(sl);
SListPopBack(&sl);
SListPrint(sl);
SListPopBack(&sl);
//SListPrint(sl);
}
//头删测试
void test4()
{
SListNode* sl = NULL;
SListPushFront(&sl, 1);
SListPushFront(&sl, 2);
SListPushFront(&sl, 3);
SListPushFront(&sl, 4);
SListPushFront(&sl, 5);
SListPrint(sl);
SListPopFront(&sl);
SListPrint(sl);
SListPopFront(&sl);
SListPrint(sl);
SListPopFront(&sl);
SListPrint(sl);
SListPopFront(&sl);
SListPrint(sl);
SListPopFront(&sl);
//SListPrint(sl);
}
void test5()
{
SListNode* sl = NULL;
SListPushFront(&sl, 1);
SListPushFront(&sl, 2);
SListPushFront(&sl, 3);
SListPushFront(&sl, 4);
SListPushFront(&sl, 5);
SListPrint(sl);
//查找测试
SListNode* find = SListFind(sl, 4);
if (find == NULL)
printf("找不到\n");
else
printf("%d\n", find->data);
//指定位置插入测试
SListInsertAfter(find, 40);
SListPrint(sl);
find = SListFind(sl, 1);
SListInsertAfter(find, 10);
SListPrint(sl);
find = SListFind(sl, 5);
SListInsertAfter(find, 50);
SListPrint(sl);
printf("\n");
//指定位置删除测试
find = SListFind(sl, 4);
SListEraseAfter(find, 40);
SListPrint(sl);
find = SListFind(sl, 1);
SListEraseAfter(find, 10);
SListPrint(sl);
find = SListFind(sl, 5);
SListEraseAfter(find, 50);
SListPrint(sl);
//销毁测试
find = SListFind(sl, 3);
SListDestroy(sl);
//SListPrint(sl);
SListPrint(find);
}
int main()
{
test5();
return 0;
}
typedef int LTDataType;
typedef struct ListNode
{
LTDataType _data;
struct ListNode* _next;
struct ListNode* _prev;
}ListNode;
// 创建返回链表的头结点.
ListNode* ListCreate();
// 双向链表销毁
void ListDestory(ListNode* pHead);
// 双向链表打印
void ListPrint(ListNode* pHead);
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* pHead);
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);
#include "List.h"
ListNode* BuyListNode(LTDataType x)
{
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
node->data = x;
node->next = NULL;
node->prev = NULL;
return node;
}
ListNode* ListCreate()
{
ListNode* head = (ListNode*)malloc(sizeof(ListNode));
head->next = head;
head->prev = head;
return head;
}
void ListPrint(ListNode* pHead)
{
assert(pHead);
ListNode* cur = pHead->next;
while (cur != pHead)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("\n");
}
void ListDestroy(ListNode* pHead)
{
ListNode* cur = pHead->next;
while (cur != pHead)
{
ListNode* next = cur->next;
free(cur);
cur = next;
}
free(pHead);
}
void ListPushBack(ListNode* pHead, LTDataType x)
{
assert(pHead);
//ListNode* newnode = BuyListNode(x);
phead tail newnode
//ListNode* tail = pHead->prev;
//tail->next = newnode;
//newnode->prev = tail;
//newnode->next = pHead;
//pHead->prev = newnode;
ListInsert(pHead, x);
}
void ListPushFront(ListNode* pHead, LTDataType x)
{
assert(pHead);
//ListNode* newnode = BuyListNode(x);
//ListNode* first = pHead->next;
//pHead->next = newnode;
//newnode->prev = pHead;
//newnode->next = first;
//first->prev = newnode;
/*ListNode* newNode = BuyListNode(x);
newNode->next = pHead->next;
pHead->next->prev = newNode;
pHead->next = newNode;
newNode->prev = pHead;*/
ListInsert(pHead->next, x);
}
void ListPopBack(ListNode* pHead)
{
assert(pHead);
//ListNode* tail = pHead->prev;
//ListNode* tailPrev = tail->prev;
pHead tailPrev tail
//tailPrev->next = pHead;
//pHead->prev = tailPrev;
//free(tail);
/*ListNode* tail = pHead->prev;
pHead->prev = tail->prev;
tail->prev->next = pHead;
free(tail);*/
ListErase(pHead->prev);
}
void ListPopFront(ListNode* pHead)
{
assert(pHead && pHead->next != pHead);
ListNode* del = pHead->next;
ListNode* delnext = del->next;
pHead->next = delnext;
delnext->prev = pHead;
free(del);
del = NULL;
}
void ListPopFront(ListNode* pHead)
{
//...
ListErase(pHead->next);
}
ListNode* ListFind(ListNode* pHead, LTDataType x)
{
assert(pHead);
ListNode* cur = pHead->next;
while (cur != pHead)
{
if (cur->data == x)
return cur;
cur = cur->next;
}
return NULL;
}
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x)
{
assert(pos);
ListNode* prev = pos->prev;
ListNode* newnode = BuyListNode(x);
// prev newnode pos
prev->next = newnode;
newnode->prev = prev;
newnode->next = pos;
pos->prev = newnode;
}
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{
assert(pos);
ListNode* prev = pos->prev;
ListNode* next = pos->next;
prev->next = next;
next->prev = prev;
free(pos);
}
#define _CRT_SECURE_NO_WARNINGS
#include"List.h"
//尾插、尾删测试
void test1()
{
ListNode* head = ListCreate();
ListPushBack(head, 1);
ListPrint(head);
ListPushBack(head, 2);
ListPrint(head);
ListPushBack(head, 3);
ListPrint(head);
ListPushBack(head, 4);
ListPrint(head);
ListPushBack(head, 5);
ListPrint(head);
printf("*************************************\n");
ListPopBack(head);
ListPrint(head);
ListPopBack(head);
ListPrint(head);
ListPopBack(head);
ListPrint(head);
ListPopBack(head);
ListPrint(head);
ListPopBack(head);
//ListPrint(head);
//ListPopBack(head);
//ListPrint(head);
}
//头插、头删测试
void test2()
{
ListNode* head = ListCreate();
ListPushFront(head, 1);
ListPrint(head);
ListPushFront(head, 2);
ListPrint(head);
ListPushFront(head, 3);
ListPrint(head);
ListPushFront(head, 4);
ListPrint(head);
ListPushFront(head, 5);
ListPrint(head);
printf("*************************************\n");
ListPopFront(head);
ListPrint(head);
ListPopFront(head);
ListPrint(head);
ListPopFront(head);
ListPrint(head);
ListPopFront(head);
ListPrint(head);
ListPopFront(head);
//ListPrint(head);
//ListPopFront(head);
//ListPrint(head);
}
void test3()
{
ListNode* head = ListCreate();
ListPushBack(head, 1);
ListPushBack(head, 2);
ListPushBack(head, 3);
ListPushBack(head, 4);
ListPushBack(head, 5);
ListPrint(head);
//查找测试
ListNode* ret = ListFind(head, 4);
printf("%d\n", ret->_data);
//插入测试
ListInsert(ret, 30);
ListPrint(head);
ListInsert(head, 50);
ListPrint(head);
ret = ListFind(head, 1);
ListInsert(ret, 10);
ListPrint(head);
printf("***************************\n");
//删除测试
ret = ListFind(head, 30);
ListErase(ret);
ListPrint(head);
ret = ListFind(head, 50);
ListErase(ret);
ListPrint(head);
ret = ListFind(head, 10);
ListErase(ret);
ListPrint(head);
//销毁测试
ListDestory(head);
//ListPrint(head);
ret = ListFind(head, 3);
printf("%d\n", ret->_data);
}
int main()
{
test3();
return 0;
}
如有错误或者不清楚的地方欢迎私信或者评论指出