#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
/* P.28 形式定义 */
typedef int ElemType; //可根据需要修改元素的类型
typedef struct DuLNode {
ElemType data; //存放数据
struct DuLNode *prior; //存放直接前驱的指针
struct DuLNode *next; //存放直接后继的指针
} DuLNode, *DuLinkList;
/* P.19-20的抽象数据类型定义转换为实际的C语言 */
Status InitList(DuLinkList *L);
Status DestroyList(DuLinkList *L);
Status ClearList(DuLinkList *L);
Status ListEmpty(DuLinkList L);
int ListLength(DuLinkList L);
Status GetElem(DuLinkList L, int i, ElemType *e);
int LocateElem(DuLinkList L, ElemType e, Status (*compare)(ElemType e1, ElemType e2));
Status PriorElem(DuLinkList L, ElemType cur_e, ElemType *pre_e);
Status NextElem(DuLinkList L, ElemType cur_e, ElemType *next_e);
Status ListInsert(DuLinkList *L, int i, ElemType e);
Status ListDelete(DuLinkList *L, int i, ElemType *e);
Status ListTraverse(DuLinkList L, Status (*visit)(ElemType e));
#include <stdio.h>
#include <stdlib.h> //malloc/realloc函数
#include <unistd.h> //exit函数
#include "linear_list_DL.h" //形式定义
#include <stdio.h>
#include <stdlib.h> //malloc/realloc函数
#include <unistd.h> //exit函数
#include "linear_list_DL.h" //形式定义
/* 初始化线性表 */
Status InitList(DuLinkList *L)
{
/* 申请头结点空间,赋值给头指针 */
*L = (DuLNode *)malloc(sizeof(DuLNode));
if (*L==NULL)
exit(OVERFLOW);
(*L)->prior = NULL;
(*L)->next = NULL;
return OK;
}
/* 删除线性表 */
Status DestroyList(DuLinkList *L)
{
DuLinkList q, p = *L; //指向首元
/* 整个链表(含头结点)依次释放(同单链表,不考虑prior指针,只用next) */
while(p != (*L)) { //若链表为空,则循环不执行
q=p->next; //抓住链表的下一个结点
free(p);
p=q;
}
*L=NULL; //头指针置NULL
return OK;
}
/* 清除线性表(保留头结点) */
Status ClearList(DuLinkList *L)
{
DuLinkList q, p = (*L)->next;
/* 从首元结点开始依次释放(同单链表,不考虑prior指针,只用next) */
while(p != (*L)) {
q = p->next; //抓住链表的下一个结点
free(p);
p = q;
}
(*L)->next = NULL; //头结点的prior域置NULL
(*L)->next = NULL; //头结点的next域置NULL
return OK;
}
/* 判断是否为空表 */
Status ListEmpty(DuLinkList L)
{
/* 判断头结点的next域即可(同单链表) */
if (L->next==NULL)
return TRUE;
else
return FALSE;
}
/* 求表的长度 */
int ListLength(DuLinkList L)
{
DuLinkList p = L->next; //指向首元结点
int len=0;
/* 循环整个链表,进行计数(同单链表) */
while(p) {
p = p->next;
len++;
}
return len;
}
/* 取表中元素 */
Status GetElem(DuLinkList L, int i, ElemType *e)
{
DuLinkList p = L->next; //指向首元结点
int pos = 1; //初始位置为1
/* 链表不为NULL 且 未到第i个元素(同单链表) */
while(p!=NULL && pos<i) {
p=p->next;
pos++;
}
if (!p || pos>i)
return ERROR;
*e = p->data;
return OK;
}
/* 查找符合指定条件的元素 */
int LocateElem(DuLinkList L, ElemType e, Status (*compare)(ElemType e1, ElemType e2))
{
DuLinkList p = L->next; //首元结点
int pos = 1; //初始位置
/* 循环整个链表(同单链表) */
while(p && (*compare)(e, p->data)==FALSE) {
p=p->next;
pos++;
}
return p ? pos:0;
}
/* 查找符合指定条件的元素的前驱元素 */
Status PriorElem(DuLinkList L, ElemType cur_e, ElemType *pre_e)
{
DuLinkList p = L->next; //指向首元结点
if (p==NULL) //空表直接返回
return ERROR;
/* 从第2个结点开始循环整个链表(如果比较相等,保证有前驱)(同单链表) */
while(p->next && p->next->data != cur_e)
p = p->next;
if (p->next==NULL) //未找到
return ERROR;
*pre_e = p->data;
return OK;
}
/* 查找符合指定条件的元素的后继元素 */
Status NextElem(DuLinkList L, ElemType cur_e, ElemType *next_e)
{
DuLinkList p = L->next; //首元结点
if (p==NULL) //空表直接返回
return ERROR;
/* 有后继结点且当前结点值不等时继续(同单链表) */
while(p->next && p->data!=cur_e)
p = p->next;
if (p->next==NULL)
return ERROR;
*next_e = p->next->data;
return OK;
}
/* 在指定位置前插入一个新元素 */
Status ListInsert(DuLinkList *L, int i, ElemType e)
{
#if 0
DuLinkList s, p = *L; //p指向头结点
int pos = 1;
/* 寻找第i个结点(i可能是表长+1) */
while(p->next && pos<i-1) {
p=p->next;
pos++;
}
if (p->next==NULL || pos>i-1) //i值非法则返回
return ERROR;
//执行到此表示找到指定位置,p指向第i-1个结点
s = (DuLinkList)malloc(sizeof(DuLNode));
if (s==NULL)
return OVERFLOW;
if (pos==i-1) {
}
else {
/* 注意,p可能是NULL */
s->data = e; //新结点数据域赋值
s->prior = p->prior;
p->prior->next = s;
s->next = p; //新结点的next是第i个
p->prior = s; //第i-1个的next是新结点
}
#else
DuLinkList s, p = *L; //p指向头结点
int pos = 0;
/* 寻找第i-1个结点 */
while(p && pos<i-1) {
p=p->next;
pos++;
}
if (p==NULL || pos>i) //i值非法则返回
return ERROR;
//执行到此表示找到指定位置,p指向第i-1个结点
s = (DuLinkList)malloc(sizeof(DuLNode));
if (s==NULL)
return OVERFLOW;
s->data = e; //新结点数据域赋值
s->next = p->next; //新结点的next是第i个结点(即使p->next是NULL也没问题)
if (p->next) //如果有第i个结点
p->next->prior = s; //第i个结点的prior是s
s->prior = p; //s的前驱是p
p->next = s; //p的后继是s
#endif
return OK;
}
/* 删除指定位置的元素,并将被删除元素的值放入e中返回 */
Status ListDelete(DuLinkList *L, int i, ElemType *e)
{
#if 1
DuLinkList p = *L; //p指向头结点
int pos = 0;
/* 寻找第i个结点(p是第i个结点) */
while(p && pos<i) {
p=p->next;
pos++;
}
if (p==NULL || pos>i) //i值非法则返回
return ERROR;
//执行到此表示找到了第i个结点,此时p指向第i个结点
*e = p->data; //取第i个结点的值
p->prior->next = p->next;
if (p->next) //要加判断条件
p->next->prior = p->prior;
free(p); //释放第i个结点
#else
DuLinkList q, p = *L; //p指向头结点
int pos = 0;
/* 寻找第i个结点(p->next是第i个结点) */
while(p->next && pos<i-1) {
p=p->next;
pos++;
}
if (p->next==NULL || pos>i-1) //i值非法则返回
return ERROR;
//执行到此表示找到了第i个结点,此时p指向第i-1个结点
q = p->next; //q指向第i个结点
p->next = q->next; //第i-1个结点的next域指向第i+1个(即使NULL也没错)
if (q->next)
q->next->prior = p;
*e = q->data; //取第i个结点的值
free(q); //释放第i个结点
#endif
return OK;
}
/* 遍历线性表 */
Status ListTraverse(DuLinkList L, Status (*visit)(ElemType e))
{
extern int line_count; //在main中定义的打印换行计数器(与算法无关)
DuLinkList p = L->next;
line_count = 0; //计数器恢复初始值(与算法无关)
#if 1
while(p && (*visit)(p->data)==TRUE) //同单链表
p=p->next;
if (p)
return ERROR;
printf("\n");//最后打印一个换行,只是为了好看,与算法无关
#else
/* 逆序输出 */
while(p->next) //同单链表
p=p->next;
/* 执行到此,p指向最后一个结点 */
while(p && p->prior && (*visit)(p->data)==TRUE) //同单链表
p=p->prior;
printf("\n");//最后打印一个换行,只是为了好看,与算法无关
#endif
return OK;
}
#include <stdio.h>
#include "linear_list_DL.h"
#define INSERT_NUM 115 //初始插入表中的元素数量
#define MAX_NUM_PER_LINE 10 //每行最多输出的元素个数
int line_count = 0; //打印链表时的计数器
/* 用于比较两个值是否相等的具体函数,与LocateElem中的函数指针定义相同,调用时代入
int LocateElem(sqlist L, ElemType e, Status (*compare)(ElemType e1, ElemType e2)) */
Status MyCompare(ElemType e1, ElemType e2)
{
if (e1==e2)
return TRUE;
else
return FALSE;
}
/* 用于访问某个元素的值的具体函数,与ListTraverse中的函数指针定义相同,调用时代入
Status ListTraverse(sqlist L, Status (*visit)(ElemType e)) */
Status MyVisit(ElemType e)
{
printf("%3d->", e);
/* 每输出MAX_NUM_PER_LINE个,打印一个换行 */
if ((++line_count)%MAX_NUM_PER_LINE == 0)
printf("\n");
return OK;
}
int main()
{
DuLinkList L;
ElemType e1, e2;
int i, pos;
InitList(&L);
printf("空表=%s\n", (ListEmpty(L)==TRUE)?"TRUE":"FALSE");
printf("表长=%d\n\n", ListLength(L));
printf("插入%d个元素:\n", INSERT_NUM);
for (i=INSERT_NUM*2; i>0; i-=2)
ListInsert(&L, 1, i);
ListTraverse(L, MyVisit);//此处传入MyVisit函数名
printf("空表=%s\n", (ListEmpty(L)==TRUE)?"TRUE":"FALSE");
printf("表长=%d\n\n", ListLength(L));
/* 分别取第1、最后、以及小于第1、大于最后的4种情况下的的元素值、前驱值、后继值
最后再加一个任意输入值 */
for (i=0; i<5; i++) {
int pos;
switch(i) {
case 0:
pos = 1;
break;
case 1:
pos = ListLength(L);
break;
case 2:
pos = -1;
break;
case 3:
pos = ListLength(L)+1;
break;
case 4:
printf("请输入要取元素的位序[1..%d]:", ListLength(L));
scanf("%d", &pos);
break;
}
/* 取第1个元素以及前驱、后继 */
if (GetElem(L, pos, &e1)==OK) {
printf("第%d个元素=%d\n", pos, e1);
/* 只有取得了某个元素,才能取前驱和后继 */
if (PriorElem(L, e1, &e2)==OK)
printf("第%d个元素(%d)的前驱=%d\n", pos, e1, e2);
else
printf("无法取得第%d个元素(%d)的前驱\n", pos, e1);
if (NextElem(L, e1, &e2)==OK)
printf("第%d个元素(%d)的后继=%d\n\n", pos, e1, e2);
else
printf("无法取得第%d个元素(%d)的后继\n\n", pos, e1);
}
else
printf("无法取得第%d个元素\n\n", pos);
} // end of for
printf("请输入要查找的元素:\n");
scanf("%d", &e1);
if ((pos=LocateElem(L, e1, MyCompare))>0) //此处传入MyCompare函数名
printf("元素%d的位序=%d\n", e1, pos);
else
printf("找不到元素%d\n", e1);
printf("\n请输入要插入元素的值:\n");
scanf("%d", &e1);
printf("请输入要插入元素的位序:\n");
scanf("%d", &pos);
if (ListInsert(&L, pos, e1)==OK) {
printf("在%d前插入元素%d成功\n", pos, e1);
printf("新表为:\n");
ListTraverse(L, MyVisit);
}
else
printf("在%d前插入元素%d失败\n", pos, e1);
printf("\n请输入要删除元素的位序:\n");
scanf("%d", &pos);
if (ListDelete(&L, pos, &e1)==OK) {
printf("删除第%d个元素=%d成功\n", pos, e1);
printf("新表为:\n");
ListTraverse(L, MyVisit);
}
else
printf("删除第%d个元素失败\n", pos);
printf("\n清空表:\n");
ClearList(&L);
printf("空表=%s\n", (ListEmpty(L)==TRUE)?"TRUE":"FALSE");
printf("表长=%d\n", ListLength(L));
DestroyList(&L);
return 0;
}