头文件 head.h
<pre name="code" class="cpp">#include<string.h>
#include<ctype.h>
#include<malloc.h> /* malloc()等 */
#include<limits.h> /* INT_MAX等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<stdlib.h> /* atoi() */
#include<io.h> /* eof() */
#include<math.h> /* floor(),ceil(),abs() */
#include<process.h> /* exit() */
/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
/* #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 */
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
typedef int ElemType;
typedef struct DLNode{
ElemType data;
struct DLNode *next, *prior;
}DLNode;
typedef struct DLNode *LinkList_DL;
Status InitList_DL(LinkList_DL *L);
Status DestoryList_DL(LinkList_DL *L);
Status ClearList_DL(LinkList_DL *L);
Status ListEmpty_DL(LinkList_DL L);
int ListLength_DL(LinkList_DL L);
Status GetElem_DL(LinkList_DL L, int i, ElemType *e);
int LocateElem_DL(LinkList_DL L, ElemType e);
Status PriorElem_DL(LinkList_DL L, ElemType cur_e, ElemType *pri_e);
Status NextElem_DL(LinkList_DL L, ElemType cur_e, ElemType *next_e);
LinkList_DL GetElemP_DL(LinkList_DL L, int i);
Status ListInsert_DL(LinkList_DL L, int i, ElemType e);
Status ListDelete_DL(LinkList_DL L, int i, ElemType *e);
Status ListTraverse_DL(LinkList_DL L);
Status ListTraverseBack_DL(LinkList_DL L);
</pre><pre name="code" class="cpp">实现方法
<pre name="code" class="cpp">#include"head.h"
/*
和循环链表不同的是,该方法没有尾指针,L就是头结点,
if(L->next->next == L)
则只有一个元素
*/
Status InitList_DL(LinkList_DL *L)
{
//产生空的双向循环链表L
(*L) = (LinkList_DL)malloc(sizeof(DLNode));
if (!(*L))
{
printf("双线性链表初始化失败!");
return ERROR;
}
else
{
(*L)->next = (*L)->prior = (*L);
return OK;
}
}
Status DestoryList_DL(LinkList_DL *L)
{
//销毁双向循环链表L,该方法和单向循环链表一样
LinkList_DL p, q = (*L)->next; //指向第一个结点
while (q != (*L)) //判断不为空
{
//注意顺序!!!!
p = q->next; //必须先将q的下一个元素指向p,要不然在下一步释放时就没有了!!!
free(q);
q = p;
}
free(*L);
*L = NULL;
return OK;
}
Status ClearList_DL(LinkList_DL *L)
{
//将表L置为空表
LinkList_DL p, q = (*L)->next; //q指向第一个结点
while (q != (*L)) //没有到表头,清空之后就只剩下表头,和初始化时一样的
{
p = q->next; //必须先将q的下一个元素指向p,要不然在下一步释放时就没有了!!!
free(q);
q = p;
}
(*L)->next = (*L)->prior = (*L);
return OK;
}
Status ListEmpty_DL(LinkList_DL L)
{
//判断该表L是否为空
if ((L->next) == L)
return TRUE;
else
return FALSE;
}
int ListLength_DL(LinkList_DL L)
{
//返回表L中元素的个数
int n = 0;
LinkList_DL p = L->next; //第一个元素
while (p != L) //没有到表尾
{
n++;
p = p->next;
}
return n;
}
Status GetElem_DL(LinkList_DL L, int i, ElemType *e)
{
//当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR
int n = 1;
LinkList_DL p = L->next; //L为头结点,p为第一个结点
// L = L->next; //第一个结点
if (i<1 || i>ListLength_DL(L) + 1)
return ERROR;
while (p != L && n<i)
{
p = p->next;
n++;
}
*e = p->next->data;
return OK;
}
int LocateElem_DL(LinkList_DL L, ElemType e)
{
//返回L中与元素e相等的元素的位置
int n = 1;
LinkList_DL p = L->next;
while (p != L)
{
if ((p->data) == e)
return n;
n++;
p = p->next;
}
return ERROR;
}
Status PriorElem_DL(LinkList_DL L, ElemType cur_e, ElemType *pri_e)
{
//返回元素cur_e的前驱
LinkList_DL p = L->next->next; //第二个结点
while (p != L) //p没有到表头
{
if ((p->data) == cur_e)
{
*pri_e = p->prior->data;
return OK;
}
p = p->next;
}
return FALSE;
}
Status NextElem_DL(LinkList_DL L, ElemType cur_e, ElemType *next_e)
{
LinkList_DL p = L->next->next; //这样做是为了防止该元素没有后继元素
while (p != L)
{
if ((p->prior->data) == cur_e)
{
*next_e = p->data;
return TRUE;
}
p = p->next;
}
return FALSE;
}
LinkList_DL GetElemP_DL(LinkList_DL L, int i)
{
//在双向链表中返回第i个元素的地址
//i=0,返回头结点的地址;若第i个元素不存在,返回NULL;
LinkList_DL p = L; //p指向头结点
int n = 1;
if (i<1 || i>ListLength_DL(L) + 1)
return NULL;
while (n <= i)
{
p = p->next;
n++;
}
return p;
}
Status ListInsert_DL(LinkList_DL L, int i, ElemType e)
{
//在带头结点的双链循环线性表L中第i个位置之前插入元素e,i的合法值为1<=i<=表长+1
LinkList_DL p, s;
if (i<1 || i>ListLength_DL(L) + 1)
return ERROR;
p = GetElemP_DL(L, i);
if (!p)
return ERROR;
s = (LinkList_DL)malloc(sizeof(struct DLNode));
if (!s)
return ERROR;
//根据图示,由左向右处理
s->data = e;
s->prior = p->prior;
p->prior->next = s;
s->next = p;
p->prior = s;
return OK;
}
Status ListDelete_DL(LinkList_DL L, int i, ElemType *e)
{
//删除带头结点的双链循环线性表L的第i个元素
LinkList_DL p;
if (i<1 || i>ListLength_DL(L) + 1)
return FALSE;
p = GetElemP_DL(L, i);
if (!p)
return FALSE;
*e = p->data;
p->prior->next = p->next;
p->next->prior = p->prior;
free(p);
return OK;
}
Status ListTraverse_DL(LinkList_DL L)
{
LinkList_DL p = L->next;
while (p != L)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
return OK;
}
Status ListTraverseBack_DL(LinkList_DL L)
{
LinkList_DL p = L->prior;
while (p != L)
{
printf("%d ", p->data);
p = p->prior;
}
printf("\n");
return OK;
}
Status GetElem_DL(LinkList_DL L, int i, ElemType *e);int LocateElem_DL(LinkList_DL L, ElemType e);Status PriorElem_DL(LinkList_DL L, ElemType cur_e, ElemType *pri_e);Status NextElem_DL(LinkList_DL L, ElemType cur_e, ElemType *next_e);LinkList_DL GetElemP_DL(LinkList_DL L, int i);Status ListInsert_DL(LinkList_DL L, int i, ElemType e);Status ListDelete_DL(LinkList_DL L, int i, ElemType *e);Status ListTraverse_DL(LinkList_DL L);Status ListTraverseBack_DL(LinkList_DL L); 测试文件
#include"head.h"
void main()
{
LinkList_DL L;
int i, n;
Status j;
ElemType e;
InitList_DL(&L);
for (i = 1; i <= 5; i++)
ListInsert_DL(L, i, i); /* 在第i个结点之前插入i */
// printf("length=%d\n", ListLength_DL(L));
printf("正序输出链表:");
ListTraverse_DL(L); /* 正序输出 */
printf("逆序输出链表:");
ListTraverseBack_DL(L); /* 逆序输出 */
printf("请输入要删除的结点数n【1-%d】:", ListLength_DL(L));
scanf_s("%d", &n);
ListDelete_DL(L, n, &e); /* 删除并释放第n个结点 */
printf("删除第%d个结点,值为%d,其余结点为:", n, e);
ListTraverse_DL(L); /* 正序输出 */
printf("链表的元素个数为%d\n", ListLength_DL(L));
printf("链表是否空:%d(1:是 0:否)\n", ListEmpty_DL(L));
ClearList_DL(&L); /* 清空链表 */
printf("清空后,链表是否空:%d(1:是 0:否)\n", ListEmpty_DL(L));
for (i = 1; i <= 5; i++)
ListInsert_DL(L, i, i); /* 重新插入5个结点 */
ListTraverse_DL(L); /* 正序输出 */
n = 3;
j = GetElem_DL(L, n, &e); /* 将链表的第n个元素赋值给e */
if (j)
printf("链表的第%d个元素值为%d\n", n, e);
else
printf("不存在第%d个元素\n", n);
n = 4;
i = LocateElem_DL(L, n);
if (i)
printf("等于%d的元素是第%d个\n", n, i);
else
printf("没有等于%d的元素\n", n);
j = PriorElem_DL(L, n, &e);
if (j)
printf("%d的前驱是%d\n", n, e);
else
printf("不存在%d的前驱\n", n);
j = NextElem_DL(L, n, &e);
if (j)
printf("%d的后继是%d\n", n, e);
else
printf("不存在%d的后继\n", n);
DestoryList_DL(&L);
system("pause");
}
Running Result:
序输出链表:1 2 3 4 5
序输出链表:5 4 3 2 1
输入要删除的结点数n【1-5】:2
除第2个结点,值为2,其余结点为:1 3 4 5
表的元素个数为4
表是否空:0(1:是 0:否)
空后,链表是否空:1(1:是 0:否)
2 3 4 5
表的第3个元素值为4
于4的元素是第4个
的前驱是3
的后继是5
按任意键继续. . .