@coder-pig
2019-05-31T14:24:47.000000Z
字数 3823
阅读 1844
数据结构
学习要点:
1.了解引入双向循环链表的原因
2.熟悉双向循环链表的特点以及存储结构
3.掌握双向循环链表的一些基本操作的实现逻辑
4.掌握逆序输出双向循环链表元素逻辑
双向循环链表的特点:
上面也说了,空间换时间,比起循环链表只是多了一个指向前驱的指针
特点的话:
判断空表:L ->next = L -> prior = L;
存储结构:
typedef struct LNode
{
ElemType data; //数据域
struct LNode *prior; //前驱指针
struct LNode *next; //后继指针
}LNode;
typedef struct LNode *LinkList;
双向循环链表的结构图:
Status InitList(LinkList L)
{
L = (LinkList)malloc(sizeof(LNode));
if(!L)exit(ERROR);
else L ->next = L ->prior = L;
return OK;
}
逻辑解析:
很简单,就是头结点自己指自己而已~
void ClearList(LinkList L)
{
LinkList p = L ->next; //指向第一个结点
while(p != L)
{
p = p ->next; //指向下一个结点
free(p->prior); //释放该结点的前驱结点
}
L ->next = L ->prior = L; //自己指自己
}
Status ListEmpty(LinkList L)
{
return L->next == L && L ->prior == L?TRUE:FALSE;
}
void DestoryList(LinkList L)
{
ClearList(L);
free(L);
L = NULL;
}
int ListLength(LinkList L)
{
int i = 0;
LinkList p = L ->next;
while(p != L)
{
i++;
p = p ->next;
}
return i;
}
Status GetElem(LinkList L,int i,ElemType *e)
{
int j = 1;
LinkList p = L ->next; //指向第一个结点
while(p != L && j < i) //指针后移
{
j++;
p = p ->next;
}
if(p == L || j > i)return ERROR; //找不到该元素
e = p ->data;
return OK;
}
int LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType))
{
int i = 0;
LinkList p = L ->next ->next; //指向第一个结点
while(p != L ->next)
{
i++;
if(compare(p->data,e))return i;
p = p ->next;
}
return 0; //找不到,返回0
}
Status BeforeElem(LinkList L,ElemType choose,ElemType *before)
{
LinkList p = L ->next ->next; //指向第二个结点
while(p != L) //未指向头结点
{
if(p ->data == choose)
{
before = p ->prior ->data;
return OK;
}
p = p ->next;
}
return ERROR;
}
Status NextElem(LinkList L,ElemType choose,ElemType *behind)
{
LinkList p = L ->next ->next; //指向第二个结点
while(p != L)
{
if(p ->prior ->data == choose)
{
behind = p ->data;
return OK;
}
p = p ->next;
}
return ERROR;
}
LinkList GetElemAdd(LinkList L,int i)
{
int j;
LinkList p = L;
if(i < 0 || i > ListLength(L))return NULL; //判断i值位置是否合法
for(j = 1;j < = i;j++)
{
p = p ->next;
}
return p;
}
Status ListInsert(LinkList L,int i,ElemType e)
{
LinkList p,q;
//判断i值是否合法
if(i < 1 || i > ListLength(L) + 1)return ERROR;
p = GetElemAdd(L,i - 1);
//NULL的话说明,第i个结点的前驱不存在,
//这里假设头节点为第一个结点的前驱
if(!p)return ERROR;
q = (LinkList)malloc(sizeof(LNode));
if(!q)return ERROR;
q ->data = e; //给新结点赋值
q ->prior = p; //新结点的前驱为第i - 1个结点
q ->next = p ->next; //新结点的后记为第i个结点
p ->next ->prior = q; //第i个结点前驱指向新结点
p ->next = q; //第i-1个结点的后继指向新结点
return OK;
}
实现逻辑图:
Status ListDelete(LinkList L,int i,ElemType *e)
{
LinkList p;
if(i < 1)return ERROR; //判断删除位置是否合法
p = GetElemAdd(L,i);
if(!p)return ERROR; //为NULL说明第i个元素不存在
e = p ->data;
p ->prior ->next = p ->next; //i-1个结点的后继指向滴i+1个结点
p ->next ->prior = p ->prior; //第i+1个结点的前驱指向第i - 1个结点
free(p); //释放第i个结点
return OK;
}
实现逻辑图:
嘿嘿,是不是觉得少了个遍历表中元素的基本操作呢,别急,我们下面写个例子,
按正序遍历链表,以及逆序来遍历表中的所有元素~
运行截图:
代码实现:
#include <stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int ElemType;
typedef int Status;
typedef struct LNode
{
ElemType data; //数据域
struct LNode *prior; //前驱指针
struct LNode *next; //后继指针
}LNode;
typedef struct LNode *LinkList;
//定义一个创建N个结点的方法
LinkList ListCreate(int N)
{
LinkList p,q,head;
int i,data;
q = head;
head = (LinkList)malloc(sizeof(LNode));
head ->prior = head;
head ->next = head;
p = head;
for(i = 0;i < N;i++)
{
printf("请输入第%d个结点的值:",i + 1);
scanf("%d",&data);
q = (LinkList)malloc(sizeof(LNode));
q ->data = data;
p ->next = q;
q ->prior = p;
q ->next = head;
head ->prior = q;
p = q;
}
return head;
}
//定义一个打印结点数据的方法
void PrintNode(ElemType e)
{
printf("%d\t",e);
}
//定义一个正序输出链表的方法
void ListTraverse(LinkList L)
{
LinkList p = L->next; //指向首元结点
while(p!=L)
{
PrintNode(p->data);
p = p ->next;
}
printf("\n");
}
//定义一个逆序输出链表的方法
void ListTraverseBack(LinkList L)
{
LinkList p = L ->prior; //指向最后一个结点
while(p!=L)
{
PrintNode(p->data);
p = p ->prior;
}
printf("\n");
}
int main()
{
LinkList p;
int N = 0;
printf("请输入双向链表的结点个数:");
scanf("%d", &N);
p = ListCreate(N);
printf("正序打印链表中的结点:\n");
ListTraverse(p);
printf("逆序打印链表中的结点:\n");
ListTraverseBack(p);
return 0;
}
很简单,就不BB了~
https://github.com/coder-pig/Data-structure-auxiliary-tutorial/blob/master/List/list5.c
https://github.com/coder-pig/Data-structure-auxiliary-tutorial/blob/master/List/list6.c