赞
踩
目录
与单链表相比,带头双向循环链表主要有以下特点:
1.节点中新增一个节点,存储的是前一个结点的地址;
2.链表的头节点存储了尾节点的地址,尾结点存储了头节点的地址;
3.具有单链表所不具备的哨兵位,且哨兵位中不存储有效数据。
与无头单向非循环链表相比,带头双向循环链表的定义中多出了新的指针prev,这个指针用于存放前一个节点的地址。如下:
- typedef int DataType;
- typedef struct SlistNode
- {
- DataType data;
- struct SlistNode*next;
- struct SlistNode*prev;
- }SlistNode;
与单向链表不同的是,带头双向循环链表的初始化需要申请一个节点作为哨兵位节点。
- ListNode* ListCreate()
- {
- ListNode* phead = BuyNewNode(-1);
- // 这里的-1没有意义,只是为了创建哨兵位
-
- phead->_next = phead;
- phead->_prev = phead;
-
- return phead;
- }
在这里使用了函数BuyNewNode用于动态开辟节点。
- ListNode* BuyNewNode(LTDataType x)
- {
- ListNode* newnode = (ListNode*)malloc(sizeof(struct ListNode));
- if (newnode == NULL)
- {
- perror("malloc fail");
- return NULL;
- }
-
- newnode->_prev = NULL;
- newnode->_next = NULL;
- newnode->_data = x;
-
- return newnode;
- }
需要注意的是:哨兵位节点不存储有效数据;且由于链表循环,初始化时需要将哨兵位的prev和next均指向自身。
可图示如下:
即在链表的头部进行节点的插入。
由于这类链表在初始化时已经创建了哨兵位,即头插是插入在哨兵位的下一个节点的;且哨兵位不可为空,使用assert进行断言。
- void ListPushFront(ListNode* pHead, LTDataType x)
- {
- assert(pHead);
-
- // 开辟包含新增数据x的节点
- ListNode* newnode = BuyNewNode(x);
-
- // 链接newnode与pHead->_next
- newnode->_next = pHead->_next;
- pHead->_next->_prev = newnode;
-
- pHead->_next = newnode;
- newnode->_prev = pHead;
- }
可图示如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。