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)
上一篇: 算法导论-插入排序
下一篇: MongoDB聚合篇