1. 带头+双向+循环链表的结构
结构:这种链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现;其次每个链表节点有前驱指针和后置指针 。
带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势
1.1链表的设计
注:
1.将int 重命名为为STLDataType 是为了修改储存类型时更为轻松,增加了壮硕性。
2.next为链表下一个节点的指针,方便寻找到下一个节点。
1.2 链表所需实现功能
// 带头+双向+循环链表增删查改实现 typedef int LTDataType; typedef struct ListNode { LTDataType _data; struct ListNode* _next; struct ListNode* _prev; }ListNode; // 创建返回链表的头结点. ListNode* ListCreate(); // 双向链表销毁 void ListDestory(ListNode* pHead); // 双向链表打印 void ListPrint(ListNode* pHead); // 双向链表尾插 void ListPushBack(ListNode* pHead, LTDataType x); // 双向链表尾删 void ListPopBack(ListNode* pHead); // 双向链表头插 void ListPushFront(ListNode* pHead, LTDataType x); // 双向链表头删 void ListPopFront(ListNode* pHead); // 双向链表查找 ListNode* ListFind(ListNode* pHead, LTDataType x); // 双向链表在pos的前面进行插入 void ListInsert(ListNode* pos, LTDataType x); // 双向链表删除pos位置的节点 void ListErase(ListNode* pos);
1.2 功能实现
// 创建返回链表的头结点.
ListNode* ListCreate()
{
ListNode* newnode = (ListNode*)malloc( sizeof(ListNode) );
newnode->_data = 0;
//注意创建的新节点前后指针指向自己
newnode->_next = newnode;
newnode->_prev = newnode;
return newnode;
}
// 双向链表销毁
void ListDestory(ListNode* pHead)
{
ListNode* phead = pHead;
ListNode* prev = pHead->_next;
ListNode* after = pHead->_next;
//after为空指针当作条件是为了释放最后一个节点回到哨兵位时
//能进到这个循环将哨兵位前后指针指向自己
while(after)
{
after = after->_next;
//释放完尾节点再次进到这个循环不释放头节点。
if(phead != prev)
free(prev);
prev = after;
//进到这个循环将哨兵位前后指针指向自己
if (phead == after)
{
prev->_next = pHead;
prev->_prev = pHead;
break;
}
}
}
// 双向链表打印
void ListPrint(ListNode* pHead)
{
ListNode* phead = pHead;
ListNode* cur = pHead->_next;
if (pHead == cur)
{
printf("哨兵位");
}
//cur指针从哨兵位后一个节点打印如果下一个不是头节点则打印“<=>”
//并前往下一个节点,如果cur到头节点则打印结束
while (phead != cur)
{
printf("%d",cur->_data);
if (cur->_next != phead)
printf("<=>");
cur = cur->_next;
}
}
// 双向链表尾插
void ListPushBack(ListNode*pHead)
{
//用哨兵位的前驱指针找到尾巴进行尾插
//即使只剩哨兵位也不需要担心像单链表那样单独考虑空链表的情况!!
//该结构带来的好处
ListNode* newnode = ListCreate();
ListNode* tail = pHead->_prev;
newnode->_prev = tail;
tail->_next = newnode;
pHead->_prev = newnode;
newnode->_next = pHead;
}
//尾删
void ListPopBack(ListNode* pHead)
{
ListNode* end = NULL;
end = pHead->_prev;
pHead->_prev = end->_prev;
end->_prev->_next = pHead;
//只需考虑只剩哨兵位的情况
if(pHead != end)
free(end);
}
//头插
void ListPushFront(ListNode* pHead , LTDataType x)
{
ListNode* frist = pHead->_next;
ListNode* newnode = ListCreate();
newnode->_data = x;
newnode->_next = frist;
frist->_prev = newnode;
pHead->_next = newnode;
newnode->_prev = pHead;
}
//头删
void ListPopFront(ListNode* pHead)
{
ListNode* frist = pHead->_next;
ListNode* after = frist->_next;
pHead->_next = after;
after->_prev = pHead;
if(pHead != frist)
free(frist);
}
//搜索节点
ListNode* ListFind(ListNode* pHead , LTDataType x)
{
ListNode* pFind = pHead->_next;
while (pFind != pHead)
{
if (pFind->_data == x)
{
return pFind;
}
pFind = pFind->_next;
}
return NULL;
}
//pos前插入节点
void Insert(ListNode* pos, LTDataType x)
{
ListNode* prev= pos->_prev;
ListNode* newnode = ListCreate();
newnode->_data = x;
newnode->_next = pos;
pos->_prev = newnode;
prev->_next = newnode;
newnode->_prev = prev;
}
//删除pos位置节点
void ListErase(ListNode* pos)
{
ListNode* cur = pos;
ListNode* prev = pos->_prev;
ListNode* after = pos->_next;
prev->_next = after;
after->_prev = prev;
if(cur != prev)
free(cur);
}