头文件 head.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 LNode{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
//typedef struct LNode *LinkList;
Status InitList_L(LinkList *L);
Status DestoryList_L(LinkList *L);
Status ClearList_L(LinkList *L);
Boolean ListEmpty_L(LinkList L);
int ListLength_L(LinkList L);
Status GetElem_L(LinkList L, int i, ElemType *e);
int LocateElem_L(LinkList L, ElemType e);
Status PriorElem_L(LinkList L, ElemType cur_e, ElemType *pre_e);
Status NextElem_L(LinkList L, ElemType cur_e, ElemType *next_e);
Status ListInsert_L(LinkList *L, int i, ElemType e);
Status ListDelet_L(LinkList *L, int i, ElemType *e);
Status ListTraverse_L(LinkList L);
void CreateList_R_L(LinkList *L, int n);
void CreateList_F_L(LinkList *L, int n);
void MergerList_L_L(LinkList A, LinkList B, LinkList *C);
void MergerList_H_L(LinkList A, LinkList *B, LinkList *C);
算法实现
#include"head.h"
//带有头结点的单链表
Status InitList_L(LinkList *L)
{
//操作结果:构造一个空线性表L
*L = (LinkList)malloc(sizeof(LNode));
if (!(*L))
{
printf("构造线性表失败!\n");
exit(OVERFLOW);
}
(*L)->next = NULL;
return OK;
}
Status DestoryList_L(LinkList *L)
{
//初始条件:线性表L已存在,将其中的每一个指向后继元素的指针都free掉
//操作结果:销毁线性表L
LinkList p;
while (*L)
{
p = (*L)->next;
free(*L);//头结点也要释放掉
*L = p;
}
return OK;
}
Status ClearList_L(LinkList *L)
{
//初始条件:线性表L已存在
//操作结果:将L重置为空表,不改变L,即只需将该链表中的指针全部释放掉但还保留其中的形式
//注意和DestoryList做对比
LinkList p, q;
p = (*L)->next; //p指向第一个结点
while (p) //要保存大致结构
{
q = p->next;
free(p);
p = q;
}
(*L)->next = NULL;
return OK;
}
Boolean ListEmpty_L(LinkList L)
{
//初始条件:线性表L已存在
//操作结果:若L为空,则返回TRUE;否则,返回FASLE
if (L->next)
return FALSE;
else
return TRUE;
}
int ListLength_L(LinkList L)
{
//初始条件:线性表L已存在
//操作结果:返回L中数据元素个数
int i = 0;
LinkList p = L->next; //单链表的第一个数据结点
while (p)
{
i++;
p = p->next;
}
return i;
}
Status GetElem_L(LinkList L, int i, ElemType *e)
{
//初始条件:线性表L已存在且1<= i <= ListLength(L) ,L为带头结点的单链表头指针
//操作结果:用e返回L中第i个数据元素的值
LinkList p = L->next;
int n = 1;
while (p && n < i) //找到第i个元素
{
p = p->next;
n++;
}
if (!p || n > i) //寻找失败则退出该函数
return ERROR;
*e = p->data;
return OK;
}
int LocateElem_L(LinkList L, ElemType e)
{
//初始条件:线性表L已存在
//操作结果:返回L中第一个与元素e相等的数据元素的位序,若这样的元素不存在则返回0
int n = 0;
LinkList p = L->next; //第一个结点,非头结点
while (p)
{
n++;
if (p->data == e)
return n;
p = p->next;
}
return 0;
}
Status PriorElem_L(LinkList L, ElemType cur_e, ElemType *pre_e)
{
//初始条件:线性表L已存在
//操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,否则失败,pre_e无定义
LinkList p = L->next; //代表当前元素的前驱
LinkList q = p->next; //代表当前元素
while (q) //从第二个元素开始
{
if (q->data == cur_e)
{
*pre_e = p->data;
return TRUE;
}
p = q;
q = q->next;
}
return INFEASIBLE;
}
Status NextElem_L(LinkList L, ElemType cur_e, ElemType *next_e)
{
//初始条件:线性表L已存在
//操作结果:若cur_e是L的数据元素且不是最后一个,则用pre_e返回它的后继,否则操作失败,next_e无意义
LinkList p = L->next;
while (p)
{
if (p->data == cur_e)
{
p = p->next;
if (p)
{
*next_e = p->data;
return TRUE;
}
else
return INFEASIBLE;
}
p = p->next;
}
return INFEASIBLE;
}
Status ListInsert_L(LinkList *L, int i, ElemType e)
{
//初始条件:线性表L已存在, 1<= i <=ListLength(L)+1
//操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1
LinkList p = *L;
int n = 1;
LinkList t;
if (i<1 || i>ListLength_L(*L) + 1)
return ERROR;
while (p && n<i)//找到位序i之前的结点,即i-1的结点
{
p = p->next;
n++;
}
if (!p || n > i)
return FALSE;
t = (LinkList)malloc(sizeof(struct LNode));
t->data = e;
t->next = p->next;
p->next = t;
return OK;
}
Status ListDelet_L(LinkList *L, int i, ElemType *e)
{
//初始条件:线性表L已存在
//操作结果:在头结点的单链表L中,删除第i个元素,并有e返回其值
LinkList p = *L, q;
int n = 1;
if (i<1 || i>ListLength_L(*L) + 1)
return ERROR;
while (p->next && n < i) //寻找第i个结点,并令p指向其前驱
{
p = p->next;
n++;
}
if (!(p->next) || n > i)
return FALSE;
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return OK;
}
Status ListTraverse_L(LinkList L)
{
//初始条件:线性表L已存在
//操作结果:输出线性链表中的元素
LinkList p = L->next;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
return OK;
}
//算法2.11 从表尾到表头逆向建立单链表的算法
void CreateList_R_L(LinkList *L, int n)
{
LinkList p;
*L = (LinkList)malloc(sizeof(LNode));
(*L)->next = NULL;
printf("请输%d个元素值【空格键隔开】:", n);
for (; n >= 1; n--)
{
p = (LinkList)malloc(sizeof(LNode));
scanf_s("%d", &p->data);
p->next = (*L)->next; //插入到表头
(*L)->next = p;
}
}
//算法2.11-1 从表头到表尾正向建立单链表的算法
void CreateList_F_L(LinkList *L, int n)
{
LinkList p, q;
(*L) = (LinkList)malloc(sizeof(struct LNode));
(*L)->next = NULL;
q = (*L);//q指向空表的头结点(相当于尾结点)
printf("请输入%d个数据【空格键隔开】", n);
for (int i = 1; i <= n; i++)
{
p = (LinkList)malloc(sizeof(struct LNode));
scanf_s("%d", &p->data);
q->next = p;//将新结点插到表尾
q = q->next;//q指向尾结点,向前进
}
q->next = NULL;//最后一个节点的指针域为空
}
//算法2.12合并两个有序链表为一个有序链表,借鉴了顺序列表的思想,效率低
void MergerList_L_L(LinkList A, LinkList B, LinkList *C)
{
//已知条件:单链表A和B中的元素按非递减排序
//输出结果:归并A和B得到新的单链表C,C的元素也按值非递减排序
int sA = ListLength_L(A), sB = ListLength_L(B);
int nA = 1, nB = 1, nC = 1;
ElemType eA, eB;
while (nA <= sA && nB <= sB)
{
GetElem_L(A, nA, &eA);//在单链表中效率比较低
GetElem_L(B, nB, &eB);//在单链表中效率比较低
if (eA < eB)
{
ListInsert_L(C, nC, eA);
nA++;
nC++;
}
else
{
ListInsert_L(C, nC, eB);
nB++;
nC++;
}
}
while (nA <= sA)
{
GetElem_L(A, nA, &eA);
ListInsert_L(C, nC, eA);
nA++;
nC++;
}
while (nB <= sB)
{
GetElem_L(B, nB, &eB);
ListInsert_L(C, nC, eB);
nB++;
nC++;
}
}
//算法2.12合并两个有序链表为一个有序链表,充分利用例链表,效率高
void MergerList_H_L(LinkList A, LinkList *B, LinkList *C)
{
LinkList pa = A->next, pb = (*B)->next, pc;
*C = pc = A;
while (pa&&pb)
if (pa->data <= pb->data)
{
pc->next = pa;//将pa所指结点归并到C中
pc = pa;//pc指向表C的最后一个节点
pa = pa->next;
}
else
{
pc->next = pb;
pc = pb;
pb = pb->next;
}
pc->next = pa ? pa : pb;//插入剩余段
free(*B); //释放B的头结点
(*B) = NULL;
}
测试文件 test.c
#include"head.h"
void main() /* 除了几个输出语句外,主程和main2-1.c很像 */
{
LinkList L; /* 与main2-1.c不同 */
ElemType e, e0;
Status i;
int j, k;
i = InitList_L(&L);
for (j = 1; j <= 5; j++)
i = ListInsert_L(&L, 1, j);
printf("在L的表头依次插入1~5后:L=");
ListTraverse_L(L); /* 依次对元素调用visit(),输出元素的值 */
i = ListEmpty_L(L);
printf("\nL是否空:i=%d(1:是 0:否)\n", i);
i = ClearList_L(&L);
printf("清空L后:L=");
ListTraverse_L(L);
i = ListEmpty_L(L);
printf("L是否空:i=%d(1:是 0:否)\n", i);
for (j = 1; j <= 10; j++)
ListInsert_L(&L, j, j);
printf("在L的表尾依次插入1~10后:L=");
ListTraverse_L(L);
GetElem_L(L, 5, &e);
printf("\n第5个元素的值为:%d\n", e);
//检测LocateElem_L
for (j = 0; j <= 1; j++)
{
k = LocateElem_L(L, j);
if (k)
printf("第%d个元素的值为%d\n", k, j);
else
printf("没有值为%d的元素\n", j);
}
for (j = 1; j <= 2; j++) /* 测试头两个数据 */
{
GetElem_L(L, j, &e0); /* 把第j个数据赋给e0 */
i = PriorElem_L(L, e0, &e); /* 求e0的前驱 */
if (i == INFEASIBLE)
printf("元素%d无前驱\n", e0);
else
printf("元素%d的前驱为:%d\n", e0, e);
}
for (j = ListLength_L(L) - 1; j <= ListLength_L(L); j++)/*最后两个数据 */
{
GetElem_L(L, j, &e0); /* 把第j个数据赋给e0 */
i = NextElem_L(L, e0, &e); /* 求e0的后继 */
if (i == INFEASIBLE)
printf("元素%d无后继\n", e0);
else
printf("元素%d的后继为:%d\n", e0, e);
}
k = ListLength_L(L); /* k为表长 */
for (j = k + 1; j >= k; j--)
{
i = ListDelet_L(&L, j, &e); /* 删除第j个数据 */
if (i == ERROR)
printf("删除第%d个数据失败\n", j);
else
printf("删除的元素为:%d\n", e);
}
printf("依次输出L的元素:");
ListTraverse_L(L);
DestoryList_L(&L);
printf("\n销毁L后:L=%u\n", L);
system("pause");
}
Running result:
在L的表头依次插入1~5后:L=5 4 3 2 1
L是否空:i=0(1:是 0:否)
清空L后:L=
L是否空:i=1(1:是 0:否)
在L的表尾依次插入1~10后:L=1 2 3 4 5 6 7 8 9 10
第5个元素的值为:5
没有值为0的元素
第1个元素的值为1
元素1无前驱
元素2的前驱为:1
元素9的后继为:10
元素10无后继
删除第11个数据失败
删除的元素为:10
依次输出L的元素:1 2 3 4 5 6 7 8 9
销毁L后:L=0
请按任意键继续. . .
测试文件 test2.c
#include"head.h"
void main()
{
LinkList A, B, C;
LinkList D, E, F;
int n = 0;
InitList_L(&A);
InitList_L(&B);
InitList_L(&C);
for (int i = 1; i <= 5; i++)
ListInsert_L(&A, i, (i + 3));
for (int i = 1; i <= 10; i++)
ListInsert_L(&B, i, i);
printf("单链表A中的元素有:");
ListTraverse_L(A);
printf("\n单链表B中的元素有:");
ListTraverse_L(B);
MergerList_L_L(A, B, &C);
printf("\n单链表C中的元素有:");
ListTraverse_L(C);
printf("\n");
printf("请输入单链表D中的元素个数值n:");
scanf_s("%d", &n);
CreateList_F_L(&D, n);
printf("请输入单链表E中的元素个数值n:");
scanf_s("%d", &n);
CreateList_F_L(&E, n);
MergerList_H_L(D, &E, &F);
printf("\n单链表F中的元素有:");
ListTraverse_L(F);
printf("\n");
system("pause");
}
Running Result:
单链表A中的元素有:4 5 6 7 8
单链表B中的元素有:1 2 3 4 5 6 7 8 9 10
单链表C中的元素有:1 2 3 4 4 5 5 6 6 7 7 8 8 9 10
请输入单链表D中的元素个数值n:3
请输入3个数据【空格键隔开】1 2 3
请输入单链表E中的元素个数值n:3
请输入3个数据【空格键隔开】4 5 6
单链表F中的元素有:1 2 3 4 5 6
请按任意键继续. . .