🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。
🐌 个人主页:蜗牛牛啊
🔥 系列专栏:🛹初出茅庐C语言、🛴数据结构
📕 学习格言:博观而约取,厚积而薄发
🌹 欢迎进来的小伙伴,如果小伙伴们在学习的过程中,发现有需要纠正的地方,烦请指正,希望能够与诸君一同成长! 🌹
无头单向非循环链表结构简单,一般不会单独用来存数据。实际中更多的是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。而带头双向循环链表的结构较为复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表,虽然它的结构复杂但是因为结构优势用代码实现起来会变得简单。
LTNode* BuyListNode(ListDataType x)
{LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));if (newnode == NULL){perror("malloc");exit(-1);}newnode->val = x;newnode->prev = NULL;newnode->next = NULL;return newnode;
}
void ListInit(LTNode** pphead)//初始化
{*pphead = (LTNode*)malloc(sizeof(LTNode));*pphead = BuyListNode(-1);(*pphead)->next = *pphead;(*pphead)->prev = *pphead;
}
//LTNode* ListInit()//初始化
//{
// LTNode* phead = BuyListNode(-1);//初始化时将头结点置为-1;
// phead->next = phead;
// phead->prev = phead;
// return phead;
//}
初始化链表有两种方式,一种是有返回类型(注释部分),另一种是在初始化函数中给结构体开辟空间(不过注意参数要为二级指针)。因为是带头结点的循环链表,所以
prev和next指针都指向自己。
void ListPrint(LTNode* phead)//打印
{assert(phead);LTNode* cur = phead->next;while (cur != phead){printf("%d ", cur->val);cur = cur->next;}printf("\n");
}
注意
while循环的结束条件,保证能够打印链表中的所有有效值。要对头结点进行assert判断,不能为空。
void ListPushBack(LTNode* phead, ListDataType x)//尾插
{assert(phead);LTNode* newnode = BuyListNode(x);LTNode* tail = phead->prev;newnode->next = tail->next;phead->prev = newnode;newnode->prev = tail;tail->next = newnode;//ListInsert(phead, x);}
void ListPopBack(LTNode* phead)//尾删
{assert(phead);assert(phead->next != phead);LTNode* prevnode = phead->prev;prevnode->prev->next = phead;phead->prev = prevnode->prev;free(prevnode);//ListErase(phead->prev);
}
尾删时要注意判断
phead->next != phead,不能删除头结点,同时记得要free(prevnode)释放删除后的空间。
void ListPushFront(LTNode* phead, ListDataType x)//头插
{assert(phead);LTNode* tail = phead->next;LTNode* newnode = BuyListNode(x);tail->prev = newnode;newnode->next = tail;newnode->prev = phead;phead->next = newnode;//ListInsert(phead->next,x);
}
void ListPopFront(LTNode* phead)//头删
{assert(phead);assert(phead->next != phead);LTNode* tail = phead->next;phead->next = tail->next;tail->next->prev = phead;//ListErase(phead->next);
}
LTNode* ListFind(LTNode* phead, ListDataType x)//找某个数返回其指针
{assert(phead);LTNode* cur = phead->next;while (cur != phead){if (cur->val == x){return cur;}cur = cur->next;}return NULL;
}
void ListInsert(LTNode* pos, ListDataType x)//在pos之前插入
{assert(pos);LTNode* newnode = BuyListNode(x);LTNode* tail = pos->prev;tail->next = newnode;newnode->prev = tail;newnode->next = pos;pos->prev = newnode;
}
void ListErase(LTNode* pos)//删除pos位置
{assert(pos);LTNode* prevnode = pos->prev;LTNode* nextnode = pos->next;free(pos);prevnode->next = nextnode;nextnode->prev = prevnode;/*pos->next->prev = pos->prev;pos->prev->next = pos->next;free(pos);*/
}
bool ListEmpty(LTNode* phead)//判断是否为空,如果是空,返回true
{assert(phead);return phead->next == phead;
}
size_t ListSize(LTNode* phead)//计算链表中有效值的个数
{assert(phead);size_t size = 0;LTNode* tail = phead->next;while (tail != phead){size++;tail = tail->next;}return size;
}
void ListDestroy(LTNode* phead)//销毁链表
{assert(phead);LTNode* tail = phead->next;while (tail != phead){LTNode* nextnode = tail->next;free(tail);tail = nextnode;}free(phead);
}
销毁链表时要注意要保证每个结点都释放,同时最后也要将头结点释放
free(phead)。
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#include
typedef int ListDataType;
typedef struct ListNode {ListDataType val;struct ListNode* prev;struct ListNode* next;
}LTNode;
LTNode* BuyListNode(ListDataType x)
{LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));if (newnode == NULL){perror("malloc");exit(-1);}newnode->val = x;newnode->prev = NULL;newnode->next = NULL;return newnode;
}
void ListInit(LTNode** pphead)//初始化
{*pphead = (LTNode*)malloc(sizeof(LTNode));*pphead = BuyListNode(-1);(*pphead)->next = *pphead;(*pphead)->prev = *pphead;
}
//LTNode* ListInit()//初始化
//{
// LTNode* phead = BuyListNode(-1);//初始化时将头结点置为-1;
// phead->next = phead;
// phead->prev = phead;
// return phead;
//}void ListPrint(LTNode* phead)//打印
{assert(phead);LTNode* cur = phead->next;while (cur != phead){printf("%d ", cur->val);cur = cur->next;}printf("\n");
}
void ListPushBack(LTNode* phead, ListDataType x)//尾插
{assert(phead);LTNode* newnode = BuyListNode(x);LTNode* tail = phead->prev;newnode->next = tail->next;phead->prev = newnode;newnode->prev = tail;tail->next = newnode;//ListInsert(phead, x);
}
void ListPopBack(LTNode* phead)//尾删
{assert(phead);assert(phead->next != phead);LTNode* prevnode = phead->prev;prevnode->prev->next = phead;phead->prev = prevnode->prev;free(prevnode);//ListErase(phead->prev);
}
void ListPushFront(LTNode* phead, ListDataType x)//头插
{assert(phead);LTNode* tail = phead->next;LTNode* newnode = BuyListNode(x);tail->prev = newnode;newnode->next = tail;newnode->prev = phead;phead->next = newnode;//ListInsert(phead->next,x);
}
void ListPopFront(LTNode* phead)//头删
{assert(phead);assert(phead->next != phead);LTNode* tail = phead->next;phead->next = tail->next;tail->next->prev = phead;//ListErase(phead->next);
}
LTNode* ListFind(LTNode* phead, ListDataType x)//找某个数返回其指针
{assert(phead);LTNode* cur = phead->next;while (cur != phead){if (cur->val == x){return cur;}cur = cur->next;}return NULL;
}
void ListInsert(LTNode* pos, ListDataType x)//在pos之前插入
{assert(pos);LTNode* newnode = BuyListNode(x);LTNode* tail = pos->prev;tail->next = newnode;newnode->prev = tail;newnode->next = pos;pos->prev = newnode;
}
void ListErase(LTNode* pos)//删除pos位置
{assert(pos);LTNode* prevnode = pos->prev;LTNode* nextnode = pos->next;free(pos);prevnode->next = nextnode;nextnode->prev = prevnode;/*pos->next->prev = pos->prev;pos->prev->next = pos->next;free(pos);*/
}
bool ListEmpty(LTNode* phead)//判断是否为空,如果是空,返回true
{assert(phead);return phead->next == phead;
}
size_t ListSize(LTNode* phead)//计算链表中有效值的个数
{assert(phead);size_t size = 0;LTNode* tail = phead->next;while (tail != phead){size++;tail = tail->next;}return size;
}
void ListDestroy(LTNode* phead)//销毁链表
{assert(phead);LTNode* tail = phead->next;while (tail != phead){LTNode* nextnode = tail->next;free(tail);tail = nextnode;}free(phead);
}
void TestList()
{//LTNode* plist = ListInit(&plist);LTNode* plist = NULL;ListInit(&plist);ListPushBack(plist, 100);ListPushBack(plist, 200);ListPushBack(plist, 300);ListPushBack(plist, 400);ListPushBack(plist, 500);ListPopBack(plist);ListPopBack(plist);ListPopBack(plist);ListPrint(plist);ListPushFront(plist, 1000);ListPushFront(plist, 2000);ListPushFront(plist, 3000);ListPopFront(plist);ListPopFront(plist);ListPrint(plist);LTNode* pos = ListFind(plist, 1000);if (pos != NULL){ListInsert(pos, 500);ListErase(pos);}ListPrint(plist);if (!ListEmpty(plist))printf("%d\n", ListSize(plist));
}
int main()
{TestList();return 0;
}