双向链表的实现
双向链表的定义
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
图形表示如下:(该图形我们会在下面的代码解析中会用到)
双向链表的建立
因为双向链表有两个指针变量,我们定义前面的指针变量为 prev ;后面的指针变量为 next
建立双向链表,代码表示如下
typedef int LTDataType;
typedef struct ListNode
{
struct ListNode* next; //后指针
struct ListNode* prev; //前指针
LTDataType data;
}LTNode;
双向链表的初始化
LTNode* BuyLTNode(LTDataType x) 函数是开辟空间函数,开辟一个名为node的链表元素的空间,将前后指针置空,将 x 赋值给date
代码实现如下:
LTNode* BuyLTNode(LTDataType x)
{
LTNode* node = (LTNode*)malloc(sizeof(LTNode));
if (node == NULL)
{
perror("malloc fail");
exit(-1);
}
node->data = x;
node->next = NULL;
node->prev = NULL;
return node;
}
到这里建立好的双向链表如下图所示:
代码实现如下:
LTNode* LTInit() 函数,初始化双向链表
LTNode* LTInit()
{
LTNode* phead = BuyLTNode(-1);
phead->next = phead;
phead->prev = phead;
return phead;
}
void LTPrint(LTNode* phead)函数,是一个简单的输出函数
就是遍历双向链表,创建cur 指针当cur == phaed 时循环结束
在遍历过程中以此对 data进行输出
代码实现如下:
void LTPrint(LTNode* phead)
{
assert(phead); //暴力检查phead是否为空
printf("phead<=>");
LTNode* cur = phead->next;
while (cur != phead) //遍历链表当cur == phead时循环结束
{
printf("%d<=>", cur->data);
cur = cur->next;
}
printf("\n");
}
双向链表的查找
代码实现如下:
LTNode* LTFind(LTNode* phead, LTDataType x)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
双向链表的尾插
图解如下:
就是说让
newhead 的头指针指向head
head 的尾指针指向 newnodenewnode 的尾指针指向 head
head 的头指针指向newnode
这样就实现了双向链表的尾插
代码实现如下:
void LTPushBack(LTNode* phead, LTDataType x)
{
assert(phead);
LTNode* tail = phead->prev;
LTNode* newnode = BuyLTNode(x);
newnode->prev = tail;
tail->next = newnode;
newnode->next = phead;
phead->prev = newnode;
}
双向链表的尾删
图解如下
将tail与Ptail和head之间的连接阻断
然后连接head与Ptail
代码实现如下:
void LTPopBack(LTNode* phead)
{
assert(phead);
assert(phead->next != phead);
LTNode* tail = phead->prev;
LTNode* Ptail = tail->prev;
free(tail);
Ptail->next = phead;
phead->prev = Ptail;
}
双向链表的头插
图解如下
void LTPushFront(LTNode* phead, LTDataType x)
{
assert(phead);
LTNode* newnode = BuyLTNode(x);
newnode->next = phead->next;
phead->next->prev = newnode;
phead->next = newnode;
newnode->prev = phead;
}
双向链表的头删
图解如下:
void LTPopFront(LTNode* phead)
{
assert(phead);
assert(phead->next != phead);
LTNode* first = phead->next;
LTNode* second = first->next;
free(first);
phead->next = second;
second->prev = phead;
}
统计双向链表中元素个数
int LTSize(LTNode* phead)
{
assert(phead);
int size = 0;
LTNode* cur = phead->next;
while (cur != phead)
{
++size;
cur = cur->next;
}
return size;
}
在pos之前位置插入 x
图解如下:
//pos 之前插入 x
void LTInsert(LTNode* pos, LTDataType x)
{
LTNode* newnode = BuyLTNode(x);
LTNode* Ppos = pos->prev;
Ppos->next = newnode;
newnode->prev = Ppos;
newnode->next = pos;
pos->prev = newnode;
}
删除pos位置
图解如下:
//删除pos位置
void LTErase(LTNode* pos)
{
assert(pos);
LTNode* front = pos->prev;
LTNode* behind = pos->next;
free(pos);
front->next = behind;
behind->prev = front;
}
双向链表的释放
代码实现如下
void LTDestroy(LTNode* phead)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
LTNode* next = cur->next;
free(cur);
cur = next;
}
return NULL;
}
以上就是对双向链表的实现