双向链表的介绍
双向链表是一种链表,它的每个节点都有两个链接,一个指向前一个节点,另一个指向下一个节点。相比于单向链表,双向链表在插入和删除操作时更加灵活,因为它们可以从两个方向进行操作。但是,双向链表的实现比单向链表更复杂,因为需要额外的指针来维护前一个和下一个节点的链接。
尾插
在链表的尾部插入新的结点,要插入新的结点,首先得定义一个新的结点,接这找到链表尾部结点,最后通过改变指针指向进行插入。
先定义一个新的结点(newnode),令他的next指向NULL;
找链表的尾部结点,定义一个移动结点tail,通过next指针进行移动,不难看出tail的next指向NULL就是链表的尾部结点
要将新结点链接到双向链表上,只需要:
将最后一个链表的结点的next指针指向newnode上,
将newnode的prev指针指向双向链表的最后一个指针上。
这样尾插就完成了,下面是代码
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{
//定义新结点
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
if (newnode) {
newnode->_data = x;
newnode->_next = NULL;
}
//找到最后一个结点
ListNode* tail = pHead;
while (tail->_next != NULL)
{
tail = tail->_next;
}
//改变指针指向
tail->_next = newnode;
newnode->_prev=tail;
}
尾删
很简单,尾删就是删除最后一个节点将最后一个结点的位置置空:
首先应找到,最后一个结点
接着,最后一个结点的prev指向最后一个结点的前一个结点,
将前一个结点的next指向NULL((将最后一个结点的位置置空)
// 双向链表尾删
void ListPopBack(ListNode* pHead)
{
//找到最后一个结点
ListNode* tail = pHead;
while (tail->_next!=NULL)
{
tail = tail->_next;
}
tail->_prev ->_next = NULL;
}
头插
头插是在头结点的后边直接插入所以还是定一个新节点(newnode),通过改变头节点的指向,和头节点下一个结点的指向以及new结点的指向来完成头插。
第一步先将newnode连接到链表上
newnode->prev=pHead;
newnode->next=pHead->next;
因为头结点的下一个结点要通过pHead的next指针来访问,所以先不要改pHead的next的指向,否则就访问不到pHead的下一个结点了;
要先将头结点的下一个结点的前驱结点指向newnode(pHead->next->prev=newnode)
接着改pHead->next指针指向newnode(pHead->next=Newnode)
这样头插就完成了
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{
ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
if (newnode)
{
newnode->_data = x;
newnode->_next = pHead->_next;
newnode->_prev = pHead;
pHead->_next->_prev=newnode;
pHead->_next = newnode;
}
}
头删
头删就是删除头节点的下一个结点,还是同样的原因,因为要通过next指针找下一个结点,所以应该先改蓝色的指针,(pHead->next->next->prev=pHead)
接着pHead->next=pHead->next->next;
// 双向链表头删
void ListPopFront(ListNode* pHead)
{
pHead->_next->_next->_prev = pHead;
pHead->_next = pHead->_next->_next;
}
实现:
void test3()
{
ListNode* Dhead = ListCreate();
ListPushBack(Dhead, 1);
ListPushBack(Dhead, 2);
ListPushBack(Dhead, 3);
ListPushBack(Dhead, 4);
printf("1到4尾插:");
ListPrint(Dhead);
printf("\n");
printf("尾删一次:");
ListPopBack(Dhead);
ListPrint(Dhead);
printf("\n");
printf("尾删两次:");
ListPopBack(Dhead);
ListPrint(Dhead);
printf("\n");
printf("\n");
ListPushFront(Dhead, 7);
ListPushFront(Dhead, 8);
ListPushFront(Dhead, 9);
printf("7到9头插:");
ListPrint(Dhead);
printf("\n");
printf("头删一次:");
ListPopFront(Dhead);
ListPrint(Dhead);
printf("\n");
printf("头删两次:");
ListPopFront(Dhead);
ListPrint(Dhead);
printf("\n");
}
int main()
{
test3();
return 0;
}
运行结果: