双向循环链表和双向链表的区别:
1)双向循环链表的尾节点的next域不是指向null;指向头节点
2)头节点的prior域不是指向null;而是指向尾节点
plist->next=plist;
plist->prior=plist;
- 增
双向循环链表的添加节点:受影响的四条线
1.插入节点自身的前驱
2.插入结点自身的后继
3.插入结点后继的前驱
4.插入结点前驱的后继
- 插入操作
头插和尾插与双向链表的头插和尾插区别: 头插的头结点的前驱在链表为空时要进行改变,链表不为空时则不变;
每次尾插都需要修改头结点的前驱指针指向最后一个节点
- 头插
//头插
bool Insert_head(PDCNode plist, ELEMTYPE val)
{
assert(plist != nullptr);
if (plist == nullptr)
{
return false;
}
//创建新节点
DCNode* pnewnode = (DCNode*)malloc(sizeof(DCNode) * 1);
assert(pnewnode != nullptr);
pnewnode->data = val;
assert(pnewnode != nullptr);
//找到插入位置
//插入 自身的两条线
pnewnode->next = plist->next; //1
pnewnode->prior = plist; //2
//不为空链表 下一个节点的前驱
if (plist->next != plist)
{
plist->next->prior = pnewnode; //3
}
//头节点的后继节点指向新节点
plist->next = pnewnode; //4
if (plist->prior == plist) //和双向链表不同之处
{ //是空指针则修改头结点的前驱指针 5
plist->prior = pnewnode; //保证plist->prior永远指向最后一个节点(1.如果本身就有有效节点则这个指针不需要修改 2、如果是空指针则需要修改
}
return true;
}
- 尾插
//尾插
bool Insert_tail(PDCNode plist, ELEMTYPE val)
{
assert(plist != nullptr);
if (plist == nullptr)
{
return false;
}
//创建新节点
DCNode* pnewnode = (DCNode*)malloc(sizeof(DCNode) * 1);
assert(pnewnode != nullptr);
pnewnode->data = val;
//找到插入位置 最后一个节点
DCNode* p = plist;
for (p; p->next != plist; p = p->next); //p指向最后一个节点???
//插入 自身两条线
pnewnode->prior = p;
pnewnode->next = plist; //pnewnode->next=p->next;
//最后一个节点的后继指向新
p->next = pnewnode;
//最后一个节点后继的前驱指向新 plist->prior重新指向最后一个节点(新节点)
p->next->prior = pnewnode; // plist->prior = pnewnode;
return true;
}
- 按位置插入
//按位置插入
bool Insert_pos(PDCNode plist, ELEMTYPE pos, ELEMTYPE val)
{
assert(plist != nullptr);
//判断pos的合法性
if (pos < 0 || pos > Get_length(plist))
{
return false;
}
//创建新节点
DCNode* pnewnode = (DCNode*)malloc(sizeof(DCNode));
assert(pnewnode != nullptr);
pnewnode->data = val;
//找到插入位置
DCNode* p = plist;
for (int i = 0; i < pos; i++)
{
p = p->next;
}
//插入 改变四条线
pnewnode->next = p->next; // 1
pnewnode->prior = p; // 2
if (p->next != plist)
{
p->next->prior = pnewnode; // 3
}
else
{ //如果为空 (类似于尾插)则将plist->prior的前驱指向新节点
plist->prior = pnewnode; //5
}
p->next = pnewnode; // 4
return true;
}
- 删除操作
- 头删
//头删
bool Del_head(PDCNode plist)
{
//判断是不是空链表
assert(plist != nullptr && plist->next != plist);
if (plist == nullptr || plist->next == plist)
{
return false;
}
DCNode* p = plist->next; //删除节点
if (p->next == plist)
{ //p是唯一的节点
plist->next = plist->prior = plist;
free(p);
p = nullptr;
}
else
{ //删除的节点不是仅存的节点
plist->next = p->next;
p->next->prior = plist;
free(p);
p = NULL;
}
return true;
}
- 尾删
//尾删
bool Del_tail(PDCNode plist)
{
assert(plist != nullptr);
// 2
DCNode* p = plist;
for (p; p->next != plist; p = p->next);//指向最后一个节点
//3 删除
if (plist->next = p) //p->prior==plist
{ //仅存节点
plist->next = plist;
plist->prior = plist;
}
else
{
p->prior->next = plist; //删除节点的上一个节点的next域指向头结点
p->next->prior = p->prior;//头结点的prior指向删除节点的前驱
}
free(p);
p = NULL;
return true;
}
- 按位置删除
//按位置删除
bool Del_pos(PDCNode plist, ELEMTYPE pos)
{
assert(plist != nullptr && pos >= 0 && pos < Get_length(plist));
//判断位置的合法性
if (pos < 0 || pos >= Get_length(plist))
{
return false;
}
if (pos == 0)
{
return Del_head(plist);
}
if (pos == Get_length(plist) - 1)
{
return Del_tail(plist);
}
//找到删除节点
//DCNode* p = plist;
//for (int i = 0; i <= pos; i++) //双向 可以直接指向前驱 直接找到删除节点
//{ //直接指向删除节点
// p = p->next;
//}
删除 释放空间
//if (p->next != nullptr)
//{
// p->next->prior = p->prior;
//}
//p->prior->next = p->next;
//free(p);
//p = nullptr;
DCNode* p = plist;
for (int i = 0; i < pos; i++)
{ //找到删除的节点的上一个节点
p = p->next;
}
DCNode* q = p->next;
p->next = q->next;
q->next->prior = p;
free(q);
q = nullptr;
return true;
}
- 按值删除
//按值删除
bool Del_val(PDCNode plist, ELEMTYPE val)
{
assert(plist != nullptr);
DCNode* p = Search(plist, val);
if (p == nullptr)
{
return false;
}
//任何情况
p->next->prior = p->prior;
p->prior->next = p->next;
free(p);
p = NULL;
return true;
}
- 查找操作
- 查找前驱
//查找值为val节点的前驱
PDCNode Get_prior(PDCNode plist, ELEMTYPE val)
{
assert(plist != nullptr);
DCNode* p = Search(plist, val);
if (p == nullptr)
{
return NULL;
}
return p->prior;
}
- 查找后继
// 查找值为val节点的后继
PDCNode Get_next(PDCNode plist, ELEMTYPE val)
{
assert(plist != nullptr);
DCNode* p = Search(plist, val);
if (p == nullptr)
{
return NULL;
}
return p->next;
}
- 销毁链表
//销毁 第一种方法 一直头删 只删除数据节点
void Destroy(PDCNode plist)
{
assert(plist != nullptr);
while (plist->next != plist)
{
DCNode* p = plist->next;
plist->next=p->next;
free(p);
p = NULL;
}
}
//销毁 第二种方法 两个指针
void Destroy2(PDCNode plist)
{
assert(plist != nullptr);
DCNode* p = plist->next;
DCNode* q;
while(p != plist)
{
q = p->next;
free(p);
p = q;
}
plist->next = plist;
}
//判空
bool Isempty(PDCNode plist)
{
return plist->next == plist;
}
//输出函数
void Show(PDCNode plist)
{
for (DCNode* p = plist->next; p != plist; p = p->next)
{
printf("%d ", p->data);
}
printf("\n");
}
//清空函数
void Clear(PDCNode plist)
{
Destroy(plist);
}
//返回链表长度
int Get_length(PDCNode plist)
{
int count = 0;
for (DCNode* p = plist->next; p != plist; p = p->next)
{
count++;
}
return count;
}