双向循环链表和单链表一样,是由一个个的节点组成,只是前者拥有两个指针域,一个指向前一个节点的地址另一个指向后一个节点。
双向链表的储存结构
typedef int data_t;
typedef struct node{
data_t data;
struct node *prior,*next;
}dlinklist;
创建一个双向循环链表
首先需要创建一个头结点并初始化
dlinklist *CreateDlinklist(){
dlinklist * head = (dlinklist *)malloc(sizeof(dlinklist));
if(head == NULL)
return NULL;
head->data = -1;
head->prior = head->next = head;
return head;
}
计算双向循环链表的有效长度
有效长度是不包含头结点的,要实现这个我们就需要定义一个指针p来对链表进行遍历。
int GetLengthDlinklist(dlinklist *head){
if(head == NULL)
return -1;
dlinklist *p = head->next;
int len = 0;
while(p != head){
//p = p->next;
len++;
p = p->next;
}
return len;
}
判断是否为空
当头节点的直接前驱指向本身是就是为空的
int Dlinklist_is_empty(dlinklist *head){
if(head == NULL)
return -1;
return head->prior == head;
}
插入数据
按位置进行数据的插入,这里我们需要创建一个新的节点来存放需要插入的数据,在定义一个新的指针对链表进行遍历找出需要插入的位置,然后将数据插入指定的位置。如图:
实现代码:
int InsertDlinklist(dlinklist *head,int pos,data_t data){
if(head == NULL)
return -1;
if(pos < 0 || pos > GetLengthDlinklist(head))
return -1;
dlinklist *p = (dlinklist *)malloc(sizeof(dlinklist));
if(p == NULL)
return -1;
dlinklist *p = (dlinklist *)malloc(sizeof(dlinklist)); //创建一个节点来存需要插入的数据
p->data = data;
p->next = p->prior = NULL;
dlinklist *q = head; //定义一个节点指针来对链表进行遍历
while(pos--){
q = q->next;
}
p->next = q->next;
p->prior = q;
q->next->prior = p;
q->next = q;
return 0;
}
按位置删除数据
首先需要遍历找到需要删除的节点,所以就需要定义一个指针进行遍历,在此之前还需要对该位置进行判断是否符合要求。找到位置后将该节点删除,并释放节点。如图:
实现代码
int DeDlinklistBypos(dlinklist *head,int pos){
if(head == NULL)
return -1;
if(pos < 0 || pos > GetLengthDlinklist(head) || Dlinklist_is_empty(head))
return -1;
dlinklist *p = head;
while(pos--){
p = p->next;
}
p->next->prior = p->prior;
p->prior->next = p->next;
free(p);
p = NULL;
return 0;
}
按值进行数据的删除
遍历找到要删除的值,然后将值所在的节点删除并释放(操作和按位置删除类似)
int DeDlinklistBydata(dlinklist *head,data_t data){
if(head == NULL)
return -1;
dlinklist *p = head->next;
while(p != head){
if(p->data == data)
break;
else
p = p->next;
}
p->next->prior = p->prior;
p->prior->next = p->next;
free(p);
p = NULL;
return 0;
}
按位置进行数据修改
找到需要修改的位置节点直接进行数据修改
int ChangeDlinklistBypos(dlinklist *head,int pos,data_t data){
if(head == NULL)
return 0;
if(pos<0 || pos> Get_dlinklist_length(head) || Dlinklist_is_empty(head))
return -1;
dlinklist *p = head;
while(pos--){
p = p->next;
}
p->data = data;
return 0;
}
按值进行数据修改
遍历找到需要修改的值所在的节点,然后进行数据修改,将新的值赋给旧的值
int ChangeDlinklistBydata(dlinklist *head,data_t old,data_t new){
if(head == NULL)
return -1;
dlinklist *p = head->next;
while(p){
if(p->data == old)
break;
else
p = p->next;
}
p->data = new;
return 0;
按位置进行查找,返回值
找出位置节点,将其中的值返回
int SearchDlinklistBypos(dlinklist *head,int pos){
if(head == NULL)
return -1;
if(pos<0 || pos >Get_dlinklist_length(head) || Dlinklist_is_empty(head))
return -1;
dlinklist *p = head;
while(pos--){
p = p->next;
}
return p->data;
}
按值进行查找,返地址
找到值所在的节点,将节点的地址返回
dlinklist *SearchDlinklistBydata(dlinklist *head,data_t data){
if(head == NULL)
return NULL;
dlinklist *p = head->next;
while(p != head){
if(p->data == data)
break;
else
p = p->next;
}
return p;
}
遍历双循环链表
定义一个指针对链表进行遍历,并输出每个节点的值
void printfDlinklist(dlinklist *head){
if(head == NULL)
return ;
dlinklist *p = head->next;
while(p != head){
printf("%3d",p->data);
p = p->next;
}
printf("\n");
return ;
}