高一凡-数据结构第2章-线性表
2.2.1线性表的顺序表示和实现
结构体如下:
struct Sqlist
{
ElemType *elem;
int length;
int listsize;
};
指针域是一个类型指针,用于顺序存储数据,两个标志位,length标志表当前存储数据个数,listsize标志表可容纳的数据量。
函数列表 |
---|
void InitList(Sqlist &L); --初始化 |
void DestoryList(Sqlist &L);–销毁 |
void ClearList(Sqlist &L);–清空 |
Status ListEmpty(Sqlist L);–表空为真 |
int ListLength(Sqlist L);–返回表长 |
Status GetElem(Sqlist L, int i, ElemType &e);–获取表中元素值 |
int LocateElem(Sqlist L, ElemType e, Status(*compare) |
Status PriorElem(Sqlist L, ElemType cur_e, ElemType &pre_e);找前驱元素 |
Status NextElem(Sqlist L, ElemType cur_e, ElemType &next_e);找后继元素 |
Status ListInsert(Sqlist &L, int i, ElemType e);插入 |
Status ListDelete(Sqlist &L, int i, ElemType &e);删除 |
void ListTraverse(Sqlist &L, void(*visit)(ElemType&));遍历 |
Status equal(ElemType c1, ElemType c2);附加函数,判等 |
int comp(ElemType a, ElemType b);比较 |
void print(ElemType c);打印 |
void print1(ElemType &c); |
void print2(ElemType c); |
1.初始化
传入引用型顺序表结构L,对于L的指针域进行分配最大顺序空间,同时初始化L的数据长度,以及顺序表的可用长度。
void InitList(Sqlist &L)
{
L.elem = (ElemType*)malloc(sizeof(ElemType) * LIST_INIT_SIZE);
if (!L.elem)
exit(OVERFLOW);
L.length = 0;
L.listsize = LIST_INIT_SIZE;
}
2.销毁与清空
销毁即free掉分配给L指针域的空间,传入的是引用。
void DestoryList(Sqlist &L)
{
free(L.elem);
L.elem = NULL;
L.length = 0;
L.listsize = 0;
}
清空就比较简单,直接将L的当前长度置为0,再次使用时,会覆盖掉原来的值。
void ClearList(Sqlist &L)
{
L.length = 0;
}
3.判空与长度
判定条件,L的当前长度为0
Status ListEmpty(Sqlist L)
{
if (L.length == 0)
return TRUE;
else
return FALSE;
}
int ListLength(Sqlist L)
{
return L.length;
}
4.获取元素值与位置
Status GetElem(Sqlist L, int i, ElemType &e)
{
if (i<1 || i>L.length)
return ERROR;
e = *(L.elem + i - 1);//注意这里是i-1,数据从*elem开始
return OK;
}
//这里的compare可以看成equal函数,当二者相等时判1,否则判0。
int LocateElem(Sqlist L, ElemType e, Status(*compare)(ElemType, ElemType))
{
int i = 1;
ElemType *p = L.elem;
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)
{
int i = 1;
ElemType *p = L.elem + 1;
while (i <= L.length &&*p != cur_e)
{
p++;
i++;
}
if (i > L.length)
return ERROR;
else
{
pre_e = *--p;
return OK;
}
}
//寻找后一个结点
Status NextElem(Sqlist L, ElemType cur_e, ElemType &next_e)
{
int i = 1;
ElemType *p = L.elem;
while (i < L.length && *p != cur_e)
{
p++;
i++;
}
if (i == L.length)
return ERROR;
else
{
next_e = *++p;
return OK;
}
}
Status ListInsert(Sqlist &L, int i, ElemType e)
{
ElemType *newbase, *p, *q;
if (i < 1 || i >L.length + 1)
return ERROR;
if (L.length == L.listsize)
{
newbase = (ElemType*)realloc(L.elem, (L.listsize + LIST_INCREMENT) * sizeof(ElemType));
if (!newbase)
exit(OVERFLOW);
L.elem = newbase;
L.listsize += LIST_INCREMENT;
}
q = L.elem + i - 1;
for (p = L.elem + L.length - 1; p >= q; --p)
*(p + 1) = *p;
*q = e;
++L.length;
return OK;
}
Status ListDelete(Sqlist &L, int i, ElemType &e)
{
ElemType *p, *q;
if (i<1 || i>L.length)
return ERROR;
p = L.elem + i - 1;
e = *p;
q = L.elem + L.length - 1;
for (++p; p <= q; ++p)
*(p - 1) = *p;
L.length--;
return OK;
}
void ListTraverse(Sqlist &L, void(*visit)(ElemType&))
{
ElemType *p = L.elem;
int i;
for (i = 1; i <= L.length; i++)
visit(*p++);
printf("\n");
}
实现文件2:func2-2.cpp
#include"C1.H"
Status equal(ElemType c1, ElemType c2)
{
if (c1 == c2)
return TRUE;
else
return FALSE;
}
int comp(ElemType a, ElemType b)
{
if (a == b)
return 0;
else
return (a - b) / abs(a - b);
}
void print(ElemType c)
{
printf("%d", c);
}
void print1(ElemType &c)
{
printf("%d ", c);
}
void print2(ElemType c)
{
printf("%c", c);
}
主函数
#include "C1.H"
Status sq(ElemType c1, ElemType c2)
{
if (c1 == c2 * c2)
return TRUE;
else
return FALSE;
}
void dbl(ElemType &c)
{
c *= 2;
}
int main()
{
Sqlist L;
ElemType e, e0;
Status i;
int j, k;
InitList(L);
printf("初始化L后,L.length = %d,L.listsize = %d,L.elem = %u\n", L.length, L.listsize, L.elem);
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调用ListTraverse()函数,依次输出表L中的元素:");
ListTraverse(L, print1);
i = ListEmpty(L);
printf("L.length = %d,L.listsize = %d,", L.length, L.listsize);
printf("L.elem = %u,L是否为空?i = %d\n\n", L.elem, i);
ClearList(L);
i = ListEmpty(L);
printf("L.length = %d,L.listsize = %d,", L.length, L.listsize);
printf("L.elem = %u,L是否为空?i = %d,", L.elem, i);
for (j = 1; j <= 10; j++)
ListInsert(L, j, j);
printf("在标为插入1-10之后,L = ");
ListTraverse(L, print1);
printf("L.length = %d,L.listsize = %d,L.elem = %u\n", L.length, L.listsize, L.elem);
ListInsert(L, 1, 0);
printf("在L的表头插入0后,L.length = %d,L.listsize = %d,L.elem = %u\n ", L.length, L.listsize, L.elem);
GetElem(L, 5, e);
ListTraverse(L, print1);
printf("第5个元素值为 %d ", e);
for (j = 10; j <= 11; j++)
{
k = LocateElem(L, j, equal);
if (k)
printf("第 %d 个元素的值为 %d\n", k, j);
else
printf("没有值为 %d 的元素\n", j);
}
for (j = 3; j <= 4; j++)
{
k = LocateElem(L, j, sq);
if (k)
printf("第 %d 个元素的值为 %d 的平方\n", k, j);
else
printf("没有值为 %d 的平方的元素\n", j);
}
for (j = 1; j <= 2; j++)
{
GetElem(L, j, e0);
i = PriorElem(L, e0, e);
if (i == ERROR)
printf("元素%d无前驱\n", e0);
else
printf("元素%d的前驱为%d\n", e0, e);
}
for (j = ListLength(L) - 1; j <= ListLength(L); j++)
{
GetElem(L, j, e0);
i = NextElem(L, e0, e);
if (i == ERROR)
printf("元素%d无后继\n", e0);
else
printf("元素%d的后继为%d\n", e0, e);
}
k = ListLength(L);
for ( j = k+1; j >= k; j--)
{
i = ListDelete(L, j, e);
if (i == ERROR)
printf("%d个元素删除失败\n", j);
else
printf("%d个元素删除成功,值为%d\n", j, e);
}
ListTraverse(L,dbl);
printf("L的元素加倍后L = ");
ListTraverse(L, print1);
DestoryList(L);
printf("销毁L后,L.length = %d,L.listsize = %d,L.elem = %u\n", L.length, L.listsize, L.elem);
return 0;
}
2.2.2换一种写法
头文件c1.h
// c1.h (文件名)
#ifndef C1_H
#define C1_H
#define LIST_INIT_SIZE 10
#define LIST_INCREMENT 2
#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(),exit()
#include<io.h> // eof()
#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等
#include<sys/timeb.h> // ftime()
#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表
// 函数结果状态代码。在教科书第10页
#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,第7、8章用到
typedef int ElemType;
struct LNode
{
ElemType data;
LNode *next;
};
typedef LNode *LinkList;
void InitList(LinkList &L);
void DestoryList(LinkList &L);
void 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);
void ListTraverse(LinkList &L, void(*visit)(ElemType));
Status equal(ElemType c1, ElemType c2);
int comp(ElemType a, ElemType b);
void print(ElemType c);
#endif
实现文件1func2-2.cpp
// func2-2.cpp 几个常用的函数
#include"C1.H"
Status equal(ElemType c1,ElemType c2)
{ // 判断是否相等的函数
if(c1==c2)
return TRUE;
else
return FALSE;
}
int comp(ElemType a,ElemType b)
{ // 根据a<、=或>b,分别返回-1、0或1
if(a==b)
return 0;
else
return (a-b)/abs(a-b);
}
void print(ElemType c)
{ // 以十进制整型的格式输出元素的值
printf("%d ",c);
}
void print1(ElemType &c)
{ // 以十进制整型的格式输出元素的值(设c为引用类型)
printf("%d ",c);
}
void print2(ElemType c)
{ // 以字符型的格式输出元素的值
printf("%c ",c);
}
实现文件2:bo2-2.cpp
#include"C1.H"
void InitList(LinkList &L)
{
L = (LNode*)malloc(sizeof(LNode));
if (!L)
exit(OVERFLOW);
L->next = NULL;
}
void DestoryList(LinkList &L)
{
LinkList q;
while (L)
{
q = L->next;
free(L);
L = q;
}
}
void ClearList(LinkList &L)
{
LinkList p = L->next;
L->next = NULL;
DestoryList(p);
}
Status ListEmpty(LinkList L)
{
if (L->next)
return FALSE;
else
return TRUE;
}
int ListLength(LinkList L)
{
int i = 0;
LinkList q = L->next;
while (q)
{
i++;
q = q->next;
}
return i;
}
Status GetElem(LinkList L, int i, ElemType &e)
{
int j = 1;
LinkList q = L->next;
while (q && j < i)
{
j++;
q = q->next;
}
if (!q || j > i)
return ERROR;
e = q->data;
return OK;
}
int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{
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)
{
LinkList q, p = L->next;
while (p->next)
{
q = p->next;
if (q->data == cur_e)
{
pre_e = p->data;
return OK;
}
p = q;
}
return ERROR;
}
Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e)
{
LinkList p = L->next;
while (p->next)
{
if (p->data == cur_e)
{
next_e = p->next->data;
return OK;
}
p = p->next;
}
return ERROR;
}
Status ListInsert(LinkList &L, int i, ElemType e)
{
int j = 0;
LinkList s, p = L;
while (p &&j < i - 1)
{
j++;
p = p->next;
}
if (!p || j > i - 1)
return ERROR;
s = (LinkList)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
Status ListDelete(LinkList &L, int i, ElemType &e)
{
int j = 0;
LinkList q, p = L;
while (p->next&&j < i - 1)
{
j++;
p = p->next;
}
if (!p->next || j > i - 1)
return ERROR;
q = p->next;
p->next = q->next;
e = q->data;
free(q);
return OK;
}
void ListTraverse(LinkList &L, void(*visit)(ElemType))
{
LinkList p = L->next;
while (p)
{
visit(p->data);
p = p->next;
}
printf("\n");
}
主函数
// algo2-3.cpp 实现算法2.11和2.12的程序
#include"c1.h"
void CreateList(LinkList &L,int n) // 算法2.11
{ // 逆位序(结点插在表头)输入n个元素的值,建立带表头结点的单链线性表L
int i;
LinkList p;
L=(LinkList)malloc(sizeof(LNode)); // 生成头结点
L->next=NULL; // 先建立一个带头结点的空单链表
printf("请输入%d个数据\n",n);
for(i=n;i>0;--i)
{ p=(LinkList)malloc(sizeof(LNode)); // 生成新结点
scanf("%d",&p->data); // 给新结点输入元素值
p->next=L->next; // 将新结点插在表头
L->next=p; // 头结点指向新结点
}
}
void CreateList1(LinkList &L,int n)
{ // 正位序(结点插在表尾)输入n个元素的值,建立带表头结点的单链线性表L
int i;
LinkList p,q;
L=(LinkList)malloc(sizeof(LNode)); // 生成头结点
L->next=NULL; // 先建立一个带头结点的空单链表
q=L; // q指向空表的头结点(相当于尾结点)
printf("请输入%d个数据\n",n);
for(i=1;i<=n;i++)
{ p=(LinkList)malloc(sizeof(LNode)); // 生成新结点
scanf("%d",&p->data); // 给新结点输入元素值
q->next=p; // 将新结点插在表尾
q=q->next; // q指向尾结点
}
p->next=NULL; // 最后一个结点的指针域为空
}
void MergeList(LinkList La,LinkList &Lb,LinkList &Lc) // 算法2.12
{ // 已知单链线性表La和Lb的元素按值非递减排列。
// 归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列。(销毁Lb,Lc即新的La)
LinkList pa=La->next,pb=Lb->next,pc; // pa、pb分别指向La、Lb的首元结点(待比较结点)
Lc=pc=La; // 用La的头结点作为Lc的头结点,pc指向La的头结点(Lc的尾结点)
while(pa&&pb) // La和Lb中的元素都未比较完
if(pa->data<=pb->data) // La的当前元素不大于Lb的当前元素
{ pc->next=pa; // 将pa所指结点归并到Lc中
pc=pa; // pc指向表Lc的最后一个结点
pa=pa->next; // 表La的下一个结点成为待比较结点
}
else // Lb的当前元素小于La的当前元素
{ pc->next=pb; // 将pb所指结点归并到Lc中
pc=pb; // pc指向表Lc的最后一个结点
pb=pb->next; // 表Lb的下一个结点成为待比较结点
}
pc->next=pa?pa:pb; // 插入剩余段
free(Lb); // 释放Lb的头结点
Lb=NULL; // Lb不再指向任何结点
}
void main()
{
int n=5;
LinkList La,Lb,Lc;
printf("按非递减顺序,");
CreateList1(La,n); // 根据输入顺序,正位序建立线性表
printf("La=");
ListTraverse(La,print); // 输出链表La的内容
printf("按非递增顺序,");
CreateList(Lb,n); // 根据输入顺序,逆位序建立线性表
printf("Lb=");
ListTraverse(Lb,print); // 输出链表Lb的内容
MergeList(La,Lb,Lc); // 按非递减顺序归并La和Lb,得到新表Lc
printf("Lc=");
ListTraverse(Lc,print); // 输出链表Lc的内容
}
2.2.3归并
头文件
// c1.h (文件名)
#ifndef C1_H
#define C1_H
#define LIST_INIT_SIZE 10
#define LIST_INCREMENT 2
#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(),exit()
#include<io.h> // eof()
#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等
#include<sys/timeb.h> // ftime()
#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表
// 函数结果状态代码。在教科书第10页
#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,第7、8章用到
typedef int ElemType;
struct Sqlist
{
ElemType *elem;
int length;
int listsize;
};
void InitList(Sqlist &L);
void DestoryList(Sqlist &L);
void ClearList(Sqlist &L);
Status ListEmpty(Sqlist L);
int ListLength(Sqlist L);
Status GetElem(Sqlist L, int i, ElemType &e);
int LocateElem(Sqlist L, ElemType e, Status(*compare)(ElemType, ElemType));
//寻找前一个节点
Status PriorElem(Sqlist L, ElemType cur_e, ElemType &pre_e);
//寻找后一个结点
Status NextElem(Sqlist L, ElemType cur_e, ElemType &next_e);
Status ListInsert(Sqlist &L, int i, ElemType e);
Status ListDelete(Sqlist &L, int i, ElemType &e);
void ListTraverse(Sqlist &L, void(*visit)(ElemType&));
Status equal(ElemType c1, ElemType c2);
int comp(ElemType a, ElemType b);
void print(ElemType c);
void print1(ElemType &c);
void print2(ElemType c);
#endif
bo2-1.cpp
#pragma once
#include"C1.H"
void InitList(Sqlist &L)
{
L.elem = (ElemType*)malloc(sizeof(ElemType) * LIST_INIT_SIZE);
if (!L.elem)
exit(OVERFLOW);
L.length = 0;
L.listsize = LIST_INIT_SIZE;
}
void DestoryList(Sqlist &L)
{
free(L.elem);
L.elem = NULL;
L.length = 0;
L.listsize = 0;
}
void ClearList(Sqlist &L)
{
L.length = 0;
}
Status ListEmpty(Sqlist L)
{
if (L.length == 0)
return TRUE;
else
return FALSE;
}
int ListLength(Sqlist L)
{
return L.length;
}
Status GetElem(Sqlist L, int i, ElemType &e)
{
if (i<1 || i>L.length)
return ERROR;
e = *(L.elem + i - 1);
return OK;
}
int LocateElem(Sqlist L, ElemType e, Status(*compare)(ElemType, ElemType))
{
int i = 1;
ElemType *p = L.elem;
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)
{
int i = 1;
ElemType *p = L.elem + 1;
while (i <= L.length &&*p != cur_e)
{
p++;
i++;
}
if (i > L.length)
return ERROR;
else
{
pre_e = *--p;
return OK;
}
}
//寻找后一个结点
Status NextElem(Sqlist L, ElemType cur_e, ElemType &next_e)
{
int i = 1;
ElemType *p = L.elem;
while (i < L.length && *p != cur_e)
{
p++;
i++;
}
if (i == L.length)
return ERROR;
else
{
next_e = *++p;
return OK;
}
}
Status ListInsert(Sqlist &L, int i, ElemType e)
{
ElemType *newbase, *p, *q;
if (i < 1 || i >L.length + 1)
return ERROR;
if (L.length == L.listsize)
{
newbase = (ElemType*)realloc(L.elem, (L.listsize + LIST_INCREMENT) * sizeof(ElemType));
if (!newbase)
exit(OVERFLOW);
L.elem = newbase;
L.listsize += LIST_INCREMENT;
}
q = L.elem + i - 1;
for (p = L.elem + L.length - 1; p >= q; --p)
*(p + 1) = *p;
*q = e;
++L.length;
return OK;
}
Status ListDelete(Sqlist &L, int i, ElemType &e)
{
ElemType *p, *q;
if (i<1 || i>L.length)
return ERROR;
p = L.elem + i - 1;
e = *p;
q = L.elem + L.length - 1;
for (++p; p <= q; ++p)
*(p - 1) = *p;
L.length--;
return OK;
}
void ListTraverse(Sqlist &L, void(*visit)(ElemType&))
{
ElemType *p = L.elem;
int i;
for (i = 1; i <= L.length; i++)
visit(*p++);
printf("\n");
}
fun2-2.cpp
#include"C1.H"
Status equal(ElemType c1, ElemType c2)
{
if (c1 == c2)
return TRUE;
else
return FALSE;
}
int comp(ElemType a, ElemType b)
{
if (a == b)
return 0;
else
return (a - b) / abs(a - b);
}
void print(ElemType c)
{
printf("%d", c);
}
void print1(ElemType &c)
{
printf("%d ", c);
}
void print2(ElemType c)
{
printf("%c", c);
}
主函数实现
#include"C1.H"
void MergeList(Sqlist La, Sqlist Lb, Sqlist &Lc)
{
ElemType *pa, *pa_last, *pb, *pb_last, *pc;
pa = La.elem;
pb = Lb.elem;
Lc.length = Lc.listsize = La.length + Lb.length;
pc = Lc.elem = (ElemType*)malloc(sizeof(ElemType) * Lc.length);
if (!Lc.elem)
exit(OVERFLOW);
pa_last = pa + La.length - 1;
pb_last = pb + Lb.length - 1;
while (pa <= pa_last&&pb <= pb_last)
{
if (*pa <= *pb)
*pc++ = *pa++;
else
*pc++ = *pb++;
}
while (pa <= pa_last)
*pc++ = *pa++;
while (pb <= pb_last)
*pc++ = *pb++;
}
int main() {
Sqlist La, Lb, Lc;
int j;
InitList(La);
InitList(Lb);
for (j = 1; j <= 5; j++)
ListInsert(La, j, j);
ListTraverse(La, print1);
for (j = 1; j <= 5; j++)
ListInsert(Lb, j, 2*j);
ListTraverse(Lb, print1);
MergeList(La, Lb, Lc);
ListTraverse(Lc, print1);
return 0;
}
2.3.1线性表的链式表示和实现
头文件
// c1.h (文件名)
#ifndef C1_H
#define C1_H
#define LIST_INIT_SIZE 10
#define LIST_INCREMENT 2
#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(),exit()
#include<io.h> // eof()
#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等
#include<sys/timeb.h> // ftime()
#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表
// 函数结果状态代码。在教科书第10页
#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,第7、8章用到
typedef int ElemType;
struct LNode
{
ElemType data;
LNode *next;
};
typedef LNode *LinkList;
void InitList(LinkList &L);
void DestoryList(LinkList &L);
void 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);
void ListTraverse(LinkList &L, void(*visit)(ElemType));
Status equal(ElemType c1, ElemType c2);
int comp(ElemType a, ElemType b);
void print(ElemType c);
void print1(ElemType c);
void print2(ElemType c);
#endif
实现函数:
#include"C1.H"
void InitList(LinkList &L)
{
L = (LNode*)malloc(sizeof(LNode));
if (!L)
exit(OVERFLOW);
L->next = NULL;
}
void DestoryList(LinkList &L)
{
LinkList q;
while (L)
{
q = L->next;
free(L);
L = q;
}
}
void ClearList(LinkList &L)
{
LinkList p = L->next;
L->next = NULL;
DestoryList(p);
}
Status ListEmpty(LinkList L)
{
if (L->next)
return FALSE;
else
return TRUE;
}
int ListLength(LinkList L)
{
int i = 0;
LinkList q = L->next;
while (q)
{
i++;
q = q->next;
}
return i;
}
Status GetElem(LinkList L, int i, ElemType &e)
{
int j = 1;
LinkList q = L->next;
while (q && j < i)
{
j++;
q = q->next;
}
if (!q || j > i)
return ERROR;
e = q->data;
return OK;
}
int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{
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)
{
LinkList q, p = L->next;
while (p->next)
{
q = p->next;
if (q->data == cur_e)
{
pre_e = p->data;
return OK;
}
p = q;
}
return ERROR;
}
Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e)
{
LinkList p = L->next;
while (p->next)
{
if (p->data == cur_e)
{
next_e = p->next->data;
return OK;
}
p = p->next;
}
return ERROR;
}
Status ListInsert(LinkList &L, int i, ElemType e)
{
int j = 0;
LinkList s, p = L;
while (p &&j < i - 1)
{
j++;
p = p->next;
}
if (!p || j > i - 1)
return ERROR;
s = (LinkList)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
Status ListDelete(LinkList &L, int i, ElemType &e)
{
int j = 0;
LinkList q, p = L;
while (p->next&&j < i - 1)
{
j++;
p = p->next;
}
if (!p->next || j > i - 1)
return ERROR;
q = p->next;
p->next = q->next;
e = q->data;
free(q);
return OK;
}
void ListTraverse(LinkList &L, void(*visit)(ElemType))
{
LinkList p = L->next;
while (p)
{
visit(p->data);
p = p->next;
}
printf("\n");
}
void print(ElemType c)
{
printf("%d", c);
}
主函数
#include "C1.H"
int main()
{
LinkList L;
ElemType e, e0;
Status i;
int j, k;
InitList(L);
for (j = 1; j <= 5; j++)
i = ListInsert(L, 1, j);
printf("在L的表头一次插入1-5后,L = ");
ListTraverse(L, print);
i = ListEmpty(L);
printf("L是否空?i = %d(1是0否),表L的长度 = %d\n", i, ListLength(L));
ClearList(L);
printf("清空L之后,L = ");
ListTraverse(L, print);
i = ListEmpty(L);
printf("L是否空?i = %d(1是0否),表L的长度 = %d\n", i, ListLength(L));
for (j = 1; j <= 10; j++)
i = ListInsert(L, j, j);
for (j = 1; j <= 2; j++)
{
GetElem(L, j, e0);
i = PriorElem(L, e0, e);
if (i == ERROR)
printf("元素%d无前驱\n", e0);
else
printf("元素%d的前驱为%d\n", e0, e);
}
for (j = ListLength(L) - 1; j <= ListLength(L); j++)
{
GetElem(L, j, e0);
i = NextElem(L, e0, e);
if (i == ERROR)
printf("元素%d无后继\n", e0);
else
printf("元素%d的后继为%d\n", e0, e);
}
k = ListLength(L);
for (j = k + 1; j >= k; j--)
{
i = ListDelete(L, j, e);
if (i == ERROR)
printf("%d个元素删除失败\n", j);
else
printf("%d个元素删除成功,值为%d\n", j, e);
}
printf("依次输出L的元素:");
ListTraverse(L, print);
DestoryList(L);
printf("销毁后,L = %u", L);
}
2.3.2 不设头节点
头文件
// c1.h (文件名)
#ifndef C1_H
#define C1_H
#define LIST_INIT_SIZE 10
#define LIST_INCREMENT 2
#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(),exit()
#include<io.h> // eof()
#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等
#include<sys/timeb.h> // ftime()
#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表
// 函数结果状态代码。在教科书第10页
#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,第7、8章用到
typedef int ElemType;
struct LNode
{
ElemType data;
LNode *next;
};
typedef LNode *LinkList;
void InitList(LinkList &L);
void DestoryList(LinkList &L);
void 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);
void ListTraverse(LinkList &L, void(*visit)(ElemType));
Status equal(ElemType c1, ElemType c2);
int comp(ElemType a, ElemType b);
void print(ElemType c);
void Union(LinkList &La, LinkList Lb);
void MergeList(LinkList La, LinkList Lb, LinkList &Lc);
#endif
// bo2-3.cpp 不设头结点的单链表(存储结构由c2-2.h定义)的部分基本操作(9个)
#include"C1.h"
#define DestroyList ClearList // DestroyList()和ClearList()的操作是一样的
void InitList(LinkList &L)
{ // 操作结果:构造一个空的线性表L
L = NULL; // 指针为空
}
void ClearList(LinkList &L)
{ // 初始条件:线性表L已存在。操作结果:将L重置为空表
LinkList p;
while (L) // L不空
{
p = L; // p指向首元结点
L = L->next; // L指向第2个结点(新首元结点)
free(p); // 释放首元结点
}
}
Status ListEmpty(LinkList L)
{ // 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE
if (L)
return FALSE;
else
return TRUE;
}
int ListLength(LinkList L)
{ // 初始条件:线性表L已存在。操作结果:返回L中数据元素的个数
int i = 0; // 计数器初值为0
LinkList p = L; // p指向第1个结点
while (p) // p指向结点(未到表尾)
{
i++; // 计数器+1
p = p->next; // p指向下一个结点
}
return i;
}
Status GetElem(LinkList L, int i, ElemType &e)
{ // L为不设头结点的单链表的头指针。当第i个元素存在时,其值赋给e并返回OK,
// 否则返回ERROR
int j = 1; // 计数器初值为1
LinkList p = L; // p指向第1个结点
if (i<1) // i值不合法
return ERROR;
while (j<i&&p) // 未到第i个元素,也未到表尾
{
j++; // 计数器+1
p = p->next; // p指向下一个结点
}
if (j == i&&p) // 存在第i个元素
{
e = p->data; // 取第i个元素的值赋给e
return OK; // 成功返回OK
}
return ERROR; // 不存在第i个元素,失败返回ERROR
}
int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{ // 初始条件:线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0)
// 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。
// 若这样的数据元素不存在,则返回值为0
int i = 0; // 计数器初值为0
LinkList p = L; // p指向第1个结点
while (p) // 未到表尾
{
i++; // 计数器+1
if (compare(p->data, e)) // 找到这样的数据元素
return i; // 返回其位序
p = p->next; // p指向下一个结点
}
return 0; // 满足关系的数据元素不存在
}
Status ListInsert(LinkList &L, int i, ElemType e)
{ // 在不设头结点的单链线性表L中第i个位置之前插入元素e
int j = 1; // 计数器初值为1
LinkList s, p = L; // p指向第1个结点
if (i<1) // i值不合法
return ERROR;
s = (LinkList)malloc(sizeof(LNode)); // 生成新结点,以下将其插入L中
s->data = e; // 给s的data域赋值e
if (i == 1) // 插在表头
{
s->next = L; // 新结点指向原第1个结点
L = s; // L指向新结点(改变L)
}
else
{ // 插在表的其余处
while (p&&j<i - 1) // 寻找第i-1个结点
{
j++; // 计数器+1
p = p->next; // p指向下一个结点
}
if (!p) // i大于表长+1
return ERROR; // 插入失败
s->next = p->next; // 新结点指向原第i个结点
p->next = s; // 原第i-1个结点指向新结点
}
return OK; // 插入成功
}
Status ListDelete(LinkList &L, int i, ElemType &e)
{ // 在不设头结点的单链线性表L中,删除第i个元素,并由e返回其值
int j = 1; // 计数器初值为1
LinkList q, p = L; // p指向第1个结点
if (!L) // 表L空
return ERROR; // 删除失败
else if (i == 1) // 删除第1个结点
{
L = p->next; // L由第2个结点开始(改变L)
e = p->data; // 将待删结点的值赋给e
free(p); // 删除并释放第1个结点
}
else
{
while (p->next&&j<i - 1) // 寻找第i个结点,并令p指向其前驱
{
j++; // 计数器+1
p = p->next; // p指向下一个结点
}
if (!p->next || j>i - 1) // 删除位置不合理
return ERROR; // 删除失败
q = p->next; // q指向待删除结点
p->next = q->next; // 待删结点的前驱指向待删结点的后继
e = q->data; // 将待删结点的值赋给e
free(q); // 释放待删结点
}
return OK; // 删除成功
}
void ListTraverse(LinkList L, void(*vi)(ElemType))
{ // 初始条件:线性表L已存在。操作结果:依次对L的每个数据元素调用函数vi()
LinkList p = L; // p指向第1个结点
while (p) // p所指结点存在
{
vi(p->data); // 对p所指结点调用函数vi()
p = p->next; // p指向下一个结点
}
printf("\n");
}
// bo2-4.cpp 不设头结点的单链表(存储结构由c2-2.h定义)的部分基本操作(2个)
#include"C1.h"
Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e)
{ // 初始条件:线性表L已存在
// 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,返回OK;
// 否则操作失败,pre_e无定义,返回ERROR
LinkList q, p = L; // p指向第1个结点
while (p->next) // p所指结点有后继
{
q = p->next; // q指向p的后继
if (q->data == cur_e) // p的后继为cur_e
{
pre_e = p->data; // 将p所指元素的值赋给pre_e
return OK; // 成功返回OK
}
p = q; // p的后继不为cur_e,p向后移
}
return ERROR; // 操作失败,返回ERROR
}
Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e)
{ // 初始条件:线性表L已存在
// 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,返回OK,
// 否则操作失败,next_e无定义,返回ERROR
LinkList p = L; // p指向第1个结点
while (p->next) // p所指结点有后继
{
if (p->data == cur_e) // p所指结点的值为cur_e
{
next_e = p->next->data; // 将p所指结点的后继结点的值赋给next_e
return OK; // 成功返回OK
}
p = p->next; // p指向下一个结点
}
return ERROR; // 操作失败,返回ERROR
}
// func2-2.cpp 几个常用的函数
#include"C1.H"
Status equal(ElemType c1, ElemType c2)
{ // 判断是否相等的函数
if (c1 == c2)
return TRUE;
else
return FALSE;
}
int comp(ElemType a, ElemType b)
{ // 根据a<、=或>b,分别返回-1、0或1
if (a == b)
return 0;
else
return (a - b) / abs(a - b);
}
void print(ElemType c)
{ // 以十进制整型的格式输出元素的值
printf("%d ", c);
}
void print1(ElemType &c)
{ // 以十进制整型的格式输出元素的值(设c为引用类型)
printf("%d ", c);
}
void print2(ElemType c)
{ // 以字符型的格式输出元素的值
printf("%c ", c);
}
#include "C1.H"
int main()
{
LinkList La, Lb, Lc;
int j, b[7] = { 2,6,8,9,11,15,20 };
InitList(La);
for (j = 1; j <= 5; j++)
ListInsert(La, j, j);
ListTraverse(La, print);
InitList(Lb);
for (j = 1; j <= 5; j++)
ListInsert(Lb, j, 2 * j);
ListTraverse(Lb, print);
Union(La, Lb);
ListTraverse(La, print);
ClearList(Lb);
for (j = 1; j <= 7; j++)
ListInsert(Lb, j, b[j - 1]);
ListTraverse(Lb, print);
MergeList(La, Lb, Lc);
ListTraverse(Lc, print);
}
2.3.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(),exit()
#include<io.h> // eof()
#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等
#include<sys/timeb.h> // ftime()
#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表
// 函数结果状态代码。在教科书第10页
#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,第7、8章用到
#include "C1.H"
#define MAX_SIZE 100
#define N 6
typedef char ElemType[N];
typedef struct {
ElemType data;
int cur;
}component,SLinkList[MAX_SIZE];
int main()
{
SLinkList s = { {"",1},{"ZHAO",2},{"QIAN",3},{"SUN",4},{"LI",5} ,{"ZHOU",6}, {"WU",7}, {"ZHENG",8}, {"WANG",0} };
int i = s[0].cur;
while (i)
{
printf("%s ", s[i].data);
i = s[i].cur;
}
printf("\n");
s[4].cur = 9;
s[9].cur = 5;
strcpy(s[9].data, "SHI");
s[6].cur = 8;
i = s[0].cur;
while (i)
{
printf("%s ", s[i].data);
i = s[i].cur;
}
printf("\n");
return 0;
}
2.3.4链表归并
// c1.h (文件名)
#ifndef C1_H
#define C1_H
#define LIST_INIT_SIZE 10
#define LIST_INCREMENT 2
#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(),exit()
#include<io.h> // eof()
#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等
#include<sys/timeb.h> // ftime()
#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表
// 函数结果状态代码。在教科书第10页
#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,第7、8章用到
typedef int ElemType;
struct LNode
{
ElemType data;
LNode *next;
};
typedef LNode *LinkList;
void InitList(LinkList &L);
void DestoryList(LinkList &L);
void 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);
void ListTraverse(LinkList &L, void(*visit)(ElemType));
Status equal(ElemType c1, ElemType c2);
int comp(ElemType a, ElemType b);
void print(ElemType c);
void Union(LinkList &La, LinkList Lb);
void MergeList(LinkList La, LinkList Lb, LinkList &Lc);
#endif
#include"C1.H"
void InitList(LinkList &L)
{
L = (LNode*)malloc(sizeof(LNode));
if (!L)
exit(OVERFLOW);
L->next = NULL;
}
void DestoryList(LinkList &L)
{
LinkList q;
while (L)
{
q = L->next;
free(L);
L = q;
}
}
void ClearList(LinkList &L)
{
LinkList p = L->next;
L->next = NULL;
DestoryList(p);
}
Status ListEmpty(LinkList L)
{
if (L->next)
return FALSE;
else
return TRUE;
}
int ListLength(LinkList L)
{
int i = 0;
LinkList q = L->next;
while (q)
{
i++;
q = q->next;
}
return i;
}
Status GetElem(LinkList L, int i, ElemType &e)
{
int j = 1;
LinkList q = L->next;
while (q && j < i)
{
j++;
q = q->next;
}
if (!q || j > i)
return ERROR;
e = q->data;
return OK;
}
int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{
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)
{
LinkList q, p = L->next;
while (p->next)
{
q = p->next;
if (q->data == cur_e)
{
pre_e = p->data;
return OK;
}
p = q;
}
return ERROR;
}
Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e)
{
LinkList p = L->next;
while (p->next)
{
if (p->data == cur_e)
{
next_e = p->next->data;
return OK;
}
p = p->next;
}
return ERROR;
}
Status ListInsert(LinkList &L, int i, ElemType e)
{
int j = 0;
LinkList s, p = L;
while (p &&j < i - 1)
{
j++;
p = p->next;
}
if (!p || j > i - 1)
return ERROR;
s = (LinkList)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
Status ListDelete(LinkList &L, int i, ElemType &e)
{
int j = 0;
LinkList q, p = L;
while (p->next&&j < i - 1)
{
j++;
p = p->next;
}
if (!p->next || j > i - 1)
return ERROR;
q = p->next;
p->next = q->next;
e = q->data;
free(q);
return OK;
}
void ListTraverse(LinkList &L, void(*visit)(ElemType))
{
LinkList p = L->next;
while (p)
{
visit(p->data);
p = p->next;
}
printf("\n");
}
// func2-2.cpp 几个常用的函数
#include"C1.H"
Status equal(ElemType c1, ElemType c2)
{ // 判断是否相等的函数
if (c1 == c2)
return TRUE;
else
return FALSE;
}
int comp(ElemType a, ElemType b)
{ // 根据a<、=或>b,分别返回-1、0或1
if (a == b)
return 0;
else
return (a - b) / abs(a - b);
}
void print(ElemType c)
{ // 以十进制整型的格式输出元素的值
printf("%d ", c);
}
void print1(ElemType &c)
{ // 以十进制整型的格式输出元素的值(设c为引用类型)
printf("%d ", c);
}
void print2(ElemType c)
{ // 以字符型的格式输出元素的值
printf("%c ", c);
}
#include "C1.H"
void Union(LinkList &La, LinkList Lb)
{
ElemType e;
int La_len, Lb_len;
int i;
La_len = ListLength(La); // 求线性表La的长度
Lb_len = ListLength(Lb); // 求线性表Lb的长度
for (i = 1; i <= Lb_len; i++) // 从表Lb的第1个元素到最后1个元素
{
GetElem(Lb, i, e); // 取表Lb中第i个数据元素的值赋给e
if (!LocateElem(La, e, equal)) // 表La中不存在和e相同的元素
ListInsert(La, ++La_len, e); // 在表La的最后插入元素e
}
}
void MergeList(LinkList La, LinkList Lb, LinkList &Lc)
{
int i = 1, j = 1, k = 0;
int La_len, Lb_len;
ElemType ai, bj;
InitList(Lc);
La_len = ListLength(La);
Lb_len = ListLength(Lb);
while (i <= La_len&&j <= Lb_len)
{
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)
{
GetElem(La, i++, ai);
ListInsert(Lc, ++k, ai);
}
while (j <= Lb_len)
{
GetElem(La, j++, bj);
ListInsert(Lc, ++k, bj);
}
}
#include "C1.H"
int main()
{
LinkList La, Lb, Lc;
int j, b[7] = { 2,6,8,9,11,15,20 };
InitList(La);
for (j = 1; j <= 5; j++)
ListInsert(La, j, j);
ListTraverse(La, print);
InitList(Lb);
for (j = 1; j <= 5; j++)
ListInsert(Lb, j, 2*j);
ListTraverse(Lb, print);
Union(La, Lb);
ListTraverse(La,print);
ClearList(Lb);
for (j = 1; j <= 7; j++)
ListInsert(Lb, j, b[j - 1]);
ListTraverse(Lb, print);
MergeList(La, Lb, Lc);
ListTraverse(Lc, print);
}
2.3.5循环链表
// c1.h (文件名)
#ifndef C1_H
#define C1_H
#define LIST_INIT_SIZE 10
#define LIST_INCREMENT 2
#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(),exit()
#include<io.h> // eof()
#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等
#include<sys/timeb.h> // ftime()
#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表
// 函数结果状态代码。在教科书第10页
#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,第7、8章用到
typedef int ElemType;
struct LNode
{
ElemType data;
LNode *next;
};
typedef LNode *LinkList;
void InitList(LinkList &L);
void DestoryList(LinkList &L);
void 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);
void ListTraverse(LinkList &L, void(*visit)(ElemType));
Status equal(ElemType c1, ElemType c2);
int comp(ElemType a, ElemType b);
void print(ElemType c);
void print1(ElemType c);
void print2(ElemType c);
#endif
#include"C1.H"
void InitList(LinkList &L)
{
L = (LNode*)malloc(sizeof(LNode));
if (!L)
exit(OVERFLOW);
L->next = L;
}
void ClearList(LinkList &L)
{
LinkList p,q;
L = L->next;
p = L->next;
while (p != L)
{
q = p->next;
free(p);
p = q;
}
L->next = L;
}
void DestoryList(LinkList &L)
{
ClearList(L);
free(L);
L = NULL;
}
Status ListEmpty(LinkList L)
{
if (L->next == L)
return TRUE;
else
return FALSE;
}
int ListLength(LinkList L)
{
int i = 0;
LinkList q = L->next;
while (q != L)
{
i++;
q = q->next;
}
return i;
}
Status GetElem(LinkList L, int i, ElemType &e)
{
int j = 1;
LinkList p = L->next->next;
if (i <= 0 || i > ListLength(L))
return ERROR;
while (j<i)
{
j++;
p = p->next;
}
e = p->data;
return OK;
}
int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{
int i = 0;
LinkList p = L->next ->next;
while (p!=L->next)
{
i++;
if (compare(p->data, e))
return i;
p = p->next;
}
return 0;
}
Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e)
{
LinkList q, p = L->next->next;
q = p->next;
while (q != L->next)
{
if (q->data == cur_e)
{
pre_e = p->data;
return OK;
}
p = q;
q = q->next;
}
return ERROR;
}
Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e)
{
LinkList p = L->next->next;
while (p!=L)
{
if (p->data == cur_e)
{
next_e = p->next->data;
return OK;
}
p = p->next;
}
return ERROR;
}
Status ListInsert(LinkList &L, int i, ElemType e)
{
int j = 0;
LinkList s, p = L->next;
if (i <= 0 || i > ListLength(L) +1)
return ERROR;
while (j < i - 1)
{
j++;
p = p->next;
}
s = (LinkList)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
if (p == L)
L = s;
return OK;
}
Status ListDelete(LinkList &L, int i, ElemType &e)
{
int j = 0;
LinkList q, p = L->next;
if (i <= 0 || i > ListLength(L))
return ERROR;
while (j < i - 1)
{
j++;
p = p->next;
}
q = p->next;
p->next = q->next;
e = q->data;
if (L == q)
L = p;
free(q);
return OK;
}
void ListTraverse(LinkList &L, void(*visit)(ElemType))
{
LinkList p = L->next->next;
while (p!=L->next)
{
visit(p->data);
p = p->next;
}
printf("\n");
}
void print(ElemType c)
{
printf("%d", c);
}
#include "C1.H"
int main()
{
LinkList L;
ElemType e, e0;
Status i;
int j, k;
InitList(L);
for (j = 1; j <= 5; j++)
i = ListInsert(L, 1, j);
printf("在L的表头一次插入1-5后,L = ");
ListTraverse(L, print);
i = ListEmpty(L);
printf("L是否空?i = %d(1是0否),表L的长度 = %d\n", i, ListLength(L));
ClearList(L);
printf("清空L之后,L = ");
ListTraverse(L, print);
i = ListEmpty(L);
printf("L是否空?i = %d(1是0否),表L的长度 = %d\n", i, ListLength(L));
for (j = 1; j <= 10; j++)
i = ListInsert(L, j, j);
ListTraverse(L, print);
for (j = 1; j <= 2; j++)
{
GetElem(L, j, e0);
i = PriorElem(L, e0, e);
if (i == ERROR)
printf("元素%d无前驱\n", e0);
else
printf("元素%d的前驱为%d\n", e0, e);
}
for (j = ListLength(L) - 1; j <= ListLength(L); j++)
{
GetElem(L, j, e0);
i = NextElem(L, e0, e);
if (i == ERROR)
printf("元素%d无后继\n", e0);
else
printf("元素%d的后继为%d\n", e0, e);
}
k = ListLength(L);
for (j = k + 1; j >= k; j--)
{
i = ListDelete(L, j, e);
if (i == ERROR)
printf("%d个元素删除失败\n", j);
else
printf("%d个元素删除成功,值为%d\n", j, e);
}
printf("依次输出L的元素:");
ListTraverse(L, print);
//DestoryList(L);
//printf("销毁后,L = %u", L);
}
2.3.6静态链表的操做
// 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(),exit()
#include<io.h> // eof()
#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等
#include<sys/timeb.h> // ftime()
#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表
// 函数结果状态代码。在教科书第10页
#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,第7、8章用到
#include "C1.H"
#define MAX_SIZE 100
#define N 6
typedef char ElemType;
typedef struct {
ElemType data;
int cur;
}component, SLinkList[MAX_SIZE];
#define DestroyList ClearList
int Malloc(SLinkList space)
{
int i = space[0].cur;
if (i)
space[0].cur = space[i].cur;
return i;
}
void Free(SLinkList space, int k)
{
space[k].cur = space[0].cur;
space[0].cur = k;
}
void InitList(SLinkList L)
{
int i;
L[MAX_SIZE - 1].cur = 0;
for (i = 0; i < MAX_SIZE - 2; i++)
L[i].cur = i + 1;
L[MAX_SIZE - 2].cur = 0;
}
void ClearList(SLinkList L)
{
int j, k, i = L[MAX_SIZE - 1].cur;
L[MAX_SIZE - 1].cur = 0;
k = L[0].cur;
L[0].cur = i;
while (i)
{
j = i;
i = L[i].cur;
}
L[j].cur = k;
}
Status ListEmpty(SLinkList L)
{
if (L[MAX_SIZE - 1].cur == 0)
return TRUE;
else
return FALSE;
}
int ListLength(SLinkList L)
{
int j = 0, i = L[MAX_SIZE - 1].cur;
while (i)
{
i = L[i].cur;
j++;
}
return j;
}
Status GetElem(SLinkList L, int i, ElemType &e)
{
int m, k = MAX_SIZE - 1;
if (i<1 || i>ListLength(L))
return ERROR;
for (m = 1; m <= i; ++m)
k = L[k].cur;
e = L[k].data;
return OK;
}
int LocateElem(SLinkList L, ElemType e)
{
int i = L[MAX_SIZE - 1].cur;
while (i&&L[i].data != e)
i = L[i].cur;
return i;
}
Status PriorElem(SLinkList L, ElemType cur_e, ElemType &pre_e)
{
int j, i = L[MAX_SIZE - 1].cur;
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)
{
int j, i = LocateElem(L, cur_e);
if (i)
{
j = L[i].cur;
if (j)
{
next_e = L[j].data;
return OK;
}
}
return ERROR;
}
Status ListInsert(SLinkList L, int i, ElemType e)
{
int m, j, k = MAX_SIZE - 1;
if (i<1 || i>ListLength(L) + 1)
return ERROR;
j = Malloc(L);
if (j)
{
L[j].data = e;
for (m = 1; m < i; m++)
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)
{
int j, k = MAX_SIZE - 1;
if (i<1 || i>ListLength(L))
return ERROR;
for (j = 1; j < i; j++)
k = L[k].cur;
j = L[k].cur;
L[k].cur = L[j].cur;
e = L[j].data;
Free(L, j);
return OK;
}
void ListTraverse(SLinkList L, void(*visit)(ElemType))
{
int i = L[MAX_SIZE - 1].cur;
while (i)
{
visit(L[i].data);
i = L[i].cur;
}
printf("\n");
}
2.7双向链表
// c1.h (文件名)
#ifndef C1_H
#define C1_H
#define LIST_INIT_SIZE 10
#define LIST_INCREMENT 2
#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(),exit()
#include<io.h> // eof()
#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等
#include<sys/timeb.h> // ftime()
#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表
// 函数结果状态代码。在教科书第10页
#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,第7、8章用到
typedef int ElemType;
typedef struct DuLNode
{
ElemType data;
DuLNode *next,*prior;
}DuLNode,*DuLinkList;
void InitList(DuLinkList &L);
void DestoryList(DuLinkList &L);
void ClearList(DuLinkList &L);
Status ListEmpty(DuLinkList L);
int ListLength(DuLinkList L);
Status GetElem(DuLinkList L, int i, ElemType &e);
int LocateElem(DuLinkList L, ElemType e, Status(*compare)(ElemType, ElemType));
//寻找前一个节点
Status PriorElem(DuLinkList L, ElemType cur_e, ElemType &pre_e);
//寻找后一个结点
Status NextElem(DuLinkList L, ElemType cur_e, ElemType &next_e);
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));
DuLinkList GetElemP(DuLinkList L, int i);
Status equal(ElemType c1, ElemType c2);
int comp(ElemType a, ElemType b);
void print(ElemType c);
void print1(ElemType c);
void print2(ElemType c);
#endif
#include"C1.H"
void InitList(DuLinkList &L)
{
L = (DuLNode*)malloc(sizeof(DuLNode));
if (!L)
exit(OVERFLOW);
else
{
L->next = L->prior = L;
}
}
void ClearList(DuLinkList &L)
{
DuLinkList p = L->next;
while (p != L)
{
p = p->next;
free(p->prior);
}
L->next = L->prior = L;
}
void DestoryList(DuLinkList &L)
{
ClearList(L);
free(L);
L = NULL;
}
Status ListEmpty(DuLinkList L)
{
if (L->next == L &&L->prior == L)
return TRUE;
else
return FALSE;
}
int ListLength(DuLinkList L)
{
int i = 0;
DuLinkList q = L->next;
while (q != L)
{
i++;
q = q->next;
}
return i;
}
Status GetElem(DuLinkList L, int i, ElemType &e)
{
int j = 1;
DuLinkList p = L->next;
while (p != L && j<i)
{
j++;
p = p->next;
}
if (p == L || j > i)
return ERROR;
e = p->data;
return OK;
}
int LocateElem(DuLinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{
int i = 0;
DuLinkList p = L->next;
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)
{
DuLinkList p = L->next->next;
while (p != L)
{
if (p->data == cur_e)
{
pre_e = p->prior->data;
return OK;
}
p = p->next;
}
return ERROR;
}
Status NextElem(DuLinkList L, ElemType cur_e, ElemType &next_e)
{
DuLinkList p = L->next->next;
while (p != L)
{
if (p->prior->data == cur_e)
{
next_e = p->data;
return OK;
}
p = p->next;
}
return ERROR;
}
DuLinkList GetElemP(DuLinkList L, int i)
{
int j;
DuLinkList p = L;
if (i < 0 || i>ListLength(L))
return ERROR;
for (j = 1; j <= i; j++)
p = p->next;
return p;
}
Status ListInsert(DuLinkList &L, int i, ElemType e)
{
int j = 0;
DuLinkList s, p = L->next;
if (i <= 0 || i > ListLength(L) + 1)
return ERROR;
p = GetElemP(L, i - 1);
s = (DuLinkList)malloc(sizeof(DuLNode));
s->data = e;
s->next = p->next;
s->prior = p;
p->next->prior = s;
p->next = s;
return OK;
}
Status ListDelete(DuLinkList &L, int i, ElemType &e)
{
int j = 0;
DuLinkList p;
if (i <= 1)
return ERROR;
p = GetElemP(L, i);
if (!p)
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))
{
DuLinkList p = L->next;
while (p != L)
{
visit(p->data);
p = p->next;
}
printf("\n");
}
void ListTraverseBack(DuLinkList &L, void(*visit)(ElemType))
{
DuLinkList p = L->prior;
while (p != L)
{
visit(p->data);
p = p->prior;
}
printf("\n");
}
void print(ElemType c)
{
printf("%d", c);
}
Status equal(ElemType c1, ElemType c2)
{
if (c1 == c2)
return TRUE;
else
return FALSE;
}
// main2-6.cpp 检验bo2-7.cpp的主程序
#include"c1.h"
void main()
{
DuLinkList L;
int i, n = 4;
Status j;
ElemType e;
InitList(L); // 初始化线性表L
for (i = 1; i <= 5; i++) // 依次插入1~5
ListInsert(L, i, i); // 在第i个结点之前插入i
printf("逆序输出链表:");
ListTraverseBack(L, print); // 逆序输出
j = GetElem(L, 2, e); // 将链表的第2个元素赋值给e
if (j)
printf("链表的第2个元素值为%d\n", e);
else
printf("不存在第2个元素\n");
i = LocateElem(L, n, equal);
if (i)
printf("等于%d的元素是第%d个\n", n, i);
else
printf("没有等于%d的元素\n", n);
j = PriorElem(L, n, e);
if (j)
printf("%d的前驱是%d,", 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);
ListDelete(L, 2, e); // 删除并释放第2个结点
printf("删除第2个结点,值为%d,其余结点为 ", e);
ListTraverse(L, print); // 正序输出
printf("链表的元素个数为%d,", ListLength(L));
printf("链表是否空?%d(1:是 0:否)\n", ListEmpty(L));
ClearList(L); // 清空链表
printf("清空后,链表是否空?%d(1:是 0:否)\n", ListEmpty(L));
DestoryList(L);
}