双向循环链表
1.线性表的双向链表存储结构
双向链表的结点含有两个指针域,其一指向直接后继,另一指向直接前驱,可描述为:
typedef struct DuLNode{
DuElemType data;
struct DuLNode *prior;
struct DuLNode *next;
}DuLNode,*DuLinkList;
2.双向循环链表基本操作
//1.双链表初始化(带头结点)
DuLNode *D_creatslink(int i);
//2.求链长(带头结点)
DuElemType D_ListLengths(DuLNode*head);
//3.取链表内元素
int D_GetElems(DuLNode*L,int i,DuElemType*t);
//4.插入操作
int D_InsertLists(DuLNode*L,int i,DuElemType e);
//5.删除操作
int D_DeleteLists(DuLNode*L,int i);
//6.定位操作
int D_LocateLists(DuLNode*L,DuElemType e);
//7.输出链表
void D_Lists(DuLNode*L);
//8.利用头结点反向输出输出链表
void BD_Lists(DuLNode*L);
3.完整程序
完整程序包括三个文件:
D_main.c(主程序)
–用于测试双向循环链表基本操作
D_linklist.h
标准库导入,存放类型定义,符号定义等预定义内容及函数声明。
D_linklist.c
存放双向循环链表基本操作函数主体内容。
①D_main.c
/*D_main.c*/
#include"D_linklist.h"
void main()
{
DuLinkList L;//创建一个结点指针
int j;
L=D_creatslink(5);
printf("表长为:%d\n",D_ListLengths(L));
D_Lists(L);
D_GetElems(L,5,&j);
printf("表内第5号元素为:%d\n",j);
D_InsertLists(L,5,666);
D_Lists(L);
printf("'99'为第%d号元素.\n",D_LocateLists(L,99));
D_DeleteLists(L,5);
D_Lists(L);
BD_Lists(L);
}
②D_linklist.h
/*D_linklist.h*/
#ifndef _D_LINKLIST_H
#define _D_LINKLIST_H
typedef int DuElemType;
#include<stdio.h>
#include<stdlib.h>
typedef struct DuLNode{
DuElemType data;
struct DuLNode *prior;
struct DuLNode *next;
}DuLNode,*DuLinkList;
/*基本操作声明*/
//1.双链表初始化(带头结点)
DuLNode *D_creatslink(int i);
//2.求链长(带头结点)
DuElemType D_ListLengths(DuLNode*head);
//3.取链表内元素
int D_GetElems(DuLNode*L,int i,DuElemType*t);
//4.插入操作
int D_InsertLists(DuLNode*L,int i,DuElemType e);
//5.删除操作
int D_DeleteLists(DuLNode*L,int i);
//6.定位操作
int D_LocateLists(DuLNode*L,DuElemType e);
//7.输出链表
void D_Lists(DuLNode*L);
//8.利用头结点反向输出输出链表
void BD_Lists(DuLNode*L);
#endif
③D_linklist.c
/*D_linklist.c*/
#include"D_linklist.h"
//1.双链表初始化(带头结点)
DuLNode *D_creatslink(int i)
{
DuLNode*prior,*next,*head,*s,*p;
int n; //循环控制变量
head=p=s=(DuLNode*)malloc(sizeof(DuLNode)); //创建一个结点作为头结点,并使头指针指向它
for(n=0;n<i;n++) //循环i次,创建i个结点
{
s=(DuLNode*)malloc(sizeof(DuLNode)); //创建一个结点
printf("请输入第%d个元素:",n+1);
scanf("%d",&s->data); //数据域赋值
p->next=s; //使上一个结点的next指针指向刚创建的结点
s->prior=p; //将创建的结点的头指针指向上一个结点
p=s; //移动P指针,使其指向当前结点
}
p->next=head; //尾结点的尾指向头指针
head->prior=p; //头结点的头结点指向尾结点
printf("双向循环列表建立成功!head:%d \n",head);
return head;
}
//2.求链长(带头结点)
DuElemType D_ListLengths(DuLNode*head)
{
DuLNode *p,*t;
int n; //链表记录变量
p=head->next; //跳过头结点
for(n=1;p!=head;n++) //循环历遍记录长度
p=p->next;
if(p==head)return n;
else return 0;
}
//3.取链表内元素
int D_GetElems(DuLNode*L,int i,DuElemType*t)
{
int n;
DuLNode*p=L;
if(i<1 || i>D_ListLengths(L))return 0; //参数i不合理,取元素失败返回0
for(n=0;n<i;n++) //循环历遍结点个数
p=p->next;
*t=p->data; //其值通过指针t返回
return 1;
}
//4.插入操作
int D_InsertLists(DuLNode*L,int i,DuElemType e)
{
DuLNode*p=L,*t,*f;
int n;
if(i<1 || i>D_ListLengths(L))return 0;
else{
for(n=0;n<i-1;n++) //循环历遍,直到i-1个位置
p=p->next;
f=p; //f指针存储第i-1个元素所在结点的地址
t=p->next; //t指针存储第i+1个元素所在结点的地址
p->next=(DuLNode*)malloc(sizeof(DuLNode)); //创建一个新结点,并将第i-1个元素所在结点的next指针指向新结点
p=p->next; //移动p,使其指向新结点
p->data=e; //给新结点数据域赋值
p->prior=f; //新结点的prior指针指向第i-1个元素所在结点
p->next=t; //新结点的next指针指向第i+1个元素所在结点
t->prior=p; //第i+1个元素所在结点的prior指针指向新结点
return 1;
}
}
//5.删除操作
int D_DeleteLists(DuLNode*L,int i)
{
DuLNode*p=L,*t,*s;
int n;
if(i<1 || i>D_ListLengths(L))return 0;
else{
for(n=0;n<i-1;n++)
p=p->next;
t=p->next; //t为待删除结点地址
p->next=t->next;//p为待删除结点上一个结点
s=t->next; //s为待删除结点下一个结点
s->prior=p; //含第i+1个元素的结点prior指针指向含第i-1个元素的结点
free(t); //释放含第i个元素的结点空间
return 1;
}
}
//6.定位操作
int D_LocateLists(DuLNode*L,DuElemType e)
{
DuLNode*p=L->next;
int n;
for(n=1;p->data!=e && p!=L;n++) //通过循环历遍寻找值e
p=p->next;
if(p->data == e) //找到,返回位序
return n;
else //没找到,返回0
return 0;
}
//7.输出链表
void D_Lists(DuLNode*L)
{
DuLNode*p=NULL;
p=L->next; //将P指向头结点
printf("链表内元素为:\n");
while(p!=L && p->data)
{
printf("-%d",p->data);
p=p->next;
}
printf("\n");
}
//8.利用头结点反向输出输出链表
void BD_Lists(DuLNode*L)
{
DuLNode*p=NULL;
p=L->prior;
printf("链表内元素为:\n");
while(p!=L && p->data)
{
printf("-%d",p->data);
p=p->prior;
}
printf("\n");
}
本次学习笔记如上所示,不足之处欢迎大家批评指正。