本章主要讲的是顺序线性表的实现,以及单向链表,双向链表C语言实现
- 抽象数据类型之表List
- 什么是抽象数据类型
- 表ADT
- 表的定义
- 表的基本操作
- 一List顺序线性表
- 定义
- 实现
- 链表
- 单项链表
- 定义
- 实现
- 双向链表
- 定义
- 实现
抽象数据类型(ADT)是一些操作的集合
ADT List
{
Data object:D = {ai | ai∈Elemset, (i=1,2,…,n, n≥0)}
Data relationshis:R1 = {<ai-1,ai>|ai-1,ai ∈D, (i=2,3,…,n) }
operations:
InitList(&L);
DestroyList(&L);
ListInsert(&L,i,e);
ListDelete(&L,i,&e);
and so on
} ADT List
(1) InitList(&L);
DestroyList(&L);
ClearList(&L);
(2) ListEmpty(L);
(3) GetElem(L, i, &e);
LocateElem(L, e, compare());
PriorElem(L, cur_e, &pre_e);
NextElem(L, cur_e, &next_e);
(4) ListInsert(&L, i, e);
ListDelete(&L, i, &e);
(5) ListTraverse(&L, visited())
#include
#include /* malloc()? */
#include /* INT_MAX? */
#include /* EOF(=^Z?F6),NULL */
#include /* atoi() */
#include /* eof() */
#include /* floor(),ceil(),abs() */
#include /* exit() */
/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
typedef int ElemType;
typedef ElemType *Triplet;
typedef struct
{
ElemType *elem; /* ?????? */
int length; /* ???? */
int listsize; /* ?????????(?sizeof(ElemType)???) */
}SqList;
void InitList(SqList *L) ;
void DestroyList(SqList *L);
void ClearList(SqList *L);
Status ListEmpty(SqList L);
int ListLength(SqList L);
Status GetElem(SqList L,int i,ElemType *e);
int LocateElem(SqList L,ElemType e,Status(*compare)(ElemType,ElemType));
Status PriorElem(SqList L,ElemType cur_e,ElemType *pre_e);
Status NextElem(SqList L,ElemType cur_e,ElemType *next_e);
Status ListInsert(SqList *L,int i,ElemType e) ;
Status ListDelete(SqList *L,int i,ElemType *e) ;
void ListTraverse(SqList L,void(*vi)(ElemType*));
Status equal(ElemType c1,ElemType c2);
int comp(ElemType a,ElemType b);
void print(ElemType c);
void print2(ElemType c);
void print1(ElemType *c);
void InitList(SqList *L) /* 算法2.3 */
{ /* 操作结果:构造一个空的顺序线性表L */
(*L).elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if(!(*L).elem)
exit(OVERFLOW); /* 存储分配失败 */
(*L).length=0; /* 空表长度为0 */
(*L).listsize=LIST_INIT_SIZE; /* 初始存储容量 */
}
void DestroyList(SqList *L)
{ /* 初始条件:顺序线性表L已存在。操作结果:销毁顺序线性表L */
free((*L).elem);
(*L).elem=NULL;
(*L).length=0;
(*L).listsize=0;
}
void ClearList(SqList *L)
{ /* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
(*L).length=0;
}
Status ListEmpty(SqList L)
{ /* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
if(L.length==0)
return TRUE;
else
return FALSE;
}
int ListLength(SqList L)
{ /* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
return L.length;
}
Status GetElem(SqList L,int i,ElemType *e)
{ /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L)。操作结果:用e返回L中第i个数据元素的值 */
if(i<1||i>L.length)
return ERROR;
*e=*(L.elem+i-1);
return OK;
}
int LocateElem(SqList L,ElemType e,Status(*compare)(ElemType,ElemType))
{ /* 初始条件:顺序线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0) */
/* 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0。算法2.6 */
ElemType *p;
int i=1; /* i的初值为第1个元素的位序 */
p=L.elem; /* p的初值为第1个元素的存储位置 */
while(i<=L.length&&!compare(*p++,e))
++i;
if(i<=L.length)
return i;
else
return 0;
}
Status PriorElem(SqList L,ElemType cur_e,ElemType *pre_e)
{ /* 初始条件:顺序线性表L已存在 */
/* 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, */
/* 否则操作失败,pre_e无定义 */
int i=2;
ElemType *p=L.elem+1;
while(i<=L.length&&*p!=cur_e)
{
p++;
i++;
}
if(i>L.length)
return INFEASIBLE; /* 操作失败 */
else
{
*pre_e=*--p;
return OK;
}
}
Status NextElem(SqList L,ElemType cur_e,ElemType *next_e)
{ /* 初始条件:顺序线性表L已存在 */
/* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, */
/* 否则操作失败,next_e无定义 */
int i=1;
ElemType *p=L.elem;
while(iif(i==L.length)
return INFEASIBLE; /* 操作失败 */
else
{
*next_e=*++p;
return OK;
}
}
Status ListInsert(SqList *L,int i,ElemType e) /* 算法2.4 */
{ /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L)+1 */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
ElemType *newbase,*q,*p;
if(i<1||i>(*L).length+1) /* i值不合法 */
return ERROR;
if((*L).length>=(*L).listsize) /* 当前存储空间已满,增加分配 */
{
newbase=(ElemType *)realloc((*L).elem,((*L).listsize+LIST_INCREMENT)*sizeof(ElemType));
if(!newbase)
exit(OVERFLOW); /* 存储分配失败 */
(*L).elem=newbase; /* 新基址 */
(*L).listsize+=LIST_INCREMENT; /* 增加存储容量 */
}
q=(*L).elem+i-1; /* q为插入位置 */
for(p=(*L).elem+(*L).length-1;p>=q;--p) /* 插入位置及之后的元素右移 */
*(p+1)=*p;
*q=e; /* 插入e */
++(*L).length; /* 表长增1 */
return OK;
}
Status ListDelete(SqList *L,int i,ElemType *e) /* 算法2.5 */
{ /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
ElemType *p,*q;
if(i<1||i>(*L).length) /* i值不合法 */
return ERROR;
p=(*L).elem+i-1; /* p为被删除元素的位置 */
*e=*p; /* 被删除元素的值赋给e */
q=(*L).elem+(*L).length-1; /* 表尾元素的位置 */
for(++p;p<=q;++p) /* 被删除元素之后的元素左移 */
*(p-1)=*p;
(*L).length--; /* 表长减1 */
return OK;
}
void ListTraverse(SqList L,void(*vi)(ElemType*))
{ /* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素调用函数vi() */
/* vi()的形参加'&',表明可通过调用vi()改变元素的值 */
ElemType *p;
int i;
p=L.elem;
for(i=1;i<=L.length;i++)
vi(p++);
printf("\n");
}
#include
#include
#include /* malloc()? */
#include /* INT_MAX? */
#include /* EOF(=^Z?F6),NULL */
#include /* atoi() */
#include /* eof() */
#include /* floor(),ceil(),abs() */
#include /* 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;
struct LNode
{
ElemType data;
LNode *next;
};
typedef LNode *LinkList; // 另一种定义LinkList的方法
Status equal(ElemType c1,ElemType c2);
int comp(ElemType a,ElemType b);
void print(ElemType c);
void print2(ElemType c);
void print1(ElemType &c);
void MakeNode(Link &p,ElemType e);
void FreeNode(Link &p);
void InitList(LinkList &L);
void ClearList(LinkList &L);
void DestroyList(LinkList &L);
void InsFirst(LinkList &L,Link h,Link s) ;
Status DelFirst(LinkList &L,Link h,Link &q) ;
void Append(LinkList &L,Link s);
Position PriorPos(LinkList L,Link p);
Status Remove(LinkList &L,Link &q);
void InsBefore(LinkList &L,Link &p,Link s);
void InsAfter(LinkList &L,Link &p,Link s);
void SetCurElem(Link p,ElemType e);
ElemType GetCurElem(Link p);
Status ListEmpty(LinkList L);
int ListLength(LinkList L);
Position GetHead(LinkList L);
Position GetLast(LinkList L);
Position NextPos(Link p);
Status LocatePos(LinkList L,int i,Link &p);
Position LocateElem(LinkList L,ElemType e,Status (*compare)(ElemType,ElemType));
void ListTraverse(LinkList L,void(*visit)(ElemType));
void OrderInsert(LinkList &L,ElemType e,int (*comp)(ElemType,ElemType));
Status LocateElem(LinkList L,ElemType e,Position &q,int(*compare)(ElemType,ElemType));
void MakeNode(Link &p,ElemType e)
{ // 分配由p指向的值为e的结点。若分配失败,则退出
p=(Link)malloc(sizeof(LNode));
if(!p)
exit(ERROR);
p->data=e;
}
void FreeNode(Link &p)
{ // 释放p所指结点
free(p);
p=NULL;
}
void InitList(LinkList &L)
{ // 构造一个空的线性链表L
Link p;
p=(Link)malloc(sizeof(LNode)); // 生成头结点
if(p)
{
p->next=NULL;
L.head=L.tail=p;
L.len=0;
}
else
exit(ERROR);
}
void ClearList(LinkList &L)
{ // 将线性链表L重置为空表,并释放原链表的结点空间
Link p,q;
if(L.head!=L.tail) // 不是空表
{
p=q=L.head->next;
L.head->next=NULL;
while(p!=L.tail)
{
p=q->next;
free(q);
q=p;
}
free(q);
L.tail=L.head;
L.len=0;
}
}
void DestroyList(LinkList &L)
{ // 销毁线性链表L,L不再存在
ClearList(L); // 清空链表
FreeNode(L.head);
L.tail=NULL;
L.len=0;
}
void InsFirst(LinkList &L,Link h,Link s) // 形参增加L,因为需修改L
{ // h指向L的一个结点,把h当做头结点,将s所指结点插入在第一个结点之前
s->next=h->next;
h->next=s;
if(h==L.tail) // h指向尾结点
L.tail=h->next; // 修改尾指针
L.len++;
}
Status DelFirst(LinkList &L,Link h,Link &q) // 形参增加L,因为需修改L
{ // h指向L的一个结点,把h当做头结点,删除链表中的第一个结点并以q返回。
// 若链表为空(h指向尾结点),q=NULL,返回FALSE
q=h->next;
if(q) // 链表非空
{
h->next=q->next;
if(!h->next) // 删除尾结点
L.tail=h; // 修改尾指针
L.len--;
return OK;
}
else
return FALSE; // 链表空
}
void Append(LinkList &L,Link s)
{ // 将指针s(s->data为第一个数据元素)所指(彼此以指针相链,以NULL结尾)的
// 一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新的尾结点
int i=1;
L.tail->next=s;
while(s->next)
{
s=s->next;
i++;
}
L.tail=s;
L.len+=i;
}
Position PriorPos(LinkList L,Link p)
{ // 已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置。若无前驱,则返回NULL
Link q;
q=L.head->next;
if(q==p) // 无前驱
return NULL;
else
{
while(q->next!=p) // q不是p的直接前驱
q=q->next;
return q;
}
}
Status Remove(LinkList &L,Link &q)
{ // 删除线性链表L中的尾结点并以q返回,改变链表L的尾指针指向新的尾结点
Link p=L.head;
if(L.len==0) // 空表
{
q=NULL;
return FALSE;
}
while(p->next!=L.tail)
p=p->next;
q=L.tail;
p->next=NULL;
L.tail=p;
L.len--;
return OK;
}
void InsBefore(LinkList &L,Link &p,Link s)
{ // 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前,
// 并修改指针p指向新插入的结点
Link q;
q=PriorPos(L,p); // q是p的前驱
if(!q) // p无前驱
q=L.head;
s->next=p;
q->next=s;
p=s;
L.len++;
}
void InsAfter(LinkList &L,Link &p,Link s)
{ // 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后,
// 并修改指针p指向新插入的结点
if(p==L.tail) // 修改尾指针
L.tail=s;
s->next=p->next;
p->next=s;
p=s;
L.len++;
}
void SetCurElem(Link p,ElemType e)
{ // 已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值
p->data=e;
}
ElemType GetCurElem(Link p)
{ // 已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值
return p->data;
}
Status ListEmpty(LinkList L)
{ // 若线性链表L为空表,则返回TRUE,否则返回FALSE
if(L.len)
return FALSE;
else
return TRUE;
}
int ListLength(LinkList L)
{ // 返回线性链表L中元素个数
return L.len;
}
Position GetHead(LinkList L)
{ // 返回线性链表L中头结点的位置
return L.head;
}
Position GetLast(LinkList L)
{ // 返回线性链表L中最后一个结点的位置
return L.tail;
}
Position NextPos(Link p)
{ // 已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置。若无后继,则返回NULL
return p->next;
}
Status LocatePos(LinkList L,int i,Link &p)
{ // 返回p指示线性链表L中第i个结点的位置,并返回OK,i值不合法时返回ERROR。i=0为头结点
int j;
if(i<0||i>L.len)
return ERROR;
else
{
p=L.head;
for(j=1;j<=i;j++)
p=p->next;
return OK;
}
}
Position LocateElem(LinkList L,ElemType e,Status (*compare)(ElemType,ElemType))
{ // 返回线性链表L中第1个与e满足函数compare()判定关系的元素的位置,
// 若不存在这样的元素,则返回NULL
Link p=L.head;
do
p=p->next;
while(p&&!(compare(p->data,e))); // 没到表尾且没找到满足关系的元素
return p;
}
void ListTraverse(LinkList L,void(*visit)(ElemType))
{ // 依次对L的每个数据元素调用函数visit()
Link p=L.head->next;
int j;
for(j=1;j<=L.len;j++)
{
visit(p->data);
p=p->next;
}
printf("\n");
}
void OrderInsert(LinkList &L,ElemType e,int (*comp)(ElemType,ElemType))
{ // 已知L为有序线性链表,将元素e按非降序插入在L中。(用于一元多项式)
Link o,p,q;
q=L.head;
p=q->next;
while(p!=NULL&&comp(p->data,e)<0) // p不是表尾且元素值小于e
{
q=p;
p=p->next;
}
o=(Link)malloc(sizeof(LNode)); // 生成结点
o->data=e; // 赋值
q->next=o; // 插入
o->next=p;
L.len++; // 表长加1
if(!p) // 插在表尾
L.tail=o; // 修改尾结点
}
Status LocateElem(LinkList L,ElemType e,Position &q,int(*compare)(ElemType,ElemType))
{ // 若升序链表L中存在与e满足判定函数compare()取值为0的元素,则q指示L中
// 第一个值为e的结点的位置,并返回TRUE;否则q指示第一个与e满足判定函数
// compare()取值>0的元素的前驱的位置。并返回FALSE。(用于一元多项式)
Link p=L.head,pp;
do
{
pp=p;
p=p->next;
}while(p&&(compare(p->data,e)<0)); // 没到表尾且p->data.expn
if(!p||compare(p->data,e)>0) // 到表尾或compare(p->data,e)>0
{
q=pp;
return FALSE;
}
else // 找到
{
q=p;
return TRUE;
}
}
}
#include
#include
#include /* malloc()? */
#include /* INT_MAX? */
#include /* EOF(=^Z?F6),NULL */
#include /* atoi() */
#include /* eof() */
#include /* floor(),ceil(),abs() */
#include /* 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 DuLNode
{
ElemType data;
DuLNode *prior,*next;
}DuLNode,*DuLinkList;
Status equal(ElemType c1,ElemType c2);
int comp(ElemType a,ElemType b);
void print(ElemType c);
void print2(ElemType c);
void print1(ElemType &c);
void InitList(DuLinkList &L);
void DestroyList(DuLinkList &L);
void 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,ElemType));
Status PriorElem(DuLinkList L,ElemType cur_e,ElemType &pre_e);
Status NextElem(DuLinkList L,ElemType cur_e,ElemType &next_e);
DuLinkList GetElemP(DuLinkList L,int i) ;
Status ListInsert(DuLinkList L,int i,ElemType e);
Status ListDelete(DuLinkList L,int i,ElemType &e) ;
void ListTraverse(DuLinkList L,void(*visit)(ElemType));
void ListTraverseBack(DuLinkList L,void(*visit)(ElemType));
void InitList(DuLinkList &L)
{ // 产生空的双向循环链表L
L=(DuLinkList)malloc(sizeof(DuLNode));
if(L)
L->next=L->prior=L;
else
exit(OVERFLOW);
}
void DestroyList(DuLinkList &L)
{ // 操作结果:销毁双向循环链表L
DuLinkList q,p=L->next; // p指向第一个结点
while(p!=L) // p没到表头
{
q=p->next;
free(p);
p=q;
}
free(L);
L=NULL;
}
void ClearList(DuLinkList L) // 不改变L
{ // 初始条件:L已存在。操作结果:将L重置为空表
DuLinkList q,p=L->next; // p指向第一个结点
while(p!=L) // p没到表头
{
q=p->next;
free(p);
p=q;
}
L->next=L->prior=L; // 头结点的两个指针域均指向自身
}
Status ListEmpty(DuLinkList L)
{ // 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE
if(L->next==L&&L->prior==L)
return TRUE;
else
return FALSE;
}
int ListLength(DuLinkList L)
{ // 初始条件:L已存在。操作结果:返回L中数据元素个数
int i=0;
DuLinkList p=L->next; // p指向第一个结点
while(p!=L) // p没到表头
{
i++;
p=p->next;
}
return i;
}
Status GetElem(DuLinkList L,int i,ElemType &e)
{ // 当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR
int j=1; // j为计数器
DuLinkList p=L->next; // p指向第一个结点
while(p!=L&&j// 顺指针向后查找,直到p指向第i个元素或p指向头结点
{
p=p->next;
j++;
}
if(p==L||j>i) // 第i个元素不存在
return ERROR;
e=p->data; // 取第i个元素
return OK;
}
int LocateElem(DuLinkList L,ElemType e,Status(*compare)(ElemType,ElemType))
{ // 初始条件:L已存在,compare()是数据元素判定函数
// 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。
// 若这样的数据元素不存在,则返回值为0
int i=0;
DuLinkList p=L->next; // p指向第1个元素
while(p!=L)
{
i++;
if(compare(p->data,e)) // 找到这样的数据元素
return i;
p=p->next;
}
return 0;
}
Status PriorElem(DuLinkList L,ElemType cur_e,ElemType &pre_e)
{ // 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,
// 前驱,否则操作失败,pre_e无定义
DuLinkList p=L->next->next; // p指向第2个元素
while(p!=L) // p没到表头
{
if(p->data==cur_e)
{
pre_e=p->prior->data;
return TRUE;
}
p=p->next;
}
return FALSE;
}
Status NextElem(DuLinkList L,ElemType cur_e,ElemType &next_e)
{ // 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,
// 否则操作失败,next_e无定义
DuLinkList p=L->next->next; // p指向第2个元素
while(p!=L) // p没到表头
{
if(p->prior->data==cur_e)
{
next_e=p->data;
return TRUE;
}
p=p->next;
}
return FALSE;
}
DuLinkList GetElemP(DuLinkList L,int i) // 另加
{ // 在双向链表L中返回第i个元素的地址。i为0,返回头结点的地址。若第i个元素不存在,
// 返回NULL(算法2.18、2.19要调用的函数)
int j;
DuLinkList p=L; // p指向头结点
if(i<0||i>ListLength(L)) // i值不合法
return NULL;
for(j=1;j<=i;j++)
p=p->next;
return p;
}
Status ListInsert(DuLinkList L,int i,ElemType e)
{ // 在带头结点的双链循环线性表L中第i个位置之前插入元素e,i的合法值为1≤i≤表长+1
// 改进算法2.18,否则无法在第表长+1个结点之前插入元素
DuLinkList p,s;
if(i<1||i>ListLength(L)+1) // i值不合法
return ERROR;
p=GetElemP(L,i-1); // 在L中确定第i个元素前驱的位置指针p
if(!p) // p=NULL,即第i个元素的前驱不存在(设头结点为第1个元素的前驱)
return ERROR;
s=(DuLinkList)malloc(sizeof(DuLNode));
if(!s)
return OVERFLOW;
s->data=e;
s->prior=p; // 在第i-1个元素之后插入
s->next=p->next;
p->next->prior=s;
p->next=s;
return OK;
}
Status ListDelete(DuLinkList L,int i,ElemType &e) // 算法2.19
{ // 删除带头结点的双链循环线性表L的第i个元素,i的合法值为1≤i≤表长
DuLinkList p;
if(i<1) // i值不合法
return ERROR;
p=GetElemP(L,i); // 在L中确定第i个元素的位置指针p
if(!p) // p=NULL,即第i个元素不存在
return ERROR;
e=p->data;
p->prior->next=p->next;
p->next->prior=p->prior;
free(p);
return OK;
}
void ListTraverse(DuLinkList L,void(*visit)(ElemType))
{ // 由双链循环线性表L的头结点出发,正序对每个数据元素调用函数visit()
DuLinkList p=L->next; // p指向头结点
while(p!=L)
{
visit(p->data);
p=p->next;
}
printf("\n");
}
void ListTraverseBack(DuLinkList L,void(*visit)(ElemType))
{ // 由双链循环线性表L的头结点出发,逆序对每个数据元素调用函数visit()。另加
DuLinkList p=L->prior; // p指向尾结点
while(p!=L)
{
visit(p->data);
p=p->prior;
}
printf("\n");
}