1.连续线性表
头文件
#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;
#define LIST_INIT_SIZE 10 /* 线性表存储空间的初始分配量 */
#define LISTINCREMENT 2 /* 线性表存储空间的分配增量 */
typedef struct
{
ElemType *elem; /* 存储空间基址 */
int length; /* 当前长度 */
int listsize; /* 当前分配的存储容量(以sizeof(ElemType)为单位) */
}SqList;
Status InitList(SqList *L);
Status DestroyList(SqList *L);
Status 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);
Status ListTraverse(SqList L, void(*vi)(ElemType*));
void InsertAscend(SqList *L, ElemType e);
void InsertDescend(SqList *L, ElemType e);
Status HeadInsert(SqList *L, ElemType e);
Status EndInsert(SqList *L, ElemType e);
Status DeleteFirst(SqList *L, ElemType *e);
Status DeleteTail(SqList *L, ElemType *e);
Status DeleteElem(SqList *L, ElemType e);
Status ReplaceElem(SqList L, int i, ElemType e);
Status CreatAscend(SqList *L, int n);
Status CreatDescend(SqList *L, int n);
实现文件
#include "arrList.h"
Status InitList(SqList *L) /* 算法2.3 */
{ /* 操作结果:构造一个空的顺序线性表 */
(*L).elem = (ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if (!(*L).elem)
exit(OVERFLOW); /* 存储分配失败 */
(*L).length = 0; /* 空表长度为0 */
(*L).listsize = LIST_INIT_SIZE; /* 初始存储容量 */
return OK;
}
Status DestroyList(SqList *L)
{ /* 初始条件:顺序线性表L已存在。操作结果:销毁顺序线性表L */
free((*L).elem);
(*L).elem = NULL;
(*L).length = 0;
(*L).listsize = 0;
return OK;
}
Status ClearList(SqList *L)
{ /* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
(*L).length = 0;
return OK;
}
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)
exit(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 (i<L.length&&*p != cur_e)
{
i++;
p++;
}
if (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 + LISTINCREMENT)*sizeof(ElemType));
if (!newbase)
exit(OVERFLOW); /* 存储分配失败 */
(*L).elem = newbase; /* 新基址 */
(*L).listsize += LISTINCREMENT; /* 增加存储容量 */
}
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;
}
Status ListTraverse(SqList L, void(*vi)(ElemType*))
{ /* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素调用函数vi()。一旦vi()失败,则操作失败 */
/* vi()的形参加'&',表明可通过调用vi()改变元素的值 */
ElemType *p;
int i;
p = L.elem;
for (i = 1; i <= L.length; i++)
vi(p++);
printf("\n");
return OK;
}
void InsertAscend(SqList *L, ElemType e)
{ /* 初始条件:按非降序排列的顺序线性表L已存在 */
/* 操作结果:在L中按非降序插入新的数据元素e,L的长度加1 */
ElemType *newbase, *p;
int k;
if ((*L).length >= (*L).listsize) /* 当前存储空间已满,增加分配 */
{
newbase = (ElemType *)realloc((*L).elem, ((*L).listsize + LISTINCREMENT)*sizeof(ElemType));
if (!newbase)
exit(OVERFLOW); /* 存储分配失败 */
(*L).elem = newbase; /* 新基址 */
(*L).listsize += LISTINCREMENT; /* 增加存储容量 */
}
p = (*L).elem;
for (k = 1; k <= (*L).length; k++)
if (e>*p)
p++;
else
break;
ListInsert(L, k, e); /* 函数在bo2-1.c中 */
}
void InsertDescend(SqList *L, ElemType e)
{ /* 初始条件:按非升序排列的顺序线性表L已存在 */
/* 操作结果:在L中按非升序插入新的数据元素e,L的长度加1 */
ElemType *newbase, *p;
int k;
if ((*L).length >= (*L).listsize) /* 当前存储空间已满,增加分配 */
{
newbase = (ElemType *)realloc((*L).elem, ((*L).listsize + LISTINCREMENT)*sizeof(ElemType));
if (!newbase)
exit(OVERFLOW); /* 存储分配失败 */
(*L).elem = newbase; /* 新基址 */
(*L).listsize += LISTINCREMENT; /* 增加存储容量 */
}
p = (*L).elem;
for (k = 1; k <= (*L).length; k++)
if (e<*p)
p++;
else
break;
ListInsert(L, k, e); /* 函数在bo2-1.c中 */
}
Status HeadInsert(SqList *L, ElemType e)
{ /* 初始条件:顺序线性表L已存在。操作结果:在L的头部插入新的数据元素e,L的长度加1 */
ElemType *p, *q, *newbase;
if ((*L).length >= (*L).listsize)
{
newbase = (ElemType *)realloc((*L).elem, ((*L).listsize + LISTINCREMENT)*sizeof(ElemType));
if (!newbase)
exit(OVERFLOW);
(*L).elem = newbase;
(*L).listsize += LISTINCREMENT;
}
q = (*L).elem;
for (p = (*L).elem + (*L).length - 1; p >= q; --p)
*(p + 1) = *p;
*q = e;
(*L).length++;
return OK;
}
Status EndInsert(SqList *L, ElemType e)
{ /* 初始条件:顺序线性表L已存在。操作结果:在L的尾部插入新的数据元素e,L的长度加1 */
ElemType *q, *newbase;
if ((*L).length >= (*L).listsize) /* 当前存储空间已满,增加分配 */
{
newbase = (ElemType *)realloc((*L).elem, ((*L).listsize + LISTINCREMENT)*sizeof(ElemType));
if (!newbase)
exit(OVERFLOW); /* 存储分配失败 */
(*L).elem = newbase; /* 新基址 */
(*L).listsize += LISTINCREMENT; /* 增加存储容量 */
}
q = (*L).elem + (*L).length; /* q为插入位置 */
*q = e;
(*L).length++;
return OK;
}
Status DeleteFirst(SqList *L, ElemType *e)
{ /* 初始条件:顺序线性表L已存在,且有不少于1个元素 */
/* 操作结果:删除L的第一个数据元素,并由e返回其值,L的长度减1 */
ElemType *p, *q;
if (ListEmpty(*L)) /* 空表无法删除 */
return ERROR;
p = (*L).elem; /* p指向第一个元素 */
*e = *p;
q = (*L).elem + (*L).length - 1; /* q指向最后一个元素 */
for (++p; p <= q; ++p)
*(p - 1) = *p; /* 从第2个元素起,所有元素向前移动一个位置 */
(*L).length--; /* 当前长度减1 */
return OK;
}
Status DeleteTail(SqList *L, ElemType *e)
{ /* 初始条件:顺序线性表L已存在,且有不少于1个元素 */
/* 操作结果:删除L的最后一个数据元素,并用e返回其值,L的长度减1 */
ElemType *p;
if (!(*L).length) /* 空表 */
return ERROR;
p = (*L).elem + (*L).length - 1; /* 最后一个数据元素的位置 */
*e = *p; /* 被删除元素的值赋给e */
(*L).length--; /* 表长减1 */
return OK;
}
Status DeleteElem(SqList *L, ElemType e)
{ /* 删除表中值为e的元素,并返回TRUE;如无此元素,则返回FALSE */
int i = 0, j;
while (i<(*L).length&&e != *((*L).elem + i))
i++;
if (i == (*L).length) /* 没找到 */
return FALSE;
else
{
for (j = i; j<(*L).length; j++)
*((*L).elem + j) = *((*L).elem + j + 1); /* 后面的元素依次前移 */
(*L).length--; /* 当前长度减1 */
return TRUE;
}
}
Status ReplaceElem(SqList L, int i, ElemType e)
{ /* 用e取代表L中第i个元素的值 */
if (i<1 || i>L.length) /* i值不合法 */
exit(ERROR);
*(L.elem + i - 1) = e;
return OK;
}
Status CreatAscend(SqList *L, int n)
{ /* 按非降序建立n个元素的线性表 */
int i, j;
ElemType e;
InitList(L);
printf("请输入%d个元素:\n", n);
scanf("%d", &e);
ListInsert(L, 1, e); /* 在空表中插入第1个元素 */
for (i = 1; i<n; i++)
{
scanf("%d", &e);
for (j = 0; j<(*L).length; j++)
if (e <= *((*L).elem + j))
break;
ListInsert(L, j + 1, e); /* 插于表中 */
}
return TRUE;
}
Status CreatDescend(SqList *L, int n)
{ /* 按非升序建立n个元素的线性表 */
int i, j;
ElemType e;
InitList(L);
printf("请输入%d个元素:\n", n);
scanf("%d", &e);
ListInsert(L, 1, e); /* 在空表中插入第1个元素 */
for (i = 1; i<n; i++)
{
scanf("%d", &e);
for (j = 0; j<(*L).length; j++)
if (e >= *((*L).elem + j))
break;
ListInsert(L, j + 1, e); /* 插于表中 */
}
return TRUE;
}
测试文件一
#include "arrList.h"
Status comp(ElemType c1, ElemType c2) /* 数据元素判定函数(平方关系) */
{
if (c1 == c2*c2)
return TRUE;
else
return FALSE;
}
void visit(ElemType *c) /* ListTraverse()调用的函数(类型要一致) */
{
printf("%d ", *c);
}
void dbl(ElemType *c) /* ListTraverse()调用的另一函数(元素值加倍) */
{
*c *= 2;
}
void main()
{
SqList L;
ElemType e, e0;
Status i;
int j, k;
i = InitList(&L);
printf("初始化L后:L.elem=%u L.length=%d L.listsize=%d\n", L.elem, L.length, L.listsize);
for (j = 1; j <= 5; j++)
i = ListInsert(&L, 1, j);
printf("在L的表头依次插入1~5后:*L.elem=");
for (j = 1; j <= 5; j++)
printf("%d ", *(L.elem + j - 1));
printf("\n");
printf("L.elem=%u L.length=%d L.listsize=%d\n", L.elem, L.length, L.listsize);
i = ListEmpty(L);
printf("L是否空:i=%d(1:是 0:否)\n", i);
i = ClearList(&L);
printf("清空L后:L.elem=%u L.length=%d L.listsize=%d\n", L.elem, L.length, L.listsize);
i = ListEmpty(L);
printf("L是否空:i=%d(1:是 0:否)\n", i);
for (j = 1; j <= 10; j++)
ListInsert(&L, j, j);
printf("在L的表尾依次插入1~10后:*L.elem=");
for (j = 1; j <= 10; j++)
printf("%d ", *(L.elem + j - 1));
printf("\n");
printf("L.elem=%u L.length=%d L.listsize=%d\n", L.elem, L.length, L.listsize);
ListInsert(&L, 1, 0);
printf("在L的表头插入0后:*L.elem=");
for (j = 1; j <= ListLength(L); j++) /* ListLength(L)为元素个数 */
printf("%d ", *(L.elem + j - 1));
printf("\n");
printf("L.elem=%u(有可能改变) L.length=%d(改变) L.listsize=%d(改变)\n", L.elem, L.length, L.listsize);
GetElem(L, 5, &e);
printf("第5个元素的值为:%d\n", e);
for (j = 3; j <= 4; j++)
{
k = LocateElem(L, j, comp);
if (k)
printf("第%d个元素的值为%d的平方\n", k, j);
else
printf("没有值为%d的平方的元素\n", j);
}
for (j = 1; j <= 2; j++) /* 测试头两个数据 */
{
GetElem(L, j, &e0); /* 把第j个数据赋给e0 */
i = PriorElem(L, e0, &e); /* 求e0的前驱 */
if (i == INFEASIBLE)
printf("元素%d无前驱\n", e0);
else
printf("元素%d的前驱为:%d\n", e0, e);
}
for (j = ListLength(L) - 1; j <= ListLength(L); j++) /* 最后两个数据 */
{
GetElem(L, j, &e0); /* 把第j个数据赋给e0 */
i = NextElem(L, e0, &e); /* 求e0的后继 */
if (i == INFEASIBLE)
printf("元素%d无后继\n", e0);
else
printf("元素%d的后继为:%d\n", e0, e);
}
k = ListLength(L); /* k为表长 */
for (j = k + 1; j >= k; j--)
{
i = ListDelete(&L, j, &e); /* 删除第j个数据 */
if (i == ERROR)
printf("删除第%d个数据失败\n", j);
else
printf("删除的元素值为:%d\n", e);
}
printf("依次输出L的元素:");
ListTraverse(L, visit); /* 依次对元素调用visit(),输出元素的值 */
printf("L的元素值加倍后:");
ListTraverse(L, dbl); /* 依次对元素调用dbl(),元素值乘2 */
ListTraverse(L, visit);
DestroyList(&L);
printf("销毁L后:L.elem=%u L.length=%d L.listsize=%d\n", L.elem, L.length, L.listsize);
}
测试文件二
#include "arrList.h"
void visit(ElemType *c) /* ListTraverse()调用的函数(类型要一致) */
{
printf("%d ", *c);
}
void main()
{
SqList L;
ElemType d, e;
Status i;
int n;
printf("按非降序建立n个元素的线性表L,请输入元素个数n: ");
scanf("%d", &n);
CreatAscend(&L, n);
printf("依次输出L的元素:");
ListTraverse(L, visit);
InsertAscend(&L, 10); /* 按非降序插入元素10 */
printf("按非降序插入元素10后,线性表L为:");
ListTraverse(L, visit);
HeadInsert(&L, 12); /* 在L的头部插入12 */
EndInsert(&L, 9); /* 在L的尾部插入9 */
printf("在L的头部插入12,尾部插入9后,线性表L为:");
ListTraverse(L, visit);
printf("请输入要删除的元素的值: ");
scanf("%d", &e);
i = DeleteElem(&L, e);
if (i)
printf("成功删除%d\n", e);
else
printf("不存在元素%d!\n", e);
printf("线性表L为:");
ListTraverse(L, visit);
printf("请输入要取代的元素的序号 元素的新值: ");
scanf("%d%d", &n, &e);
ReplaceElem(L, n, e);
printf("线性表L为:");
ListTraverse(L, visit);
DestroyList(&L);
printf("销毁L后,按非升序重新建立n个元素的线性表L,请输入元素个数n(>2): ");
scanf("%d", &n);
CreatDescend(&L, n);
printf("依次输出L的元素:");
ListTraverse(L, visit);
InsertDescend(&L, 10); /* 按非升序插入元素10 */
printf("按非升序插入元素10后,线性表L为:");
ListTraverse(L, visit);
printf("请输入要删除的元素的值: ");
scanf("%d", &e);
i = DeleteElem(&L, e);
if (i)
printf("成功删除%d\n", e);
else
printf("不存在元素%d!\n", e);
printf("线性表L为:");
ListTraverse(L, visit);
DeleteFirst(&L, &e);
DeleteTail(&L, &d);
printf("删除表头元素%d和表尾元素%d后,线性表L为:\n", e, d);
ListTraverse(L, visit);
}
测试文件三
#include "arrList.h"
Status equal(ElemType c1, ElemType c2)
{ /* 判断是否相等的函数,Union()用到 */
if (c1 == c2)
return TRUE;
else
return FALSE;
}
void Union(SqList *La, SqList Lb) /* 算法2.1 */
{ /* 将所有在线性表Lb中但不在La中的数据元素插入到La中 */
ElemType e;
int La_len, Lb_len;
int i;
La_len = ListLength(*La); /* 求线性表的长度 */
Lb_len = ListLength(Lb);
for (i = 1; i <= Lb_len; i++)
{
GetElem(Lb, i, &e); /* 取Lb中第i个数据元素赋给e */
if (!LocateElem(*La, e, equal)) /* La中不存在和e相同的元素,则插入之 */
ListInsert(La, ++La_len, e);
}
}
void print(ElemType *c)
{
printf("%d ", *c);
}
void main()
{
SqList La, Lb;
Status i;
int j;
i = InitList(&La);
if (i == 1) /* 创建空表La成功 */
for (j = 1; j <= 5; j++) /* 在表La中插入5个元素 */
i = ListInsert(&La, j, j);
printf("La= "); /* 输出表La的内容 */
ListTraverse(La, print);
InitList(&Lb); /* 也可不判断是否创建成功 */
for (j = 1; j <= 5; j++) /* 在表Lb中插入5个元素 */
i = ListInsert(&Lb, j, 2 * j);
printf("Lb= "); /* 输出表Lb的内容 */
ListTraverse(Lb, print);
Union(&La, Lb);
printf("new La= "); /* 输出新表La的内容 */
ListTraverse(La, print);
}
测试文件四
#include "arrList.h"
void MergeList(SqList La, SqList Lb, SqList *Lc) /* 算法2.2 */
{ /* 已知线性表La和Lb中的数据元素按值非递减排列。 */
/* 归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排列 */
int i = 1, j = 1, k = 0;
int La_len, Lb_len;
ElemType ai, bj;
InitList(Lc); /* 创建空表Lc */
La_len = ListLength(La);
Lb_len = ListLength(Lb);
while (i <= La_len&&j <= Lb_len) /* 表La和表Lb均非空 */
{
GetElem(La, i, &ai);
GetElem(Lb, j, &bj);
if (ai <= bj)
{
ListInsert(Lc, ++k, ai);
++i;
}
else
{
ListInsert(Lc, ++k, bj);
++j;
}
}
while (i <= La_len) /* 表La非空且表Lb空 */
{
GetElem(La, i++, &ai);
ListInsert(Lc, ++k, ai);
}
while (j <= Lb_len) /* 表Lb非空且表La空 */
{
GetElem(Lb, j++, &bj);
ListInsert(Lc, ++k, bj);
}
}
void print(ElemType *c)
{
printf("%d ", *c);
}
void main()
{
SqList La, Lb, Lc;
int j, a[4] = { 3, 5, 8, 11 }, b[7] = { 2, 6, 8, 9, 11, 15, 20 };
InitList(&La); /* 创建空表La */
for (j = 1; j <= 4; j++) /* 在表La中插入4个元素 */
ListInsert(&La, j, a[j - 1]);
printf("La= "); /* 输出表La的内容 */
ListTraverse(La, print);
InitList(&Lb); /* 创建空表Lb */
for (j = 1; j <= 7; j++) /* 在表Lb中插入7个元素 */
ListInsert(&Lb, j, b[j - 1]);
printf("Lb= "); /* 输出表Lb的内容 */
ListTraverse(Lb, print);
MergeList(La, Lb, &Lc);
printf("Lc= "); /* 输出表Lc的内容 */
ListTraverse(Lc, print);
}
测试文件五
#include "arrList.h"
void MergeList(SqList La, SqList Lb, SqList *Lc) /* 算法2.7 */
{ /* 已知顺序线性表La和Lb的元素按值非递减排列。 */
/* 归并La和Lb得到新的顺序线性表Lc,Lc的元素也按值非递减排列 */
ElemType *pa, *pa_last, *pb, *pb_last, *pc;
pa = La.elem;
pb = Lb.elem;
(*Lc).listsize = (*Lc).length = La.length + Lb.length;/*不用InitList()创建空表Lc */
pc = (*Lc).elem = (ElemType *)malloc((*Lc).listsize*sizeof(ElemType));
if (!(*Lc).elem) /* 存储分配失败 */
exit(OVERFLOW);
pa_last = La.elem + La.length - 1;
pb_last = Lb.elem + Lb.length - 1;
while (pa <= pa_last&&pb <= pb_last) /* 表La和表Lb均非空 */
{ /* 归并 */
if (*pa <= *pb)
*pc++ = *pa++;
else
*pc++ = *pb++;
}
while (pa <= pa_last) /* 表La非空且表Lb空 */
*pc++ = *pa++; /* 插入La的剩余元素 */
while (pb <= pb_last) /* 表Lb非空且表La空 */
*pc++ = *pb++; /* 插入Lb的剩余元素 */
}
void print(ElemType *c)
{
printf("%d ", *c);
}
void main()
{
SqList La, Lb, Lc;
int j;
InitList(&La); /* 创建空表La */
for (j = 1; j <= 5; j++) /* 在表La中插入5个元素 */
ListInsert(&La, j, j);
printf("La= "); /* 输出表La的内容 */
ListTraverse(La, print);
InitList(&Lb); /* 创建空表Lb */
for (j = 1; j <= 5; j++) /* 在表Lb中插入5个元素 */
ListInsert(&Lb, j, 2 * j);
printf("Lb= "); /* 输出表Lb的内容 */
ListTraverse(Lb, print);
MergeList(La, Lb, &Lc);
printf("Lc= "); /* 输出表Lc的内容 */
ListTraverse(Lc, print);
}
测试文件六
#include "arrList.h"
int comp(ElemType c1, ElemType c2)
{
int i;
if (c1<c2)
i = 1;
else if (c1 == c2)
i = 0;
else
i = -1;
return i;
}
void MergeList(SqList La, SqList Lb, SqList *Lc)
{ /* 另一种合并线性表的方法(根据算法2.7下的要求修改算法2.7) */
ElemType *pa, *pa_last, *pb, *pb_last, *pc;
pa = La.elem;
pb = Lb.elem;
(*Lc).listsize = La.length + Lb.length; /* 此句与算法2.7不同 */
pc = (*Lc).elem = (ElemType *)malloc((*Lc).listsize*sizeof(ElemType));
if (!(*Lc).elem)
exit(OVERFLOW);
pa_last = La.elem + La.length - 1;
pb_last = Lb.elem + Lb.length - 1;
while (pa <= pa_last&&pb <= pb_last) /* 表La和表Lb均非空 */
switch (comp(*pa, *pb)) /* 此句与算法2.7不同 */
{
case 0: pb++;
case 1: *pc++ = *pa++;
break;
case -1: *pc++ = *pb++;
}
while (pa <= pa_last) /* 表La非空且表Lb空 */
*pc++ = *pa++;
while (pb <= pb_last) /* 表Lb非空且表La空 */
*pc++ = *pb++;
(*Lc).length = pc - (*Lc).elem; /* 加此句 */
}
void print(ElemType *c)
{
printf("%d ", *c);
}
void main()
{
SqList La, Lb, Lc;
int j;
InitList(&La); /* 创建空表La */
for (j = 1; j <= 5; j++) /* 在表La中插入5个元素 */
ListInsert(&La, j, j);
printf("La= "); /* 输出表La的内容 */
ListTraverse(La, print);
InitList(&Lb); /* 创建空表Lb */
for (j = 1; j <= 5; j++) /* 在表Lb中插入5个元素 */
ListInsert(&Lb, j, 2 * j);
printf("Lb= "); /* 输出表Lb的内容 */
ListTraverse(Lb, print);
MergeList(La, Lb, &Lc);
printf("Lc= "); /* 输出表Lc的内容 */
ListTraverse(Lc, print);
}
2.单链表
头文件
#include <stdio.h>
#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;
struct LNode
{
ElemType data;
struct LNode *next;
};
typedef struct LNode *LinkList; /* 另一种定义LinkList的方法 */
Status InitList(LinkList *L);
Status DestroyList(LinkList *L);
Status ClearList(LinkList L);
Status ListEmpty(LinkList L);
int ListLength(LinkList L);
Status GetElem(LinkList L, int i, ElemType *e);
int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));
Status PriorElem(LinkList L, ElemType cur_e, ElemType *pre_e);
Status NextElem(LinkList L, ElemType cur_e, ElemType *next_e);
Status ListInsert(LinkList L, int i, ElemType e);
Status ListDelete(LinkList L, int i, ElemType *e);
Status ListTraverse(LinkList L, void(*vi)(ElemType));
void InsertAscend(LinkList L, ElemType e);
void InsertDescend(LinkList L, ElemType e);
Status HeadInsert(LinkList L, ElemType e);
Status EndInsert(LinkList L, ElemType e);
Status DeleteFirst(LinkList L, ElemType *e);
Status DeleteTail(LinkList L, ElemType *e);
Status DeleteElem(LinkList L, ElemType e);
Status ReplaceElem(LinkList L, int i, ElemType e);
Status CreatAscend(LinkList *L, int n);
Status CreatDescend(LinkList *L, int n);
Status GetFirstElem(LinkList L, ElemType *e);
实现文件
#include "list.h"
Status InitList(LinkList *L)
{ /* 操作结果:构造一个空的线性表L */
*L=(LinkList)malloc(sizeof(struct LNode)); /* 产生头结点,并使L指向此头结点 */
if(!*L) /* 存储分配失败 */
exit(OVERFLOW);
(*L)->next=NULL; /* 指针域为空 */
return OK;
}
Status DestroyList(LinkList *L)
{ /* 初始条件:线性表L已存在。操作结果:销毁线性表L */
LinkList q;
while(*L)
{
q=(*L)->next;
free(*L);
*L=q;
}
return OK;
}
Status ClearList(LinkList L) /* 不改变L */
{ /* 初始条件:线性表L已存在。操作结果:将L重置为空表 */
LinkList p,q;
p=L->next; /* p指向第一个结点 */
while(p) /* 没到表尾 */
{
q=p->next;
free(p);
p=q;
}
L->next=NULL; /* 头结点指针域为空 */
return OK;
}
Status ListEmpty(LinkList L)
{ /* 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
if(L->next) /* 非空 */
return FALSE;
else
return TRUE;
}
int ListLength(LinkList L)
{ /* 初始条件:线性表L已存在。操作结果:返回L中数据元素个数 */
int i=0;
LinkList p=L->next; /* p指向第一个结点 */
while(p) /* 没到表尾 */
{
i++;
p=p->next;
}
return i;
}
Status GetElem(LinkList L,int i,ElemType *e) /* 算法2.8 */
{ /* L为带头结点的单链表的头指针。当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */
int j=1; /* j为计数器 */
LinkList p=L->next; /* p指向第一个结点 */
while(p&&j<i) /* 顺指针向后查找,直到p指向第i个元素或p为空 */
{
p=p->next;
j++;
}
if(!p||j>i) /* 第i个元素不存在 */
return ERROR;
*e=p->data; /* 取第i个元素 */
return OK;
}
int LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType))
{ /* 初始条件: 线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0) */
/* 操作结果: 返回L中第1个与e满足关系compare()的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int i=0;
LinkList p=L->next;
while(p)
{
i++;
if(compare(p->data,e)) /* 找到这样的数据元素 */
return i;
p=p->next;
}
return 0;
}
Status PriorElem(LinkList L,ElemType cur_e,ElemType *pre_e)
{ /* 初始条件: 线性表L已存在 */
/* 操作结果: 若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, */
/* 返回OK;否则操作失败,pre_e无定义,返回INFEASIBLE */
LinkList q,p=L->next; /* p指向第一个结点 */
while(p->next) /* p所指结点有后继 */
{
q=p->next; /* q为p的后继 */
if(q->data==cur_e)
{
*pre_e=p->data;
return OK;
}
p=q; /* p向后移 */
}
return INFEASIBLE;
}
Status NextElem(LinkList L,ElemType cur_e,ElemType *next_e)
{ /* 初始条件:线性表L已存在 */
/* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, */
/* 返回OK;否则操作失败,next_e无定义,返回INFEASIBLE */
LinkList p=L->next; /* p指向第一个结点 */
while(p->next) /* p所指结点有后继 */
{
if(p->data==cur_e)
{
*next_e=p->next->data;
return OK;
}
p=p->next;
}
return INFEASIBLE;
}
Status ListInsert(LinkList L,int i,ElemType e) /* 算法2.9。不改变L */
{ /* 在带头结点的单链线性表L中第i个位置之前插入元素e */
int j=0;
LinkList p=L,s;
while(p&&j<i-1) /* 寻找第i-1个结点 */
{
p=p->next;
j++;
}
if(!p||j>i-1) /* i小于1或者大于表长 */
return ERROR;
s=(LinkList)malloc(sizeof(struct LNode)); /* 生成新结点 */
s->data=e; /* 插入L中 */
s->next=p->next;
p->next=s;
return OK;
}
Status ListDelete(LinkList L,int i,ElemType *e) /* 算法2.10。不改变L */
{ /* 在带头结点的单链线性表L中,删除第i个元素,并由e返回其值 */
int j=0;
LinkList p=L,q;
while(p->next&&j<i-1) /* 寻找第i个结点,并令p指向其前趋 */
{
p=p->next;
j++;
}
if(!p->next||j>i-1) /* 删除位置不合理 */
return ERROR;
q=p->next; /* 删除并释放结点 */
p->next=q->next;
*e=q->data;
free(q);
return OK;
}
Status ListTraverse(LinkList L,void(*vi)(ElemType))
/* vi的形参类型为ElemType,与bo2-1.c中相应函数的形参类型ElemType&不同 */
{ /* 初始条件:线性表L已存在 */
/* 操作结果:依次对L的每个数据元素调用函数vi()。一旦vi()失败,则操作失败 */
LinkList p=L->next;
while(p)
{
vi(p->data);
p=p->next;
}
printf("\n");
return OK;
}
/* bo2-9.c 单链表线性表(存储结构由c2-2.h定义)的扩展操作(11个) */
void InsertAscend(LinkList L, ElemType e)
{ /* 初始条件:按非降序排列的线性表L已存在。操作结果:在L中按非降序插入新的数据元素e */
LinkList q = L, p = L->next;
while (p&&e>p->data)
{
q = p;
p = p->next;
}
q->next = (LinkList)malloc(sizeof(struct LNode)); /* 插在q后 */
q->next->data = e;
q->next->next = p;
}
void InsertDescend(LinkList L, ElemType e)
{ /* 初始条件:按非升序排列的线性表L已存在。操作结果:在L中按非升序插入新的数据元素e */
LinkList q = L, p = L->next;
while (p&&e<p->data)
{
q = p;
p = p->next;
}
q->next = (LinkList)malloc(sizeof(struct LNode)); /* 插在q后 */
q->next->data = e;
q->next->next = p;
}
Status HeadInsert(LinkList L, ElemType e)
{ /* 初始条件:线性表L已存在。操作结果:在L的头部插入新的数据元素e,作为链表的第一个元素 */
LinkList s;
s = (LinkList)malloc(sizeof(struct LNode)); /* 生成新结点 */
s->data = e; /* 给结点赋值 */
s->next = L->next; /* 插在表头 */
L->next = s;
return OK;
}
Status EndInsert(LinkList L, ElemType e)
{ /* 初始条件:线性表L已存在。操作结果:在L的尾部插入新的数据元素e,作为链表的最后一个元素 */
LinkList p = L;
while (p->next) /* 使p指向表尾元素 */
p = p->next;
p->next = (LinkList)malloc(sizeof(struct LNode)); /* 在表尾生成新结点 */
p->next->data = e; /* 给新结点赋值 */
p->next->next = NULL; /* 表尾 */
return OK;
}
Status DeleteFirst(LinkList L, ElemType *e)
{ /* 初始条件:线性表L已存在,且有不少于1个元素 */
/* 操作结果:删除L的第一个数据元素,并由e返回其值 */
LinkList p = L->next;
if (p)
{
*e = p->data;
L->next = p->next;
free(p);
return OK;
}
else
return ERROR;
}
Status DeleteTail(LinkList L, ElemType *e)
{ /* 初始条件:线性表L已存在,且有不少于1个元素 */
/* 操作结果:删除L的最后一个数据元素,并用e返回其值 */
LinkList p = L, q = NULL;
if (!p->next) /* 链表为空 */
return ERROR;
while (p->next)
{
q = p;
p = p->next;
}
q->next = NULL; /* 新尾结点的next域设为NULL */
*e = p->data;
free(p);
return OK;
}
Status DeleteElem(LinkList L, ElemType e)
{ /* 删除表中值为e的元素,并返回TRUE;如无此元素,则返回FALSE */
LinkList p = L, q;
while (p)
{
q = p->next;
if (q&&q->data == e)
{
p->next = q->next;
free(q);
return TRUE;
}
p = q;
}
return FALSE;
}
Status ReplaceElem(LinkList L, int i, ElemType e)
{ /* 用e取代表L中第i个元素的值 */
LinkList p = L;
int j = 0;
while (p->next&&j<i)
{
j++;
p = p->next;
}
if (j == i)
{
p->data = e;
return OK;
}
else /* 表中不存在第i个元素 */
return ERROR;
}
Status CreatAscend(LinkList *L, int n)
{ /* 按非降序建立n个元素的线性表 */
int j;
LinkList p, q, s;
if (n <= 0)
return ERROR;
InitList(L);
printf("请输入%d个元素:\n", n);
s = (LinkList)malloc(sizeof(struct LNode)); /* 第一个结点 */
scanf("%d", &s->data);
s->next = NULL;
(*L)->next = s;
for (j = 1; j<n; j++)
{
s = (LinkList)malloc(sizeof(struct LNode)); /* 其余结点 */
scanf("%d", &s->data);
q = *L;
p = (*L)->next;
while (p&&p->data<s->data) /* p没到表尾,且所指元素值小于新值 */
{
q = p;
p = p->next; /* 指针后移 */
}
s->next = q->next; /* 元素插在q的后面 */
q->next = s;
}
return OK;
}
Status CreatDescend(LinkList *L, int n)
{ /* 按非升序建立n个元素的线性表 */
int j;
LinkList p, q, s;
if (n <= 0)
return ERROR;
InitList(L);
printf("请输入%d个元素:\n", n);
s = (LinkList)malloc(sizeof(struct LNode)); /* 第一个结点 */
scanf("%d", &s->data);
s->next = NULL;
(*L)->next = s;
for (j = 1; j<n; j++)
{
s = (LinkList)malloc(sizeof(struct LNode)); /* 其余结点 */
scanf("%d", &s->data);
q = *L;
p = (*L)->next;
while (p&&p->data>s->data) /* p没到表尾,且所指元素值大于新值 */
{
q = p;
p = p->next; /* 指针后移 */
}
s->next = q->next; /* 元素插在q的后面 */
q->next = s;
}
return OK;
}
Status GetFirstElem(LinkList L, ElemType *e)
{ /* 返回表头元素的值 */
LinkList p = L->next;
if (!p) /* 空表 */
return ERROR;
else /* 非空表 */
*e = p->data;
return OK;
}
测试文件一
#include"list.h" /* 与main2-1.c不同 */
Status comp(ElemType c1,ElemType c2)
{ /* 数据元素判定函数(相等为TRUE,否则为FALSE) */
if(c1==c2)
return TRUE;
else
return FALSE;
}
void visit(ElemType c) /* 与main2-1.c不同 */
{
printf("%d ",c);
}
void main() /* 除了几个输出语句外,主程和main2-1.c很像 */
{
LinkList L; /* 与main2-1.c不同 */
ElemType e,e0;
Status i;
int j,k;
i=InitList(&L);
for(j=1;j<=5;j++)
i=ListInsert(L,1,j);
printf("在L的表头依次插入1~5后:L=");
ListTraverse(L,visit); /* 依次对元素调用visit(),输出元素的值 */
i=ListEmpty(L);
printf("L是否空:i=%d(1:是 0:否)\n",i);
i=ClearList(L);
printf("清空L后:L=");
ListTraverse(L,visit);
i=ListEmpty(L);
printf("L是否空:i=%d(1:是 0:否)\n",i);
for(j=1;j<=10;j++)
ListInsert(L,j,j);
printf("在L的表尾依次插入1~10后:L=");
ListTraverse(L,visit);
GetElem(L,5,&e);
printf("第5个元素的值为:%d\n",e);
for(j=0;j<=1;j++)
{
k=LocateElem(L,j,comp);
if(k)
printf("第%d个元素的值为%d\n",k,j);
else
printf("没有值为%d的元素\n",j);
}
for(j=1;j<=2;j++) /* 测试头两个数据 */
{
GetElem(L,j,&e0); /* 把第j个数据赋给e0 */
i=PriorElem(L,e0,&e); /* 求e0的前驱 */
if(i==INFEASIBLE)
printf("元素%d无前驱\n",e0);
else
printf("元素%d的前驱为:%d\n",e0,e);
}
for(j=ListLength(L)-1;j<=ListLength(L);j++)/*最后两个数据 */
{
GetElem(L,j,&e0); /* 把第j个数据赋给e0 */
i=NextElem(L,e0,&e); /* 求e0的后继 */
if(i==INFEASIBLE)
printf("元素%d无后继\n",e0);
else
printf("元素%d的后继为:%d\n",e0,e);
}
k=ListLength(L); /* k为表长 */
for(j=k+1;j>=k;j--)
{
i=ListDelete(L,j,&e); /* 删除第j个数据 */
if(i==ERROR)
printf("删除第%d个数据失败\n",j);
else
printf("删除的元素为:%d\n",e);
}
printf("依次输出L的元素:");
ListTraverse(L,visit);
DestroyList(&L);
printf("销毁L后:L=%u\n",L);
}
测试文件二
#include "list.h"
void visit(ElemType c) /* ListTraverse()调用的函数(类型要一致) */
{
printf("%d ", c);
}
void main()
{
LinkList L; /* 此句和main2-8.c不同 */
ElemType d, e;
Status i;
int n;
printf("按非降序建立n个元素的线性表L,请输入元素个数n: ");
scanf("%d", &n);
CreatAscend(&L, n);
printf("依次输出L的元素:");
ListTraverse(L, visit);
InsertAscend(L, 10); /* 按非降序插入元素10 */
printf("按非降序插入元素10后,线性表L为:");
ListTraverse(L, visit);
HeadInsert(L, 12); /* 在L的头部插入12 */
EndInsert(L, 9); /* 在L的尾部插入9 */
printf("在L的头部插入12,尾部插入9后,线性表L为:");
ListTraverse(L, visit);
i = GetFirstElem(L, &e); /* 此句加 */
printf("第1个元素是: %d\n", e); /* 此句加 */
printf("请输入要删除的元素的值: ");
scanf("%d", &e);
i = DeleteElem(L, e);
if (i)
printf("成功删除%d!\n", e);
else
printf("不存在元素%d!\n", e);
printf("线性表L为:");
ListTraverse(L, visit);
printf("请输入要取代的元素的序号 元素的新值: ");
scanf("%d%d", &n, &e);
ReplaceElem(L, n, e);
printf("线性表L为:");
ListTraverse(L, visit);
DestroyList(&L);
printf("销毁L后,按非升序重新建立n个元素的线性表L,请输入元素个数n(>2): ");
scanf("%d", &n);
CreatDescend(&L, n);
printf("依次输出L的元素:");
ListTraverse(L, visit);
InsertDescend(L, 10); /* 按非升序插入元素10 */
printf("按非升序插入元素10后,线性表L为:");
ListTraverse(L, visit);
printf("请输入要删除的元素的值: ");
scanf("%d", &e);
i = DeleteElem(L, e);
if (i)
printf("成功删除%d!\n", e);
else
printf("不存在元素%d!\n", e);
printf("线性表L为:");
ListTraverse(L, visit);
DeleteFirst(L, &e);
DeleteTail(L, &d);
printf("删除表头元素%d和表尾元素%d后,线性表L为:", e, d);
ListTraverse(L, visit);
}
测试文件三
#include "list.h"
void CreateList(LinkList *L, int n) /* 算法2.11 */
{ /* 逆位序(插在表头)输入n个元素的值,建立带表头结构的单链线性表L */
int i;
LinkList p;
*L = (LinkList)malloc(sizeof(struct LNode));
(*L)->next = NULL; /* 先建立一个带头结点的单链表 */
printf("请输入%d个数据\n", n);
for (i = n; i>0; --i)
{
p = (LinkList)malloc(sizeof(struct LNode)); /* 生成新结点 */
scanf("%d", &p->data); /* 输入元素值 */
p->next = (*L)->next; /* 插入到表头 */
(*L)->next = p;
}
}
void CreateList2(LinkList *L, int n)
{ /* 正位序(插在表尾)输入n个元素的值,建立带表头结构的单链线性表 */
int i;
LinkList p = NULL, q = NULL;
*L = (LinkList)malloc(sizeof(struct LNode)); /* 生成头结点 */
(*L)->next = NULL;
q = *L;
printf("请输入%d个数据\n", n);
for (i = 1; i <= n; i++)
{
p = (LinkList)malloc(sizeof(struct LNode));
scanf("%d", &p->data);
q->next = p;
q = q->next;
}
p->next = NULL;
}
void MergeList(LinkList La, LinkList *Lb, LinkList *Lc)/* 算法2.12 */
{ /* 已知单链线性表La和Lb的元素按值非递减排列。 */
/* 归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列 */
LinkList pa = La->next, pb = (*Lb)->next, pc;
*Lc = pc = La; /* 用La的头结点作为Lc的头结点 */
while (pa&&pb)
if (pa->data <= pb->data)
{
pc->next = pa;
pc = pa;
pa = pa->next;
}
else
{
pc->next = pb;
pc = pb;
pb = pb->next;
}
pc->next = pa ? pa : pb; /* 插入剩余段 */
free(*Lb); /* 释放Lb的头结点 */
Lb = NULL;
}
void visit(ElemType c) /* ListTraverse()调用的函数(类型要一致) */
{
printf("%d ", c);
}
void main()
{
int n = 5;
LinkList La, Lb, Lc;
printf("按非递减顺序, ");
CreateList2(&La, n); /* 正位序输入n个元素的值 */
printf("La="); /* 输出链表La的内容 */
ListTraverse(La, visit);
printf("按非递增顺序, ");
CreateList(&Lb, n); /* 逆位序输入n个元素的值 */
printf("Lb="); /* 输出链表Lb的内容 */
ListTraverse(Lb, visit);
MergeList(La, &Lb, &Lc); /* 按非递减顺序归并La和Lb,得到新表Lc */
printf("Lc="); /* 输出链表Lc的内容 */
ListTraverse(Lc, visit);
}
测试文件四
#include "list.h"
Status equal(ElemType c1, ElemType c2)
{ /* 判断是否相等的函数,Union()用到 */
if (c1 == c2)
return TRUE;
else
return FALSE;
}
void Union(LinkList La, LinkList Lb) /* 算法2.1,此句与algo2-1.c不同 */
{ /* 将所有在线性表Lb中但不在La中的数据元素插入到La中 */
ElemType e;
int La_len, Lb_len;
int i;
La_len = ListLength(La); /* 求线性表的长度 */
Lb_len = ListLength(Lb);
for (i = 1; i <= Lb_len; i++)
{
GetElem(Lb, i, &e); /* 取Lb中第i个数据元素赋给e */
if (!LocateElem(La, e, equal)) /* La中不存在和e相同的元素,则插入之 */
ListInsert(La, ++La_len, e);
}
}
void print(ElemType c)
{
printf("%d ", c);
}
void main()
{
LinkList La, Lb; /* 此句与algo2-1.c不同(因为采用不同的结构) */
Status i;
int j;
i = InitList(&La);
if (i == 1) /* 创建空表La成功 */
for (j = 1; j <= 5; j++) /* 在表La中插入5个元素 */
i = ListInsert(La, j, j);
printf("La= "); /* 输出表La的内容 */
ListTraverse(La, print);
InitList(&Lb); /* 也可不判断是否创建成功 */
for (j = 1; j <= 5; j++) /* 在表Lb中插入5个元素 */
i = ListInsert(Lb, j, 2 * j);
printf("Lb= "); /* 输出表Lb的内容 */
ListTraverse(Lb, print);
Union(La, Lb);
printf("new La= "); /* 输出新表La的内容 */
ListTraverse(La, print);
}
测试程序五
#include "list.h"
void MergeList(LinkList La, LinkList Lb, LinkList *Lc) /* 算法2.2,此句与algo2-2.c不同 */
{ /* 已知线性表La和Lb中的数据元素按值非递减排列。 */
/* 归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排列 */
int i = 1, j = 1, k = 0;
int La_len, Lb_len;
ElemType ai, bj;
InitList(Lc); /* 创建空表Lc */
La_len = ListLength(La);
Lb_len = ListLength(Lb);
while (i <= La_len&&j <= Lb_len) /* 表La和表Lb均非空 */
{
GetElem(La, i, &ai);
GetElem(Lb, j, &bj);
if (ai <= bj)
{
ListInsert(*Lc, ++k, ai);
++i;
}
else
{
ListInsert(*Lc, ++k, bj);
++j;
}
}
while (i <= La_len) /* 表La非空且表Lb空 */
{
GetElem(La, i++, &ai);
ListInsert(*Lc, ++k, ai);
}
while (j <= Lb_len) /* 表Lb非空且表La空 */
{
GetElem(Lb, j++, &bj);
ListInsert(*Lc, ++k, bj);
}
}
void print(ElemType c)
{
printf("%d ", c);
}
void main()
{
LinkList La, Lb, Lc; /* 此句与algo2-2.c不同 */
int j, a[4] = { 3, 5, 8, 11 }, b[7] = { 2, 6, 8, 9, 11, 15, 20 };
InitList(&La); /* 创建空表La */
for (j = 1; j <= 4; j++) /* 在表La中插入4个元素 */
ListInsert(La, j, a[j - 1]);
printf("La= "); /* 输出表La的内容 */
ListTraverse(La, print);
InitList(&Lb); /* 创建空表Lb */
for (j = 1; j <= 7; j++) /* 在表Lb中插入7个元素 */
ListInsert(Lb, j, b[j - 1]);
printf("Lb= "); /* 输出表Lb的内容 */
ListTraverse(Lb, print);
MergeList(La, Lb, &Lc);
printf("Lc= "); /* 输出表Lc的内容 */
ListTraverse(Lc, print);
}
测试文件六
#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 */
#define NAMELEN 8 /* 姓名最大长度 */
#define CLASSLEN 4 /* 班级名最大长度 */
struct stud /* 记录的结构 */
{
char name[NAMELEN + 1];
long num;
char sex;
int age;
char Class[CLASSLEN + 1];
int health;
};
typedef struct stud ElemType; /* 链表结点元素类型为结构体 */
struct LNode
{
ElemType data;
struct LNode *next;
};
typedef struct LNode *LinkList; /* 另一种定义LinkList的方法 */
char sta[3][9] = { "健康 ", "一般 ", "神经衰弱" }; /* 健康状况(3类) */
FILE *fp;
Status InitList(LinkList *L) /* 拷自bo2-2.c */
{ /* 操作结果:构造一个空的线性表L */
*L = (LinkList)malloc(sizeof(struct LNode)); /* 产生头结点,并使L指向此头结点 */
if (!*L) /* 存储分配失败 */
exit(OVERFLOW);
(*L)->next = NULL; /* 指针域为空 */
return OK;
}
Status ListTraverse(LinkList L, void(*vi)(ElemType)) /* 拷自bo2-2.c */
{ /* 初始条件:线性表L已存在 */
/* 操作结果:依次对L的每个数据元素调用函数vi()。一旦vi()失败,则操作失败 */
LinkList p = L->next;
while (p)
{
vi(p->data);
p = p->next;
}
printf("\n");
return OK;
}
void InsertAscend(LinkList L, ElemType e) /* 此函数是由bo2-9.c中的同名函数改写 */
{ /* 按学号非降序插入 */
LinkList q = L, p = L->next;
while (p&&e.num>p->data.num)
{
q = p;
p = p->next;
}
q->next = (LinkList)malloc(sizeof(struct LNode)); /* 插在q后 */
q->next->data = e;
q->next->next = p;
}
void Print(struct stud e)
{ /* 显示记录e的内容 */
printf("%-8s %6ld", e.name, e.num);
if (e.sex == 'm')
printf(" 男");
else
printf(" 女");
printf("%5d %-4s", e.age, e.Class);
printf("%9s\n", sta[e.health]);
}
void ReadIn(struct stud *e)
{ /* 由键盘输入结点信息 */
printf("请输入姓名(<=%d个字符): ", NAMELEN);
scanf("%s", e->name);
printf("请输入学号: ");
scanf("%ld", &e->num);
printf("请输入性别(m:男 f:女): ");
scanf("%*c%c", &e->sex);
printf("请输入年龄: ");
scanf("%d", &e->age);
printf("请输入班级(<=%d个字符): ", CLASSLEN);
scanf("%s", e->Class);
printf("请输入健康状况(0:%s 1:%s 2:%s):", sta[0], sta[1], sta[2]);
scanf("%d", &e->health);
}
void WriteToFile(struct stud e)
{ /* 将结点信息写入fp指定的文件 */
fwrite(&e, sizeof(struct stud), 1, fp);
}
Status ReadFromFile(struct stud *e)
{ /* 由fp指定的文件读取结点信息到e */
int i;
i = fread(e, sizeof(struct stud), 1, fp);
if (i == 1) /* 读取文件成功 */
return OK;
else
return ERROR;
}
Status FindFromNum(LinkList L, long num, LinkList *p, LinkList *q)
{ /* 查找表中学号为num的结点,如找到,q指向此结点,p指向q的前驱, */
/* 并返回TRUE;如无此元素,则返回FALSE */
*p = L;
while (*p)
{
*q = (*p)->next;
if (*q && (*q)->data.num>num) /* 因为是按学号非降序排列 */
break;
if (*q && (*q)->data.num == num) /* 找到该学号 */
return TRUE;
*p = *q;
}
return FALSE;
}
Status FindFromName(LinkList L, char name[], LinkList *p, LinkList *q)
{ /* 查找表中姓名为name的结点,如找到,q指向此结点,p指向q的前驱, */
/* 并返回TRUE;如无此元素,则返回FALSE */
*p = L;
while (*p)
{
*q = (*p)->next;
if (*q&&!strcmp((*q)->data.name, name)) /* 找到该姓名 */
return TRUE;
*p = *q;
}
return FALSE;
}
Status DeleteElemNum(LinkList L, long num)
{ /* 删除表中学号为num的元素,并返回TRUE;如无此元素,则返回FALSE */
LinkList p, q;
if (FindFromNum(L, num, &p, &q)) /* 找到此结点,且q指向其,p指向其前驱 */
{
p->next = q->next;
free(q);
return TRUE;
}
return FALSE;
}
Status DeleteElemName(LinkList L, char name[])
{ /* 删除表中姓名为name的元素,并返回TRUE;如无此元素,则返回FALSE */
LinkList p, q;
if (FindFromName(L, name, &p, &q)) /* 找到此结点,且q指向其,p指向其前驱 */
{
p->next = q->next;
free(q);
return TRUE;
}
return FALSE;
}
void Modify(ElemType *e)
{ /* 修改结点内容 */
char s[80];
Print(*e); /* 显示原内容 */
printf("请输入待修改项的内容,不修改的项按回车键保持原值:\n");
printf("请输入姓名(<=%d个字符): ", NAMELEN);
gets(s);
if (strlen(s))
strcpy(e->name, s);
printf("请输入学号: ");
gets(s);
if (strlen(s))
e->num = atol(s);
printf("请输入性别(m:男 f:女): ");
gets(s);
if (strlen(s))
e->sex = s[0];
printf("请输入年龄: ");
gets(s);
if (strlen(s))
e->age = atoi(s);
printf("请输入班级(<=%d个字符): ", CLASSLEN);
gets(s);
if (strlen(s))
strcpy(e->Class, s);
printf("请输入健康状况(0:%s 1:%s 2:%s):", sta[0], sta[1], sta[2]);
gets(s);
if (strlen(s))
e->health = atoi(s); /* 修改完毕 */
}
#define N 4 /* student记录的个数 */
void main()
{
struct stud student[N] = { { "王小林", 790631, 'm', 18, "计91", 0 },
{ "陈红", 790632, 'f', 20, "计91", 1 },
{ "刘建平", 790633, 'm', 21, "计91", 0 },
{ "张立立", 790634, 'm', 17, "计91", 2 } }; /* 表的初始记录 */
int i, j, flag = 1;
long num;
char filename[13], name[NAMELEN + 1];
ElemType e;
LinkList T, p, q;
InitList(&T); /* 初始化链表 */
while (flag)
{
printf("1:将结构体数组student中的记录按学号非降序插入链表\n");
printf("2:将文件中的记录按学号非降序插入链表\n");
printf("3:键盘输入新记录,并将其按学号非降序插入链表\n");
printf("4:删除链表中第一个有给定学号的记录\n");
printf("5:删除链表中第一个有给定姓名的记录\n");
printf("6:修改链表中第一个有给定学号的记录\n");
printf("7:修改链表中第一个有给定姓名的记录\n");
printf("8:查找链表中第一个有给定学号的记录\n");
printf("9:查找链表中第一个有给定姓名的记录\n");
printf("10:显示所有记录 11:将链表中的所有记录存入文件 12:结束\n");
printf("请选择操作命令: ");
scanf("%d", &i);
switch (i)
{
case 1: for (j = 0; j<N; j++)
InsertAscend(T, student[j]);
break;
case 2: printf("请输入文件名: ");
scanf("%s", filename);
if ((fp = fopen(filename, "rb")) == NULL)
printf("打开文件失败!\n");
else
{
while (ReadFromFile(&e))
InsertAscend(T, e);
fclose(fp);
}
break;
case 3: ReadIn(&e);
InsertAscend(T, e);
break;
case 4: printf("请输入待删除记录的学号: ");
scanf("%ld", &num);
if (!DeleteElemNum(T, num))
printf("没有学号为%ld的记录\n", num);
break;
case 5: printf("请输入待删除记录的姓名: ");
scanf("%s", name);
if (!DeleteElemName(T, name))
printf("没有姓名为%s的记录\n", name);
break;
case 6: printf("请输入待修改记录的学号: ");
scanf("%ld%*c", &num); /* %*c吃掉回车符 */
if (!FindFromNum(T, num, &p, &q))
printf("没有学号为%ld的记录\n", num);
else
{
Modify(&q->data);
if (q->data.num != num) /* 学号被修改 */
{
p->next = q->next; /* 把q所指的结点从L中删除 */
InsertAscend(T, q->data); /* 把元素插入L */
free(q); /* 删除q */
}
}
break;
case 7: printf("请输入待修改记录的姓名: ");
scanf("%s%*c", name); /* %*c吃掉回车符 */
if (!FindFromName(T, name, &p, &q))
printf("没有姓名为%s的记录\n", name);
else
{
num = q->data.num; /* 学号存入num */
Modify(&q->data);
if (q->data.num != num) /* 学号被修改 */
{
p->next = q->next; /* 把q所指的结点从L中删除 */
InsertAscend(T, q->data); /* 把元素插入L */
free(q); /* 删除q */
}
}
break;
case 8: printf("请输入待查找记录的学号: ");
scanf("%ld", &num);
if (!FindFromNum(T, num, &p, &q))
printf("没有学号为%ld的记录\n", num);
else
Print(q->data);
break;
case 9: printf("请输入待查找记录的姓名: ");
scanf("%s", name);
if (!FindFromName(T, name, &p, &q))
printf("没有姓名为%s的记录\n", name);
else
Print(q->data);
break;
case 10:printf(" 姓名 学号 性别 年龄 班级 健康状况\n");
ListTraverse(T, Print);
break;
case 11:printf("请输入文件名: ");
scanf("%s", filename);
if ((fp = fopen(filename, "wb")) == NULL)
printf("打开文件失败!\n");
else
ListTraverse(T, WriteToFile);
fclose(fp);
break;
case 12:flag = 0;
}
}
}
3.另一种线性表
/* c1.h (程序名) */
#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;
/* c2-6.h 抽象数据类型Polynomial的实现 */
//typedef struct /* 项的表示,多项式的项作为LinkList的数据元素 */
//{
// float coef; /* 系数 */
// int expn; /* 指数 */
//}term, ElemType;
/* 两个类型名:term用于本ADT,ElemType为LinkList的数据对象名 */
/* c2-5.h 带头结点的线性链表类型 */
typedef struct LNode /* 结点类型 */
{
ElemType data;
struct LNode *next;
}LNode, *Link, *Position;
typedef struct LinkList /* 链表类型 */
{
Link head, tail; /* 分别指向线性链表中的头结点和最后一个结点 */
int len; /* 指示线性链表中数据元素的个数 */
}LinkList;
Status MakeNode(Link *p, ElemType e);
void FreeNode(Link *p);
Status InitList(LinkList *L);
Status ClearList(LinkList *L);
Status DestroyList(LinkList *L);
Status InsFirst(LinkList *L, Link h, Link s);
Status DelFirst(LinkList *L, Link h, Link *q);
Status Append(LinkList *L, Link s);
Position PriorPos(LinkList L, Link p);
Status Remove(LinkList *L, Link *q);
Status InsBefore(LinkList *L, Link *p, Link s);
Status InsAfter(LinkList *L, Link *p, Link s);
Status 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));
Status ListTraverse(LinkList L, void(*visit)(ElemType));
Status OrderInsert(LinkList *L, ElemType e, int(*comp)(ElemType, ElemType));
Status LocateElemP(LinkList L, ElemType e, Position *q, int(*compare)(ElemType, ElemType));
实现文件
#include "LinkList2.h"
/* bo2-6.c 具有实用意义的线性链表(存储结构由c2-5.h定义)的24个基本操作 */
Status MakeNode(Link *p, ElemType e)
{ /* 分配由p指向的值为e的结点,并返回OK;若分配失败。则返回ERROR */
*p = (Link)malloc(sizeof(LNode));
if (!*p)
return ERROR;
(*p)->data = e;
return OK;
}
void FreeNode(Link *p)
{ /* 释放p所指结点 */
free(*p);
*p = NULL;
}
Status InitList(LinkList *L)
{ /* 构造一个空的线性链表 */
Link p;
p = (Link)malloc(sizeof(LNode)); /* 生成头结点 */
if (p)
{
p->next = NULL;
(*L).head = (*L).tail = p;
(*L).len = 0;
return OK;
}
else
return ERROR;
}
Status 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;
}
return OK;
}
Status DestroyList(LinkList *L)
{ /* 销毁线性链表L,L不再存在 */
ClearList(L); /* 清空链表 */
FreeNode(&(*L).head);
(*L).tail = NULL;
(*L).len = 0;
return OK;
}
Status 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++;
return OK;
}
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; /* 链表空 */
}
Status 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;
return OK;
}
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;
}
Status 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++;
return OK;
}
Status 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++;
return OK;
}
Status SetCurElem(Link p, ElemType e)
{ /* 已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值 */
p->data = e;
return OK;
}
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;
}
Status ListTraverse(LinkList L, void(*visit)(ElemType))
{ /* 依次对L的每个数据元素调用函数visit()。一旦visit()失败,则操作失败 */
Link p = L.head->next;
int j;
for (j = 1; j <= L.len; j++)
{
visit(p->data);
p = p->next;
}
printf("\n");
return OK;
}
Status 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; /* 修改尾结点 */
return OK;
}
Status LocateElemP(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<e.expn */
if (!p || compare(p->data, e)>0) /* 到表尾或compare(p->data,e)>0 */
{
*q = pp;
return FALSE;
}
else /* 找到 */
{
*q = p;
return TRUE;
}
}
测试文件一
#include "LinkList2.h"
Status compare(ElemType c1, ElemType c2) /* c1等于c2 */
{
if (c1 == c2)
return TRUE;
else
return FALSE;
}
int cmp(ElemType a, ElemType b)
{ /* 根据a<、=或>b,分别返回-1、0或1 */
if (a == b)
return 0;
else
return (a - b) / abs(a - b);
}
void visit(ElemType c)
{
printf("%d ", c);
}
void main()
{
Link p, h;
LinkList L;
Status i;
int j, k;
i = InitList(&L);
if (!i) /* 初始化空的线性表L不成功 */
exit(FALSE); /* 退出程序运行 */
for (j = 1; j <= 2; j++)
{
MakeNode(&p, j); /* 生成由p指向、值为j的结点 */
InsFirst(&L, L.tail, p); /* 插在表尾 */
}
OrderInsert(&L, 0, cmp); /* 按升序插在有序表头 */
for (j = 0; j <= 3; j++)
{
i = LocateElemP(L, j, &p, cmp);
if (i)
printf("链表中有值为%d的元素。\n", p->data);
else
printf("链表中没有值为%d的元素。\n", j);
}
printf("输出链表:");
ListTraverse(L, visit); /* 输出L */
for (j = 1; j <= 4; j++)
{
printf("删除表头结点:");
DelFirst(&L, L.head, &p); /* 删除L的首结点,并以p返回 */
if (p)
printf("%d\n", GetCurElem(p));
else
printf("表空,无法删除 p=%u\n", p);
}
printf("L中结点个数=%d L是否空 %d(1:空 0:否)\n", ListLength(L), ListEmpty(L));
MakeNode(&p, 10);
p->next = NULL; /* 尾结点 */
for (j = 4; j >= 1; j--)
{
MakeNode(&h, j * 2);
h->next = p;
p = h;
} /* h指向一串5个结点,其值依次是2 4 6 8 10 */
Append(&L, h); /* 把结点h链接在线性链表L的最后一个结点之后 */
OrderInsert(&L, 12, cmp); /* 按升序插在有序表尾头 */
OrderInsert(&L, 7, cmp); /* 按升序插在有序表中间 */
printf("输出链表:");
ListTraverse(L, visit); /* 输出L */
for (j = 1; j <= 2; j++)
{
p = LocateElem(L, j * 5, compare);
if (p)
printf("L中存在值为%d的结点。\n", j * 5);
else
printf("L中不存在值为%d的结点。\n", j * 5);
}
for (j = 1; j <= 2; j++)
{
LocatePos(L, j, &p); /* p指向L的第j个结点 */
h = PriorPos(L, p); /* h指向p的前驱 */
if (h)
printf("%d的前驱是%d。\n", p->data, h->data);
else
printf("%d没前驱。\n", p->data);
}
k = ListLength(L);
for (j = k - 1; j <= k; j++)
{
LocatePos(L, j, &p); /* p指向L的第j个结点 */
h = NextPos(p); /* h指向p的后继 */
if (h)
printf("%d的后继是%d。\n", p->data, h->data);
else
printf("%d没后继。\n", p->data);
}
printf("L中结点个数=%d L是否空 %d(1:空 0:否)\n", ListLength(L), ListEmpty(L));
p = GetLast(L); /* p指向最后一个结点 */
SetCurElem(p, 15); /* 将最后一个结点的值变为15 */
printf("第1个元素为%d 最后1个元素为%d\n", GetCurElem(GetHead(L)->next), GetCurElem(p));
MakeNode(&h, 10);
InsBefore(&L, &p, h); /* 将10插到尾结点之前,p指向新结点 */
p = p->next; /* p恢复为尾结点 */
MakeNode(&h, 20);
InsAfter(&L, &p, h); /* 将20插到尾结点之后 */
k = ListLength(L);
printf("依次删除表尾结点并输出其值:");
for (j = 0; j <= k; j++)
{
i = Remove(&L, &p);
if (!i) /* 删除不成功 */
printf("删除不成功 p=%u\n", p);
else
printf("%d ", p->data);
}
MakeNode(&p, 29); /* 重建具有1个结点(29)的链表 */
InsFirst(&L, L.head, p);
DestroyList(&L); /* 销毁线性链表L */
printf("销毁线性链表L之后: L.head=%u L.tail=%u L.len=%d\n", L.head, L.tail, L.len);
}
测试文件二
#include "LinkList2.h"
typedef LinkList polynomial;
#define DestroyPolyn DestroyList /* 与bo2-6.cpp中的函数同义不同名 */
#define PolynLength ListLength /* 与bo2-6.cpp中的函数同义不同名 */
Status OrderInsertMerge(LinkList *L, ElemType e, int(*compare)(term, term))
{ /* 按有序判定函数compare()的约定,将值为e的结点插入或合并到升序链表L的适当位置 */
Position q, s;
if (LocateElemP(*L, e, &q, compare)) /* L中存在该指数项 */
{
q->data.coef += e.coef; /* 改变当前结点系数的值 */
if (!q->data.coef) /* 系数为0 */
{ /* 删除多项式L中当前结点 */
s = PriorPos(*L, q); /* s为当前结点的前驱 */
if (!s) /* q无前驱 */
s = (*L).head;
DelFirst(L, s, &q);
FreeNode(&q);
}
return OK;
}
else /* 生成该指数项并插入链表 */
if (MakeNode(&s, e)) /* 生成结点成功 */
{
InsFirst(L, q, s);
return OK;
}
else /* 生成结点失败 */
return ERROR;
}
int cmp(term a, term b) /* CreatPolyn()的实参 */
{ /* 依a的指数值<、=或>b的指数值,分别返回-1、0或+1 */
if (a.expn == b.expn)
return 0;
else
return (a.expn - b.expn) / abs(a.expn - b.expn);
}
void CreatPolyn(polynomial *P, int m) /* 算法2.22 */
{ /* 输入m项的系数和指数,建立表示一元多项式的有序链表P */
Position q, s;
term e;
int i;
InitList(P);
printf("请依次输入%d个系数,指数:\n", m);
for (i = 1; i <= m; ++i)
{ /* 依次输入m个非零项(可按任意顺序) */
scanf("%f,%d", &e.coef, &e.expn);
if (!LocateElemP(*P, e, &q, cmp)) /* 当前链表中不存在该指数项,cmp是实参 */
if (MakeNode(&s, e)) /* 生成结点并插入链表 */
InsFirst(P, q, s);
}
}
void PrintPolyn(polynomial P)
{ /* 打印输出一元多项式P */
Link q;
q = P.head->next; /* q指向第一个结点 */
printf(" 系数 指数\n");
while (q)
{
printf("%f %d\n", q->data.coef, q->data.expn);
q = q->next;
}
}
void AddPolyn(polynomial *Pa, polynomial *Pb) /* 算法2.23 */
{ /* 多项式加法:Pa=Pa+Pb,并销毁一元多项式Pb */
Position ha, hb, qa, qb;
term a, b;
ha = GetHead(*Pa);
hb = GetHead(*Pb); /* ha和hb分别指向Pa和Pb的头结点 */
qa = NextPos(ha);
qb = NextPos(hb); /* qa和qb分别指向Pa和Pb中当前结点(现为第一个结点) */
while (!ListEmpty(*Pa) && !ListEmpty(*Pb) && qa)
{ /* Pa和Pb均非空且ha没指向尾结点(qa!=0) */
a = GetCurElem(qa);
b = GetCurElem(qb); /* a和b为两表中当前比较元素 */
switch (cmp(a, b))
{
case -1:ha = qa; /* 多项式Pa中当前结点的指数值小 */
qa = NextPos(ha); /* ha和qa均向后移一个结点 */
break;
case 0: qa->data.coef += qb->data.coef;
/* 两者的指数值相等,修改Pa当前结点的系数值 */
if (qa->data.coef == 0) /* 删除多项式Pa中当前结点 */
{
DelFirst(Pa, ha, &qa);
FreeNode(&qa);
}
else
ha = qa;
DelFirst(Pb, hb, &qb);
FreeNode(&qb);
qb = NextPos(hb);
qa = NextPos(ha);
break;
case 1: DelFirst(Pb, hb, &qb); /* 多项式Pb中当前结点的指数值小 */
InsFirst(Pa, ha, qb);
ha = ha->next;
qb = NextPos(hb);
}
}
if (!ListEmpty(*Pb))
{
(*Pb).tail = hb;
Append(Pa, qb); /* 链接Pb中剩余结点 */
}
DestroyPolyn(Pb); /* 销毁Pb */
}
void AddPolyn1(polynomial *Pa, polynomial *Pb)
{ /* 另一种多项式加法的算法:Pa=Pa+Pb,并销毁一元多项式Pb */
Position qb;
term b;
qb = GetHead(*Pb); /* qb指向Pb的头结点 */
qb = qb->next; /* qb指向Pb的第一个结点 */
while (qb)
{
b = GetCurElem(qb);
OrderInsertMerge(Pa, b, cmp);
qb = qb->next;
}
DestroyPolyn(Pb); /* 销毁Pb */
}
void Opposite(polynomial Pa)
{ /* 一元多项式系数取反 */
Position p;
p = Pa.head;
while (p->next)
{
p = p->next;
p->data.coef *= -1;
}
}
void SubtractPolyn(polynomial *Pa, polynomial *Pb)
{ /* 多项式减法:Pa=Pa-Pb,并销毁一元多项式Pb */
Opposite(*Pb);
AddPolyn(Pa, Pb);
}
void MultiplyPolyn(polynomial *Pa, polynomial *Pb)
{ /* 多项式乘法:Pa=PaPb,并销毁一元多项式Pb */
polynomial Pc;
Position qa, qb;
term a, b, c;
InitList(&Pc);
qa = GetHead(*Pa);
qa = qa->next;
while (qa)
{
a = GetCurElem(qa);
qb = GetHead(*Pb);
qb = qb->next;
while (qb)
{
b = GetCurElem(qb);
c.coef = a.coef*b.coef;
c.expn = a.expn + b.expn;
OrderInsertMerge(&Pc, c, cmp);
qb = qb->next;
}
qa = qa->next;
}
DestroyPolyn(Pb); /* 销毁Pb */
ClearList(Pa); /* 将Pa重置为空表 */
(*Pa).head = Pc.head;
(*Pa).tail = Pc.tail;
(*Pa).len = Pc.len;
}
void main()
{
polynomial p, q;
int m;
printf("请输入第一个一元多项式的非零项的个数:");
scanf("%d", &m);
CreatPolyn(&p, m);
printf("请输入第二个一元多项式的非零项的个数:");
scanf("%d", &m);
CreatPolyn(&q, m);
AddPolyn(&p, &q);
printf("两个一元多项式相加的结果:\n");
PrintPolyn(p);
printf("请输入第三个一元多项式的非零项的个数:");
scanf("%d", &m);
CreatPolyn(&q, m);
AddPolyn1(&p, &q);
printf("两个一元多项式相加的结果(另一种方法):\n");
PrintPolyn(p);
printf("请输入第四个一元多项式的非零项的个数:");
scanf("%d", &m);
CreatPolyn(&q, m);
SubtractPolyn(&p, &q);
printf("两个一元多项式相减的结果:\n");
PrintPolyn(p);
printf("请输入第五个一元多项式的非零项的个数:");
scanf("%d", &m);
CreatPolyn(&q, m);
MultiplyPolyn(&p, &q);
printf("两个一元多项式相乘的结果:\n");
PrintPolyn(p);
DestroyPolyn(&p);
}
测试文件三
#include "LinkList2.h"
Status ListInsert_L(LinkList *L, int i, ElemType e) /* 算法2.20 */
{ /* 在带头结点的单链线性表L的第i个元素之前插入元素e */
Link h, s;
if (!LocatePos(*L, i - 1, &h))
return ERROR; /* i值不合法 */
if (!MakeNode(&s, e))
return ERROR; /* 结点分配失败 */
InsFirst(L, h, s); /*对于从第i个结点开始的链表,第i-1个结点是它的头结点 */
return OK;
}
Status MergeList_L(LinkList La, LinkList Lb, LinkList *Lc, int(*compare)(ElemType, ElemType))
{ /* 已知单链线性表La和Lb的元素按值非递减排列。归并La和Lb得到新的单链 */
/* 线性表Lc,Lc的元素也按值非递减排列。(不改变La、Lb)算法2.21 */
Link ha, hb, pa, pb, q;
ElemType a, b;
if (!InitList(Lc))
return ERROR; /* 存储空间分配失败 */
ha = GetHead(La); /* ha和hb分别指向La和Lb的头结点 */
hb = GetHead(Lb);
pa = NextPos(ha); /* pa和pb分别指向La和Lb的第一个结点 */
pb = NextPos(hb);
while (!ListEmpty(La) && !ListEmpty(Lb)) /* La和Lb均非空 */
{
a = GetCurElem(pa); /* a和b为两表中当前比较元素 */
b = GetCurElem(pb);
if (compare(a, b) <= 0)
{
DelFirst(&La, ha, &q);
InsFirst(Lc, (*Lc).tail, q);
pa = NextPos(ha);
}
else /* a>b */
{
DelFirst(&Lb, hb, &q);
InsFirst(Lc, (*Lc).tail, q);
pb = NextPos(hb);
}
}
if (!ListEmpty(La))
Append(Lc, pa);
else
Append(Lc, pb);
FreeNode(&ha);
FreeNode(&hb);
return OK;
}
int comp(ElemType c1, ElemType c2)
{
return c1 - c2;
}
void visit(ElemType c)
{
printf("%d ", c); /* 整型 */
}
void main()
{
LinkList La, Lb, Lc;
int j;
InitList(&La);
for (j = 1; j <= 5; j++)
ListInsert_L(&La, j, j); /* 顺序插入 1 2 3 4 5 */
printf("La=");
ListTraverse(La, visit);
InitList(&Lb);
for (j = 1; j <= 5; j++)
ListInsert_L(&Lb, j, 2 * j); /* 顺序插入 2 4 6 8 10 */
printf("Lb=");
ListTraverse(Lb, visit);
InitList(&Lc);
MergeList_L(La, Lb, &Lc, comp); /* 归并La和Lb,产生Lc */
printf("Lc=");
ListTraverse(Lc, visit);
DestroyList(&Lc);
}
4.设头尾指针的循环单链表
头文件
#include <stdio.h>
#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;
struct LNode
{
ElemType data;
struct LNode *next;
};
typedef struct LNode *LinkList; /* 另一种定义LinkList的方法 */
Status InitList_CL(LinkList *L);
Status DestroyList_CL(LinkList *L);
Status ClearList_CL(LinkList *L);
Status ListEmpty_CL(LinkList L);
int ListLength_CL(LinkList L);
Status GetElem_CL(LinkList L, int i, ElemType *e);
int LocateElem_CL(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));
Status PriorElem_CL(LinkList L, ElemType cur_e, ElemType *pre_e);
Status NextElem_CL(LinkList L, ElemType cur_e, ElemType *next_e);
Status ListInsert_CL(LinkList *L, int i, ElemType e);
Status ListDelete_CL(LinkList *L, int i, ElemType *e);
Status ListTraverse_CL(LinkList L, void(*vi)(ElemType));
实现文件
#include "cirList.h"
Status InitList_CL(LinkList *L)
{ /* 操作结果:构造一个空的线性表L */
*L = (LinkList)malloc(sizeof(struct LNode)); /* 产生头结点,并使L指向此头结点 */
if (!*L) /* 存储分配失败 */
exit(OVERFLOW);
(*L)->next = *L; /* 指针域指向头结点 */
return OK;
}
Status DestroyList_CL(LinkList *L)
{ /* 操作结果:销毁线性表L */
LinkList q, p = (*L)->next; /* p指向第一个(非头结点)结点 */
while (p != *L) /* 没到表尾 */
{
q = p->next;
free(p);
p = q;
}
free(*L);
*L = NULL;
return OK;
}
Status ClearList_CL(LinkList *L) /* 改变L */
{ /* 初始条件:线性表L已存在。操作结果:将L重置为空表 */
LinkList p, q;
*L = (*L)->next; /* L指向头结点 */
p = (*L)->next; /* p指向第一个结点 */
while (p != *L) /* 没到表尾 */
{
q = p->next;
free(p);
p = q;
}
(*L)->next = *L; /* 头结点指针域指向自身 */
return OK;
}
Status ListEmpty_CL(LinkList L)
{ /* 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
if (L->next == L) /* 空 */
return TRUE;
else
return FALSE;
}
int ListLength_CL(LinkList L)
{ /* 初始条件:L已存在。操作结果:返回L中数据元素个数 */
int i = 0;
LinkList p = L->next; /* p指向头结点 */
while (p != L) /* 没到表尾 */
{
i++;
p = p->next;
}
return i;
}
Status GetElem_CL(LinkList L, int i, ElemType *e)
{ /* 当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */
int j = 1; /* 初始化,j为计数器 */
LinkList p = L->next->next; /* p指向第一个结点 */
if (i <= 0 || i>ListLength_CL(L)) /* 第i个元素不存在 */
return ERROR;
while (j<i)
{ /* 顺指针向后查找,直到p指向第i个元素 */
p = p->next;
j++;
}
*e = p->data; /* 取第i个元素 */
return OK;
}
int LocateElem_CL(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{ /* 初始条件:线性表L已存在,compare()是数据元素判定函数 */
/* 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int i = 0;
LinkList p = L->next->next; /* p指向第一个结点 */
while (p != L->next)
{
i++;
if (compare(p->data, e)) /* 满足关系 */
return i;
p = p->next;
}
return 0;
}
Status PriorElem_CL(LinkList L, ElemType cur_e, ElemType *pre_e)
{ /* 初始条件:线性表L已存在 */
/* 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, */
/* 否则操作失败,pre_e无定义 */
LinkList q, p = L->next->next; /* p指向第一个结点 */
q = p->next;
while (q != L->next) /* p没到表尾 */
{
if (q->data == cur_e)
{
*pre_e = p->data;
return TRUE;
}
p = q;
q = q->next;
}
return FALSE;
}
Status NextElem_CL(LinkList L, ElemType cur_e, ElemType *next_e)
{ /* 初始条件:线性表L已存在 */
/* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, */
/* 否则操作失败,next_e无定义 */
LinkList p = L->next->next; /* p指向第一个结点 */
while (p != L) /* p没到表尾 */
{
if (p->data == cur_e)
{
*next_e = p->next->data;
return TRUE;
}
p = p->next;
}
return FALSE;
}
Status ListInsert_CL(LinkList *L, int i, ElemType e) /* 改变L */
{ /* 在L的第i个位置之前插入元素e */
LinkList p = (*L)->next, s; /* p指向头结点 */
int j = 0;
if (i <= 0 || i>ListLength_CL(*L) + 1) /* 无法在第i个元素之前插入 */
return ERROR;
while (j<i - 1) /* 寻找第i-1个结点 */
{
p = p->next;
j++;
}
s = (LinkList)malloc(sizeof(struct LNode)); /* 生成新结点 */
s->data = e; /* 插入L中 */
s->next = p->next;
p->next = s;
if (p == *L) /* 改变尾结点 */
*L = s;
return OK;
}
Status ListDelete_CL(LinkList *L, int i, ElemType *e) /* 改变L */
{ /* 删除L的第i个元素,并由e返回其值 */
LinkList p = (*L)->next, q; /* p指向头结点 */
int j = 0;
if (i <= 0 || i>ListLength_CL(*L)) /* 第i个元素不存在 */
return ERROR;
while (j<i - 1) /* 寻找第i-1个结点 */
{
p = p->next;
j++;
}
q = p->next; /* q指向待删除结点 */
p->next = q->next;
*e = q->data;
if (*L == q) /* 删除的是表尾元素 */
*L = p;
free(q); /* 释放待删除结点 */
return OK;
}
Status ListTraverse_CL(LinkList L, void(*vi)(ElemType))
{ /* 初始条件:L已存在。操作结果:依次对L的每个数据元素调用函数vi()。一旦vi()失败,则操作失败 */
LinkList p = L->next->next;
while (p != L->next)
{
vi(p->data);
p = p->next;
}
printf("\n");
return OK;
}
#include "cirList.h"
Status compare(ElemType c1, ElemType c2)
{
if (c1 == c2)
return TRUE;
else
return FALSE;
}
void visit(ElemType c)
{
printf("%d ", c);
}
void main()
{
LinkList L;
ElemType e;
int j;
Status i;
i = InitList_CL(&L); /* 初始化单循环链表L */
printf("初始化单循环链表L i=%d (1:初始化成功)\n", i);
i = ListEmpty_CL(L);
printf("L是否空 i=%d(1:空 0:否)\n", i);
ListInsert_CL(&L, 1, 3); /* 在L中依次插入3,5 */
ListInsert_CL(&L, 2, 5);
i = GetElem_CL(L, 1, &e);
j = ListLength_CL(L);
printf("L中数据元素个数=%d,第1个元素的值为%d。\n", j, e);
printf("L中的数据元素依次为:");
ListTraverse_CL(L, visit);
PriorElem_CL(L, 5, &e); /* 求元素5的前驱 */
printf("5前面的元素的值为%d。\n", e);
NextElem_CL(L, 3, &e); /* 求元素3的后继 */
printf("3后面的元素的值为%d。\n", e);
printf("L是否空 %d(1:空 0:否)\n", ListEmpty_CL(L));
j = LocateElem_CL(L, 5, compare);
if (j)
printf("L的第%d个元素为5。\n", j);
else
printf("不存在值为5的元素\n");
i = ListDelete_CL(&L, 2, &e);
printf("删除L的第2个元素:\n");
if (i)
{
printf("删除的元素值为%d,现在L中的数据元素依次为:", e);
ListTraverse_CL(L, visit);
}
else
printf("删除不成功!\n");
printf("清空L:%d(1: 成功)\n", ClearList_CL(&L));
printf("清空L后,L是否空:%d(1:空 0:否)\n", ListEmpty_CL(L));
printf("销毁L:%d(1: 成功)\n", DestroyList_CL(&L));
}
测试文件二
#include "cirList.h"
void MergeList_CL(LinkList *La, LinkList Lb)
{
LinkList p = Lb->next;
Lb->next = (*La)->next;
(*La)->next = p->next;
free(p);
*La = Lb;
}
void visit(ElemType c)
{
printf("%d ", c);
}
void main()
{
int n = 5, i;
LinkList La, Lb;
InitList_CL(&La);
for (i = 1; i <= n; i++)
ListInsert_CL(&La, i, i);
printf("La="); /* 输出链表La的内容 */
ListTraverse_CL(La, visit);
InitList_CL(&Lb);
for (i = 1; i <= n; i++)
ListInsert_CL(&Lb, 1, i * 2);
printf("Lb="); /* 输出链表Lb的内容 */
ListTraverse_CL(Lb, visit);
MergeList_CL(&La, Lb);
printf("La+Lb="); /* 输出合并后的链表的内容 */
ListTraverse_CL(La, visit);
}
5.双向循环链表
头文件
/* c1.h (程序名) */
#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 DuLNode
{
ElemType data;
struct DuLNode *prior, *next;
}DuLNode, *DuLinkList;
/* bo2-5.c 双链循环线性表(存储结构由c2-4.h定义)的基本操作(14个) */
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, 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));
实现文件
#include "duLinkList.h"
Status InitList(DuLinkList *L)
{ /* 产生空的双向循环链表L */
*L = (DuLinkList)malloc(sizeof(DuLNode));
if (*L)
{
(*L)->next = (*L)->prior = *L;
return OK;
}
else
return OVERFLOW;
}
Status 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;
return OK;
}
Status 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; /* 头结点的两个指针域均指向自身 */
return OK;
}
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<i) /* 顺指针向后查找,直到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个元素的位置指针(算法2.18、2.19要调用的函数) */
int j;
DuLinkList p = L;
for (j = 1; j <= i; j++)
p = p->next;
return p;
}
Status ListInsert(DuLinkList L, int i, ElemType e) /* 改进算法2.18 */
{ /* 在带头结点的双链循环线性表L中第i个位置之前插入元素e,i的合法值为1≤i≤表长+1 */
DuLinkList p, s;
if (i<1 || i>ListLength(L) + 1) /* i值不合法 */
return ERROR;
p = GetElemP(L, i - 1); /* 在L中确定第i-1个元素的位置指针p */
if (!p) /* p=NULL,即第i-1个元素不存在 */
return ERROR;
s = (DuLinkList)malloc(sizeof(DuLNode));
if (!s)
return OVERFLOW;
s->data = e; /* 在第i-1个元素之后插入 */
s->prior = p;
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≤表长+1 */
DuLinkList p;
if (i<1 || i>ListLength(L)) /* 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");
}
测试文件一
#include "duLinkList.h"
Status compare(ElemType c1, ElemType c2) /* 数据元素判定函数(判定相等) */
{
if (c1 == c2)
return TRUE;
else
return FALSE;
}
void vd(ElemType c) /* ListTraverse()调用的函数(类型一致) */
{
printf("%d ", c);
}
void main()
{
DuLinkList L;
int i, n;
Status j;
ElemType e;
InitList(&L);
for (i = 1; i <= 5; i++)
ListInsert(L, i, i); /* 在第i个结点之前插入i */
printf("正序输出链表:");
ListTraverse(L, vd); /* 正序输出 */
printf("逆序输出链表:");
ListTraverseBack(L, vd); /* 逆序输出 */
n = 2;
ListDelete(L, n, &e); /* 删除并释放第n个结点 */
printf("删除第%d个结点,值为%d,其余结点为:", n, e);
ListTraverse(L, vd); /* 正序输出 */
printf("链表的元素个数为%d\n", ListLength(L));
printf("链表是否空:%d(1:是 0:否)\n", ListEmpty(L));
ClearList(L); /* 清空链表 */
printf("清空后,链表是否空:%d(1:是 0:否)\n", ListEmpty(L));
for (i = 1; i <= 5; i++)
ListInsert(L, i, i); /* 重新插入5个结点 */
ListTraverse(L, vd); /* 正序输出 */
n = 3;
j = GetElem(L, n, &e); /* 将链表的第n个元素赋值给e */
if (j)
printf("链表的第%d个元素值为%d\n", n, e);
else
printf("不存在第%d个元素\n", n);
n = 4;
i = LocateElem(L, n, compare);
if (i)
printf("等于%d的元素是第%d个\n", n, i);
else
printf("没有等于%d的元素\n", n);
j = PriorElem(L, n, &e);
if (j)
printf("%d的前驱是%d\n", n, e);
else
printf("不存在%d的前驱\n", n);
j = NextElem(L, n, &e);
if (j)
printf("%d的后继是%d\n", n, e);
else
printf("不存在%d的后继\n", n);
DestroyList(&L);
}
6.静态链表
头文件
#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;
//#define N 6 /* 字符串长度 */
//typedef char ElemType[N];
//#define N 2
//typedef char ElemType;
#define MAXSIZE 100 /* 链表的最大长度 */
typedef struct
{
ElemType data;
int cur;
}component, SLinkList[MAXSIZE];
int Malloc(SLinkList space);
void Free(SLinkList space, int k);
void DestroyList();
void InitSpace(SLinkList L);
int InitList(SLinkList L);
Status ClearList(SLinkList L, int n);
Status ListEmpty(SLinkList L, int n);
int ListLength(SLinkList L, int n);
Status GetElem(SLinkList L, int n, int i, ElemType *e);
int LocateElem(SLinkList L, int n, ElemType e);
Status PriorElem(SLinkList L, int n, ElemType cur_e, ElemType *pre_e);
Status NextElem(SLinkList L, int n, ElemType cur_e, ElemType *next_e);
Status ListInsert(SLinkList L, int n, int i, ElemType e);
Status ListDelete(SLinkList L, int n, int i, ElemType *e);
Status ListTraverse(SLinkList L, int n, void(*vi)(ElemType));
实现文件
#include "staticList.h"
int Malloc(SLinkList space) /* 算法2.15 */
{ /* 若备用链表非空,则返回分配的结点下标(备用链表的第一个结点),否则返回0 */
int i = space[0].cur;
if (i) /* 备用链表非空 */
space[0].cur = space[i].cur; /* 备用链表的头结点指向原备用链表的第二个结点 */
return i; /* 返回新开辟结点的坐标 */
}
void Free(SLinkList space, int k) /* 算法2.16 */
{ /* 将下标为k的空闲结点回收到备用链表(成为备用链表的第一个结点) */
space[k].cur = space[0].cur; /* 回收结点的"游标"指向备用链表的第一个结点 */
space[0].cur = k; /* 备用链表的头结点指向新回收的结点 */
}
void DestroyList()
{ /* 静态数组不能被销毁 */
}
void InitSpace(SLinkList L) /* 算法2.14。另加 */
{ /* 将一维数组L中各分量链成一个备用链表,L[0].cur为头指针。“0”表示空指针 */
int i;
for (i = 0; i<MAXSIZE - 1; i++)
L[i].cur = i + 1;
L[MAXSIZE - 1].cur = 0;
}
int InitList(SLinkList L)
{ /* 构造一个空链表,返回值为空表在数组中的位序 */
int i;
i = Malloc(L); /* 调用Malloc(),简化程序 */
L[i].cur = 0; /* 空链表的表头指针为空(0) */
return i;
}
Status ClearList(SLinkList L, int n)
{ /* 初始条件:L中表头位序为n的静态链表已存在。操作结果:将此表重置为空表 */
int j, k, i = L[n].cur; /* 链表第一个结点的位置 */
L[n].cur = 0; /* 链表空 */
k = L[0].cur; /* 备用链表第一个结点的位置 */
L[0].cur = i; /* 把链表的结点连到备用链表的表头 */
while (i) /* 没到链表尾 */
{
j = i;
i = L[i].cur; /* 指向下一个元素 */
}
L[j].cur = k; /* 备用链表的第一个结点接到链表的尾部 */
return OK;
}
Status ListEmpty(SLinkList L, int n)
{ /* 判断L中表头位序为n的链表是否空,若是空表返回TRUE;否则返回FALSE */
if (L[n].cur == 0) /* 空表 */
return TRUE;
else
return FALSE;
}
int ListLength(SLinkList L, int n)
{ /* 返回L中表头位序为n的链表的数据元素个数 */
int j = 0, i = L[n].cur; /* i指向第一个元素 */
while (i) /* 没到静态链表尾 */
{
i = L[i].cur; /* 指向下一个元素 */
j++;
}
return j;
}
Status GetElem(SLinkList L, int n, int i, ElemType *e)
{ /* 用e返回L中表头位序为n的链表的第i个元素的值 */
int l, k = n; /* k指向表头序号 */
if (i<1 || i>ListLength(L, n)) /* i值不合理 */
return ERROR;
for (l = 1; l <= i; l++) /* 移动i-1个元素 */
k = L[k].cur;
*e = L[k].data;
return OK;
}
int LocateElem(SLinkList L, int n, ElemType e)
{ /* 在L中表头位序为n的静态单链表中查找第1个值为e的元素。 */
/* 若找到,则返回它在L中的位序,否则返回0 */
int i = L[n].cur; /* i指示表中第一个结点 */
while (i&&L[i].data != e) /* 在表中顺链查找(e不能是字符串) */
i = L[i].cur;
return i;
}
Status PriorElem(SLinkList L, int n, ElemType cur_e, ElemType *pre_e)
{ /* 初始条件:在L中表头位序为n的静态单链表已存在 */
/* 操作结果:若cur_e是此单链表的数据元素,且不是第一个, */
/* 则用pre_e返回它的前驱,否则操作失败,pre_e无定义 */
int j, i = L[n].cur; /* i为链表第一个结点的位置 */
do
{ /* 向后移动结点 */
j = i;
i = L[i].cur;
} while (i&&cur_e != L[i].data);
if (i) /* 找到该元素 */
{
*pre_e = L[j].data;
return OK;
}
return ERROR;
}
Status NextElem(SLinkList L, int n, ElemType cur_e, ElemType *next_e)
{ /* 初始条件:在L中表头位序为n的静态单链表已存在 */
/* 操作结果:若cur_e是此单链表的数据元素,且不是最后一个, */
/* 则用next_e返回它的后继,否则操作失败,next_e无定义 */
int i;
i = LocateElem(L, n, cur_e); /* 在链表中查找第一个值为cur_e的元素的位置 */
if (i) /* 在静态单链表中存在元素cur_e */
{
i = L[i].cur; /* cur_e的后继的位置 */
if (i) /* cur_e有后继 */
{
*next_e = L[i].data;
return OK; /* cur_e元素有后继 */
}
}
return ERROR; /* L不存在cur_e元素,cur_e元素无后继 */
}
Status ListInsert(SLinkList L, int n, int i, ElemType e)
{ /* 在L中表头位序为n的链表的第i个元素之前插入新的数据元素e */
int l, j, k = n; /* k指向表头 */
if (i<1 || i>ListLength(L, n) + 1)
return ERROR;
j = Malloc(L); /* 申请新单元 */
if (j) /* 申请成功 */
{
L[j].data = e; /* 赋值给新单元 */
for (l = 1; l<i; l++) /* 移动i-1个元素 */
k = L[k].cur;
L[j].cur = L[k].cur;
L[k].cur = j;
return OK;
}
return ERROR;
}
Status ListDelete(SLinkList L, int n, int i, ElemType *e)
{ /* 删除在L中表头位序为n的链表的第i个数据元素e,并返回其值 */
int j, k = n; /* k指向表头 */
if (i<1 || i>ListLength(L, n))
return ERROR;
for (j = 1; j<i; j++) /* 移动i-1个元素 */
k = L[k].cur;
j = L[k].cur;
L[k].cur = L[j].cur;
*e = L[j].data;
Free(L, j);
return OK;
}
Status ListTraverse(SLinkList L, int n, void(*vi)(ElemType))
{ /* 依次对L中表头位序为n的链表的每个数据元素,调用函数vi()。一旦vi()失败,则操作失败 */
int i = L[n].cur; /* 指向第一个元素 */
while (i) /* 没到静态链表尾 */
{
vi(L[i].data); /* 调用vi() */
i = L[i].cur; /* 指向下一个元素 */
}
printf("\n");
return OK;
}
测试文件一
#include "staticList.h"
void main()
{
SLinkList s = { { "", 1 }, { "ZHAO", 2 }, { "QIAN", 3 }, { "SUN", 4 }, { "LI", 5 }, { "ZHOU", 6 }, { "WU", 7 }, { "ZHENG", 8 }, { "WANG", 0 } };
int i;
i = s[0].cur;
while (i) /* 输出教科书中图2.10(a)的状态 */
{
printf("%s ", s[i].data); /* 输出链表的当前值 */
i = s[i].cur; /* 找到下一个 */
}
printf("\n");
s[4].cur = 9; /* 按教科书中图2.10(b)修改 */
s[6].cur = 8;
s[9].cur = 5;
strcpy(s[9].data, "SHI");
i = s[0].cur;
while (i) /* 输出教科书中图2.10(b)的状态 */
{
printf("%s ", s[i].data); /* 输出链表的当前值 */
i = s[i].cur; /* 找到下一个 */
}
printf("\n");
}
测试文件二
#include "staticList.h"
void difference(SLinkList space, int *S) /* 算法2.17 */
{ /* 依次输入集合A和B的元素,在一维数组space中建立表示集合(A-B)∪(B-A) */
/* 的静态链表,S为其头指针。假设备用空间足够大,space[0].cur为备用空间的头指针 */
int r, p, m, n, i, j, k;
ElemType b;
InitSpace(space); /* 初始化备用空间 */
*S = Malloc(space); /* 生成S的头结点 */
r = *S; /* r指向S的当前最后结点 */
printf("请输入集合A和B的元素个数m,n:");
scanf("%d,%d%*c", &m, &n); /* %*c吃掉回车符 */
printf("请输入集合A的元素(共%d个):", m);
for (j = 1; j <= m; j++) /* 建立集合A的链表 */
{
i = Malloc(space); /* 分配结点 */
scanf("%c", &space[i].data); /* 输入A的元素值 */
space[r].cur = i; /* 插入到表尾 */
r = i;
}
scanf("%*c"); /* %*c吃掉回车符 */
space[r].cur = 0; /* 尾结点的指针为空 */
printf("请输入集合B的元素(共%d个):", n);
for (j = 1; j <= n; j++)
{ /* 依次输入B的元素,若不在当前表中,则插入,否则删除 */
scanf("%c", &b);
p = *S;
k = space[*S].cur; /* k指向集合A中的第一个结点 */
while (k != space[r].cur&&space[k].data != b)
{ /* 在当前表中查找 */
p = k;
k = space[k].cur;
}
if (k == space[r].cur)
{ /* 当前表中不存在该元素,插入在r所指结点之后,且r的位置不变 */
i = Malloc(space);
space[i].data = b;
space[i].cur = space[r].cur;
space[r].cur = i;
}
else /* 该元素已在表中,删除之 */
{
space[p].cur = space[k].cur;
Free(space, k);
if (r == k)
r = p; /* 若删除的是尾元素,则需修改尾指针 */
}
}
}
void visit(ElemType c)
{
printf("%c ", c);
}
void main()
{
int k;
SLinkList s;
difference(s, &k);
ListTraverse(s, k, visit);
}
测试文件三
#include "staticList.h"
//
/这段程序有点问题
void visit(ElemType c)
{
printf("%c ", c);
}
int difference(SLinkList space) /* 改进算法2.17(尽量利用基本操作实现) */
{ /* 依次输入集合A和B的元素,在一维数组space中建立表示集合(A-B)∪(B-A) */
/* 的静态链表,并返回其头指针。假设备用空间足够大,space[0].cur为备用空间的头指针 */
int m, n, i, j, k, S;
ElemType b, c;
InitSpace(space); /* 初始化备用空间 */
S = InitList(space); /* 生成链表S的头结点 */
printf("请输入集合A和B的元素个数m,n:");
scanf("%d,%d%*c", &m, &n); /* %*c吃掉回车符 */
printf("请输入集合A的元素(共%d个):", m);
for (j = 1; j <= m; j++) /* 建立集合A的链表 */
{
scanf("%c", &b); /* 输入A的元素值 */
ListInsert(space, S, j, b); /* 插入到表尾 */
}
scanf("%*c"); /* 吃掉回车符 */
printf("请输入集合B的元素(共%d个):", n);
for (j = 1; j <= n; j++)
{ /* 依次输入B的元素,若不在当前表中,则插入,否则删除 */
scanf("%c", &b);
k = LocateElem(space, S, b); /* k为b的位序 */
if (k) /* b在当前表中 */
{
PriorElem(space, S, b, &c); /* b的前驱为c */
i = LocateElem(space, S, c); /* i为c的位序 */
space[i].cur = space[k].cur; /* 将k的指针赋给i的指针 */
Free(space, k); /* 将下标为k的空闲结点回收到备用链表 */
}
else
ListInsert(space, S, ListLength(space, S) + 1, b); /* 在表尾插入b */
}
return S;
}
void main()
{
int k;
SLinkList s;
k = difference(s);
ListTraverse(s, k, visit);
}
测试程序四
#include "staticList.h"
void visit(ElemType c)
{
printf("%d ", c);
}
void main()
{
int j, k, La, Lb;
Status i;
ElemType e, e0;
SLinkList L;
InitSpace(L); /* 建立备用链表 */
La = InitList(L); /* 初始化链表La */
Lb = InitList(L); /* 初始化链表Lb */
printf("La表空否?%d(1:空 0:否) La的表长=%d\n", ListEmpty(L, La), ListLength(L, La));
for (j = 1; j <= 5; j++)
ListInsert(L, La, 1, j);
printf("在空表La的表头依次插入1~5后:La=");
ListTraverse(L, La, visit);
for (j = 1; j <= 5; j++)
ListInsert(L, Lb, j, j);
printf("在空表Lb的表尾依次插入1~5后:Lb=");
ListTraverse(L, Lb, visit);
printf("La表空否?%d(1:空 0:否) La的表长=%d\n", ListEmpty(L, La), ListLength(L, La));
ClearList(L, La);
printf("清空La后:La=");
ListTraverse(L, La, visit);
printf("La表空否?%d(1:空 0:否) La的表长=%d\n", ListEmpty(L, La), ListLength(L, La));
for (j = 2; j<8; j += 5)
{
i = GetElem(L, Lb, j, &e);
if (i)
printf("Lb表的第%d个元素的值为:%d\n", j, e);
else
printf("Lb表不存在第%d个元素!\n", j, e);
}
for (j = 0; j <= 1; j++)
{
k = LocateElem(L, Lb, j);
if (k)
printf("Lb表中值为%d的元素在静态链表中的位序为%d\n", j, k);
else
printf("Lb表中没有值为%d的元素\n", j);
}
for (j = 1; j <= 2; j++) /* 测试头两个数据 */
{
GetElem(L, Lb, j, &e0); /* 把第j个数据赋给e0 */
i = PriorElem(L, Lb, e0, &e); /* 求e0的前驱 */
if (!i)
printf("Lb表中的元素%d无前驱\n", e0);
else
printf("Lb表中元素%d的前驱为:%d\n", e0, e);
}
for (j = ListLength(L, Lb) - 1; j <= ListLength(L, Lb); j++) /* 最后两个数据 */
{
GetElem(L, Lb, j, &e0); /* 把第j个数据赋给e0 */
i = NextElem(L, Lb, e0, &e); /* 求e0的后继 */
if (!i)
printf("Lb表中元素%d无后继\n", e0);
else
printf("Lb表中元素%d的后继为:%d\n", e0, e);
}
k = ListLength(L, Lb); /* k为表长 */
for (j = k + 1; j >= k; j--)
{
i = ListDelete(L, Lb, j, &e); /* 删除第j个数据 */
if (i)
printf("Lb表中第%d个元素为%d,已删除。\n", j, e);
else
printf("删除Lb表中第%d个数据失败(不存在此元素)。\n", j);
}
printf("依次输出Lb的元素:");
ListTraverse(L, Lb, visit); /* 依次对元素调用visit(),输出元素的值 */
}
另一个版本静态链表
头文件
/* c1.h (程序名) */
#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;
/* c2-3.h 线性表的静态单链表存储结构 */
#define MAXSIZE 100 /* 链表的最大长度 */
typedef struct
{
ElemType data;
int cur;
}component, SLinkList[MAXSIZE];
int Malloc(SLinkList space);
void Free(SLinkList space, int k);
void DestroyList();
void InitList(SLinkList L);
Status ClearList(SLinkList L);
Status ListEmpty(SLinkList L);
int ListLength(SLinkList L);
Status GetElem(SLinkList L, int i, ElemType *e);
int LocateElem(SLinkList L, ElemType e);
Status PriorElem(SLinkList L, ElemType cur_e, ElemType *pre_e);
Status NextElem(SLinkList L, ElemType cur_e, ElemType *next_e);
Status ListInsert(SLinkList L, int i, ElemType e);
Status ListDelete(SLinkList L, int i, ElemType *e);
Status ListTraverse(SLinkList L, void(*vi)(ElemType));
实现文件
#include "staticList2.h"
int Malloc(SLinkList space) /* 算法2.15 */
{ /* 若备用链表非空,则返回分配的结点下标(备用链表的第一个结点),否则返回0 */
int i = space[0].cur;
if (i) /* 备用链表非空 */
space[0].cur = space[i].cur; /* 备用链表的头结点指向原备用链表的第二个结点 */
return i; /* 返回新开辟结点的坐标 */
}
void Free(SLinkList space, int k) /* 算法2.16 */
{ /* 将下标为k的空闲结点回收到备用链表(成为备用链表的第一个结点) */
space[k].cur = space[0].cur; /* 回收结点的"游标"指向备用链表的第一个结点 */
space[0].cur = k; /* 备用链表的头结点指向新回收的结点 */
}
void DestroyList()
{ /* 静态数组不能被销毁 */
}
void InitList(SLinkList L)
{ /* 构造一个空的链表,表头为L的最后一个单元L[MAXSIZE-1],其余单元链成 */
/* 一个备用链表,表头为L的第一个单元L[0],“0”表示空指针 */
int i;
L[MAXSIZE - 1].cur = 0; /* L的最后一个单元为空链表的表头 */
for (i = 0; i<MAXSIZE - 2; i++) /* 将其余单元链接成以L[0]为表头的备用链表 */
L[i].cur = i + 1;
L[MAXSIZE - 2].cur = 0;
}
Status ClearList(SLinkList L)
{ /* 初始条件:线性表L已存在。操作结果:将L重置为空表 */
int i, j, k;
i = L[MAXSIZE - 1].cur; /* 链表第一个结点的位置 */
L[MAXSIZE - 1].cur = 0; /* 链表空 */
k = L[0].cur; /* 备用链表第一个结点的位置 */
L[0].cur = i; /* 把链表的结点连到备用链表的表头 */
while (i) /* 没到链表尾 */
{
j = i;
i = L[i].cur; /* 指向下一个元素 */
}
L[j].cur = k; /* 备用链表的第一个结点接到链表的尾部 */
return OK;
}
Status ListEmpty(SLinkList L)
{ /* 若L是空表,返回TRUE;否则返回FALSE */
if (L[MAXSIZE - 1].cur == 0) /* 空表 */
return TRUE;
else
return FALSE;
}
int ListLength(SLinkList L)
{ /* 返回L中数据元素个数 */
int j = 0, i = L[MAXSIZE - 1].cur; /* i指向第一个元素 */
while (i) /* 没到静态链表尾 */
{
i = L[i].cur; /* 指向下一个元素 */
j++;
}
return j;
}
Status GetElem(SLinkList L, int i, ElemType *e)
{ /* 用e返回L中第i个元素的值 */
int l, k = MAXSIZE - 1; /* k指向表头序号 */
if (i<1 || i>ListLength(L))
return ERROR;
for (l = 1; l <= i; l++) /* 移动到第i个元素处 */
k = L[k].cur;
*e = L[k].data;
return OK;
}
int LocateElem(SLinkList L, ElemType e) /* 算法2.13(有改动) */
{ /* 在静态单链线性表L中查找第1个值为e的元素。若找到,则返回它在L中的 */
/* 位序,否则返回0。(与其它LocateElem()的定义不同) */
int i = L[MAXSIZE - 1].cur; /* i指示表中第一个结点 */
while (i&&L[i].data != e) /* 在表中顺链查找(e不能是字符串) */
i = L[i].cur;
return i;
}
Status PriorElem(SLinkList L, ElemType cur_e, ElemType *pre_e)
{ /* 初始条件:线性表L已存在 */
/* 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, */
/* 否则操作失败,pre_e无定义 */
int j, i = L[MAXSIZE - 1].cur; /* i指示链表第一个结点的位置 */
do
{ /* 向后移动结点 */
j = i;
i = L[i].cur;
} while (i&&cur_e != L[i].data);
if (i) /* 找到该元素 */
{
*pre_e = L[j].data;
return OK;
}
return ERROR;
}
Status NextElem(SLinkList L, ElemType cur_e, ElemType *next_e)
{ /* 初始条件:线性表L已存在 */
/* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, */
/* 否则操作失败,next_e无定义 */
int j, i = LocateElem(L, cur_e); /* 在L中查找第一个值为cur_e的元素的位置 */
if (i) /* L中存在元素cur_e */
{
j = L[i].cur; /* cur_e的后继的位置 */
if (j) /* cur_e有后继 */
{
*next_e = L[j].data;
return OK; /* cur_e元素有后继 */
}
}
return ERROR; /* L不存在cur_e元素,cur_e元素无后继 */
}
Status ListInsert(SLinkList L, int i, ElemType e)
{ /* 在L中第i个元素之前插入新的数据元素e */
int l, j, k = MAXSIZE - 1; /* k指向表头 */
if (i<1 || i>ListLength(L) + 1)
return ERROR;
j = Malloc(L); /* 申请新单元 */
if (j) /* 申请成功 */
{
L[j].data = e; /* 赋值给新单元 */
for (l = 1; l<i; l++) /* 移动i-1个元素 */
k = L[k].cur;
L[j].cur = L[k].cur;
L[k].cur = j;
return OK;
}
return ERROR;
}
Status ListDelete(SLinkList L, int i, ElemType *e)
{ /* 删除在L中第i个数据元素e,并返回其值 */
int j, k = MAXSIZE - 1; /* k指向表头 */
if (i<1 || i>ListLength(L))
return ERROR;
for (j = 1; j<i; j++) /* 移动i-1个元素 */
k = L[k].cur;
j = L[k].cur;
L[k].cur = L[j].cur;
*e = L[j].data;
Free(L, j);
return OK;
}
Status ListTraverse(SLinkList L, void(*vi)(ElemType))
{ /* 初始条件:线性表L已存在 */
/* 操作结果:依次对L的每个数据元素调用函数vi()。一旦vi()失败,则操作失败 */
int i = L[MAXSIZE - 1].cur; /* 指向第一个元素 */
while (i) /* 没到静态链表尾 */
{
vi(L[i].data); /* 调用vi() */
i = L[i].cur; /* 指向下一个元素 */
}
printf("\n");
return OK;
}
测试文件一
#include "staticList2.h"
void visit(ElemType c)
{
printf("%d ", c);
}
void main()
{
int j, k;
Status i;
ElemType e, e0;
SLinkList L;
InitList(L);
for (j = 1; j <= 5; j++)
i = ListInsert(L, 1, j);
printf("在L的表头依次插入1~5后:L=");
ListTraverse(L, visit);
i = ListEmpty(L);
printf("L是否空:i=%d(1:是 0:否)表L的长度=%d\n", i, ListLength(L));
i = ClearList(L);
printf("清空L后:L=");
ListTraverse(L, visit);
i = ListEmpty(L);
printf("L是否空:i=%d(1:是 0:否)表L的长度=%d\n", i, ListLength(L));
for (j = 1; j <= 10; j++)
ListInsert(L, j, j);
printf("在L的表尾依次插入1~10后:L=");
ListTraverse(L, visit);
GetElem(L, 5, &e);
printf("第5个元素的值为:%d\n", e);
for (j = 0; j <= 1; j++)
{
k = LocateElem(L, j);
if (k)
printf("值为%d的元素在静态链表中的位序为%d\n", j, k);
else
printf("没有值为%d的元素\n", j);
}
for (j = 1; j <= 2; j++) /* 测试头两个数据 */
{
GetElem(L, j, &e0); /* 把第j个数据赋给e0 */
i = PriorElem(L, e0, &e); /* 求e0的前驱 */
if (!i)
printf("元素%d无前驱\n", e0);
else
printf("元素%d的前驱为:%d\n", e0, e);
}
for (j = ListLength(L) - 1; j <= ListLength(L); j++) /* 最后两个数据 */
{
GetElem(L, j, &e0); /* 把第j个数据赋给e0 */
i = NextElem(L, e0, &e); /* 求e0的后继 */
if (!i)
printf("元素%d无后继\n", e0);
else
printf("元素%d的后继为:%d\n", e0, e);
}
k = ListLength(L); /* k为表长 */
for (j = k + 1; j >= k; j--)
{
i = ListDelete(L, j, &e); /* 删除第j个数据 */
if (i)
printf("删除的元素为:%d\n", e);
else
printf("删除第%d个数据失败\n", j);
}
printf("依次输出L的元素:");
ListTraverse(L, visit); /* 依次对元素调用visit(),输出元素的值 */
}