线性表

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(),输出元素的值 */
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值