一、介绍
1.各种链表的区分
- 单向链表:链式的存储结构在逻辑上是连续的每次通过一个指针来指向下一个节点将其链接起来
- 双向链表:包含两个指针,一个(prior)指向前一个节点,一个(next)指向后一个节点。
- 单向循环链表:与单向链表的区别就是,单向链表的最后一个节点指针是指向NULL的,单向循环链表最后一个节点的指针是指向头节点head的。
- 双向循环链表:最后一个节点的next指向head,而head的prior指向最后一个节点,构成一个环
2.双向循环链表
同时具备双向链表和循环链表的特性,非常灵活。搜索可以不从头指针开始,也可以反向搜索。
链表中每个节点由指针域和数据域两个部分组成。
该链表中每个节点有两个指针域,分别指向前一个节点和后一个节点。
同时,最后一个节点和第一个节点相链接,构成一个环。
3.数据元素的组织
typedef int data_t;
typedef struct node{
data_t data;
struct node *prior;
struct node *next;
}dlistnode;
二、相关函数
1.初始化操作
dlistnode* dlist_create(){
dlistnode *H,*r,*p;
int n;
if((H=(dlistnode *)malloc(sizeof(dlistnode)))==NULL)
{
puts("malloc failed");
return NULL;
}
H->prior = H;
H->next = H;
r = H;
while(1){
printf("please input(-1 exit):");
scanf("%d",&n);
if(n==-1)
break;
if((p=(dlistnode *)malloc(sizeof(dlistnode)))==NULL)
{
printf("malloc failed\n");
return NULL;
}
p->data=n;
p->prior=r;
p->next=r->next;
r->next=p;
H->prior=p;
r=p;
}
return H;
}
2.遍历输出
void dlist_show(dlistnode* H)
{
dlistnode *p;
p=H->next;
while(p!=H)
{
printf("%d ",p->data);
p=p->next;
}
putchar(10);
}
3.查找
按位置查找
dlistnode* dlist_get(dlistnode *H,int pos)
{
int i=-1;
dlistnode *p=H;
if(pos <0){
puts("pos < 0,invalid!");
return NULL;
}
while(i<pos){
p=p->next;
i++;
if(p==H){
puts("pos > length,invalid");
return NULL;
}
}
return p;
}
4.插入
int dlist_insert(dlistnode *H,data_t value,int pos)
{
dlistnode *p,*q;
p=dlist_get(H,pos);
if(p==NULL)
return -1;
if((q=(dlistnode *)malloc(sizeof(dlistnode)))==NULL)
{
printf("malloc failed\n");
return -1;
}
q->data = value;
q->prior=p->prior;
q->next=p;
p->prior->next=q;
p->prior = q;
return 0;
}
5.删除
int dlist_delete(dlistnode *H,int pos)
{
dlistnode *p;
p=dlist_get(H,pos);
if(p==NULL)
return -1;
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);
p=NULL;
return 0;
}
6.测试
#include "dlist.h"
int main(int argc, const char *argv[])
{
dlistnode *H;
int pos;
H=dlist_create();
dlist_show(H);
while(1)
{
printf("input pos(-1 exit):");
scanf("%d",&pos);
if(pos==-1)
break;
dlist_delete(H,pos);
}
dlist_show(H);
return 0;
}