双向循环链表的时间复杂度除了查找,都为O(1)。
首先创建出结构体
typedef struct ListNode {
struct ListNode *next;
struct ListNode *prev;
LTDataType data;
} ListNode;
LTDataType其实是int类型的别名,方便后期代码维护
typedef int LTDataType;
双向链表的内容:
1:初始化
2:销毁链表
3:头插
4:尾插
5:头删
6:尾删
7:查找
首先要写一个创建新节点的函数,将第一个节点设置为头节点
ListNode *CreNode(LTDataType x) {
ListNode *newnode = (ListNode *)malloc(sizeof(ListNode));
newnode->data = x;
newnode->next = NULL;
newnode->prev = NULL;
return newnode;
}
然后将节点的prev和next指向自己,形成循环,循环链表相比于单向链表的好处在于可以更加容易找到尾节点,增删改的时间复杂度小于单项链表。
ListNode* ListInit()
{
ListNode* phead = BuyListNode(0);
phead->next = phead;
phead->prev = phead;
return phead;
}
这里也可以使用void ListInit(ListNode** phead)二级指针来进行初始化
void ListPushFront(ListNode* phead, LTDataType x)
{
assert(phead);
ListNode* newnode = BuyListNode(x);
newnode->next = phead->next;
phead->next->prev = newnode;
phead->next = newnode;
newnode->prev = phead;
}
void ListPopFront(ListNode* phead)
{
assert(phead->next != phead);
ListNode* first = phead->next;
ListNode* second = first->next;
phead->next = second;
second->prev = phead;
free(first);
first = NULL;
}
void ListPopBack(ListNode* phead)
{
assert(phead->next != phead);
ListNode* tail = phead->prev;
ListNode* prev = tail->prev;
prev->next = phead;
phead->prev = prev;
free(tail);
tail = NULL;
}
void ListPushBack(ListNode* phead, LTDataType x)
{
assert(phead);
ListNode* tail = phead->prev;
ListNode* newnode = BuyListNode(x);
tail->next = newnode;
newnode->prev = tail;
newnode->next = phead;
phead->prev = newnode;
}
#include
#include
#include
//定义数据类型
typedef int LTDataType;
//创建链表结构体
typedef struct ListNode {
struct ListNode *next;
struct ListNode *prev;
LTDataType data;
} ListNode;
//创建新节点
ListNode *CreNode(LTDataType x) {
ListNode *newnode = (ListNode *)malloc(sizeof(ListNode));
newnode->data = x;
newnode->next = NULL;
newnode->prev = NULL;
return newnode;
}
ListNode *ListInit() {
//初始化节点,全指向自己
ListNode *phead = CreNode(0);
phead->next = phead;
phead->prev = phead;
return phead;
}
//头插
void ListPushFront(ListNode *phead, LTDataType x) {
assert(phead);
ListNode *newnode = CreNode(x);
newnode->next = phead->next;
phead->next->prev = newnode;
phead->next = newnode;
newnode->prev = phead;
}
//尾插
void ListPushBack(ListNode *phead, LTDataType x) {
//创建新节点
ListNode *newnode = CreNode(x);
ListNode *cur = phead->prev;
cur->next = newnode;
newnode->prev = cur;
phead->prev = newnode;
newnode->next = phead;
}
//打印
void print(ListNode *phead) {
ListNode *cur = phead->next;
while (cur != phead) {
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}
//头删
void ListPopFront(ListNode *phead) {
assert(phead->next != phead);
ListNode *first = phead->next;
ListNode *second = first->next;
phead->next = second;
second->prev = phead;
free(first);
first = NULL;
}
//尾删
void ListPopBack(ListNode *phead) {
ListNode *cur = phead->prev;
ListNode *last = cur->prev;
last->next = phead;
phead->prev = last;
free(cur);
cur = NULL;
}
ListNode *ListFind(ListNode *phead, LTDataType x) {
ListNode *cur = phead->next;
while (cur != phead) {
if (cur->data == x) {
return cur;
}
cur = cur->next;
}
return NULL;
}
// pos位置之前插入x
void ListInsert(ListNode *pos, LTDataType x) {
ListNode *cur = pos->prev;
ListNode *newnode = CreNode(x);
cur->next = newnode;
newnode->prev = cur;
newnode->next = pos;
pos->prev = newnode;
}
//删除pos位置的值
void ListErase(ListNode *pos) {
ListNode *prev = pos->prev;
ListNode *next = pos->next;
prev->next = next;
next->prev = prev;
free(pos);
pos = NULL;
}
//计算链表长度
void ListSize(ListNode *phead) {
ListNode *tail = phead->next;
int cnt = 0;
while (tail != phead) {
cnt++;
tail = tail->next;
}
printf("链表的长度为:%d", cnt);
}
int main(void) {
ListNode *phead = ListInit(); //初始化,创建链表头节点
ListPushFront(phead, 1);
ListPushFront(phead, 2);
ListPushFront(phead, 3);
print(phead);
ListPushBack(phead, 4);
ListPushBack(phead, 5);
ListPushBack(phead, 6);
print(phead);
ListPopFront(phead);
print(phead);
ListPopBack(phead);
print(phead);
ListNode *pos = ListFind(phead, 5);
ListInsert(pos, 30);
print(phead);
ListErase(pos);
print(phead);
ListSize(phead);
return 0;
}