c语言下的双向循环链表

二.双向循环链表

1.概念

双向循环链表的节点包含一个数据域,两个指针域,一个指针域指向上一个节点,另一个指针域指向下一个节点

这样双向循环链表构成了两个相反方向遍历的圆环

双向循环链表与单链表相比,提高了访问的效率,也付出了多维护一个指针的代价

双向循环链表的插入和删除操作比单向链表复杂,查找和修改和单向链表的算法一样

#include <stdio.h>
#include <stdlib.h>
#include “dlist.h”

//创建空链表
dlist_t create_emptydlist()
{
//构造头节点
dlist_t head = (dlist_t)malloc(sizeof(dlist));
if(head){
head->data = -1;
//头节点的前置和后置都指向自己表示空链表
head->prev = head;
head->next = head;
}

return head;

}

//按值删除,返回删除元素个数
int delete_by_value(dlist_t head,T dt)
{
int i = 0;
dlist_t tmp = NULL;

while(tmp = search_by_value(head,dt)){
    //要删除节点的后一个节点的前置指针指向要删除节点的前一个节点
    tmp->next->prev = tmp->prev;
    //要删除节点的前一个节点的后置指针指向要删除节点的后一个节点
    tmp->prev->next = tmp->next;
    //释放要删除的节点
    free(tmp);
    tmp = NULL;
    i++;
}

return i;

}

//按值查找
dlist_t search_by_value(dlist_t head,T dt)
{
//略过无效头节点
dlist_t tmp = head->next;

while(tmp!=head){
    if(tmp->data==dt)
        return tmp;
    tmp = tmp->next;
}

return NULL;

}

//按位置删除
int delete_by_pos(dlist_t head,int pos)
{
//先查找链表,找到要删除的节点
dlist_t tmp = search_by_pos(head,pos);

//如果找到了就删掉,没找到就返回错误
if(tmp){
    //要删除节点的后一个节点的前置指针指向要删除节点的前一个节点
    tmp->next->prev = tmp->prev;
    //要删除节点的前一个节点的后置指针指向要删除节点的后一个节点
    tmp->prev->next = tmp->next;
    //释放要删除的节点
    free(tmp);
    tmp = NULL;

    return 0;
}

//没有找到节点,返回-1
return -1;

}

//按位置查找
dlist_t search_by_pos(dlist_t head,int pos)
{
int i = 1;
dlist_t tmp = head->next;

//遍历到头节点为止
while(tmp!=head){
    if(i==pos)
        return tmp;
    tmp = tmp->next;
    i++;
}

//回到头节点,谁没有符合编号的节点
return NULL;

}

//从指定位置之后插入节点
dlist_t insert(dlist_t p,T dt)
{
if(!p)
return NULL;

//构造新节点
dlist_t newnode = (dlist_t)malloc(sizeof(dlist));
if(newnode){
    newnode->data = dt;
    //将新节点的前置指向p,后置指向p的下一个节点
    newnode->prev = p;
    newnode->next = p->next;
    //将p的后置指向新节点,将P的下一个节点的前置指向新节点
    p->next->prev = newnode;
    p->next = newnode;
    
}

return newnode;

}

//排序
void sort(dlist_t head)
{
dlist_t tmp = head->next,p = NULL,q = NULL;

//将链表置空
head->next = head;
head->prev = head;

while(tmp!=head){
    //保存原链表中tmp的下一个节点
    q = tmp->next;
    
    //找到tmp插入的位置
    for(p=head->prev;p!=head&&p->data>tmp->data;p=p->prev);
    //将tmp插入到p之后
    tmp->prev = p;
    tmp->next = p->next;
    p->next->prev = tmp;
    p->next = tmp;

    //将tmp指向要插入的下一个节点
    tmp = q;
}

}

//销毁链表
void destory_dlist(dlist_t *phead)
{
dlist_t head = (*phead)->next,p = NULL;

while(head!=*phead){
    p = head;
    head = head->next;
    free(p);
}
free(head);

*phead = NULL;
p = NULL;   

}

//遍历
void travel(dlist_t head)
{
//略过无效头节点
dlist_t tmp = head->next;

while(tmp!=head){
    printf("%d ",tmp->data);
    tmp = tmp->next;
}
printf("\n");

}

双向循环链表(https://download.csdn.net/download/qq_41256954/11079083)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值