本文我们所要实现的是循环链表,即带头双向循环链表
带头双向循环链表与无头单向非循环链表不同的是,它结构复杂,一般用于单独存储数据,实际中使用的链表数据结构,均是带头双向循环链表。而无头单向非循环链表结构简单,一般不会用来单独存储数据,实际更多用于其他数据结构的子结构。
在实现循环链表增删查改之前,首先应该创建一个循环链表
typedef int CLTDataType;typedef struct CListNode
{struct CListNode* next;struct CListNode* prev;CLTDataType data;
}CLTNode;
其中prev是前一个结点地址,next是下一个结点。
代码如下(示例):
CLTNode* BuyListNode(CLTDataType x)
{CLTNode* newnode = (CLTNode*)malloc(sizeof(CLTNode));if (newnode == NULL){perror("malloc fail");exit(-1);}newnode->data = x;newnode->next = NULL;newnode->prev = NULL;return newnode;
}
1、初始化
代码如下(示例):
CLTNode* LTInit()
{CLTNode* phead = BuyListNode(-1);phead->next = phead;phead->prev = phead;return phead;
}
2、打印
void LTPrint(CLTNode* phead)
{assert(phead);CLTNode* cur = phead->next;while (cur != phead){printf("%d ", cur->data);cur = cur->next;}printf("\n");
}
void LTPushBack(CLTNode* phead, CLTDataType x)
{assert(phead);CLTNode* newnode = BuyListNode(x);CLTNode* tail = phead->prev;tail->next = newnode;newnode->prev = tail;newnode->next = phead;phead->prev = newnode;
}
头插一共两种写法
第一种:
先让新结点的next指向下一个结点,再让头结点的next指向新结点,有先后顺序。
代码如下:
void LTPushFront(CLTNode* phead, CLTDataType x)
{assert(phead);CLTNode* newnode = BuyListNode(x);newnode->next = phead->next;phead->next->prev = newnode;phead->next = newnode;newnode->prev = phead;
}
第二种:
创建一个新指针,无先后顺序
代码如下:
void LTPushFront(CLTNode* phead, CLTDataType x)
{assert(phead);CLTNode* newnode = BuyListNode(x);CLTNode* first = phead->next;phead->next = newnode;newnode->prev = phead;newnode->next = first;first->prev = newnode;
}
pos在head处时,进行尾插
pos在d1处时,进行头插
代码如下:
void LTInsert(CLTNode* pos, CLTDataType x)
{assert(pos);CLTNode* prev = pos->prev;CLTNode* newnode = BuyListNode(x);prev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}
在头删和尾删也可直接调用此函数
头删:LTInsert(phead, x)
尾删:LTInsert(phead->next, x)
void LTPopBack(CLTNode* phead)
{assert(phead);assert(phead->next != phead);CLTNode* tail = phead->prev;CLTNode* tailPrev = tail->prev;tailPrev->next = phead;phead->prev = tailPrev;free(tail);
}
代码如下:
void LTPopFront(CLTNode* phead)
{assert(phead);assert(phead->next != phead);CLTNode* first = phead->next;CLTNode* second = first->next;free(first);phead->next = second;second->prev = phead;}
代码如下:
void LTErase(CLTNode* pos)
{assert(pos);CLTNode* prev = pos->prev;CLTNode* next = pos->next;free(pos);prev->next = next;next->prev = prev;
}
在头删和尾删也可直接调用此函数
头删:LTErase(phead->next)
尾删:LTErase(phead->prev)
1、查找
代码如下:
CLTNode* LTFind(CLTNode* phead, CLTDataType x)
{assert(phead);CLTNode* cur = phead->next;while (cur != phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}
2、销毁
代码如下:
void LTDestroy(CLTNode* phead)
{assert(phead);CLTNode* cur = phead->next;while (cur != phead){CLTNode* next = cur->next;free(cur);cur = next;}free(phead);
}
下一篇:业务员如何找客户?