抽象数据类型的实现

第3章 抽象数据类型的实现

3.1 实验概要

实验项目名称: 抽象数据类型的实现 实验项目性质: 设计性实验 所属课程名称: 数据结构 实验计划学时: 6

3.2 实验目的

对某个具体的抽象数据类型,运用课程所学的知识和方法,设计合理的数据结构,并在此基础上实现该抽象数据类型的全部基本操作。通过本设计性实验,检验所学知识和能力,发现学习中存在的问题。 进而达到熟练地运用本课程中的基础知识及技术的目的。

3.3 预习与参考

1.确定要实现的抽象数据类型,并对基本操作做适当的选取和增加; 2.选择存储结构,并写出相应的类型定义;

3.设计各基本操作的实现算法,并表达为函数形式; 4.设计测试方案,编写主函数;

5.将上述4步的结果写成预习报告。

3.4 实验要求和设计指标

以教材中线性表,串,稀疏矩阵,广义表,二叉树,树,图以及查找表等抽象数据类型为对象,利用C 语言的数据类型表示和实现其中某个抽象数据类型。

可选的抽象数据类型如下表所列:

注:如果基本操作数量较多,可选择实现其中一个基本操作子集。

实验要求如下: 1.参加实验的学生应首先了解设计的任务,然后根据自己的基础和能力从中选择一题。一般来说,选择题目应以在规定的时间内能完成,并能得到应有的锻炼为原则。 若学生对教材以外的相关题目较感兴趣,希望选作实验的题目时,应征得指导教师的认可,并写出明确的抽象数据类型定义及说明。

2. 实验前要作好充分准备,包括:理解实验要求,掌握辅助工具的使用,了解该抽象数据类型的定义及意义,以及其基本操作的算法并设计合理的存储结构。

3. 实验时严肃认真,要严格按照要求独立进行设计,不能随意更改。注意观察并记录各种错误现象,纠正错误,使程序满足预定的要求,实验记录应作为实验报告的一部分。

4. 实验后要及时总结,写出实验报告,并附所打印的问题解答、程序清单,所输入的数据及相应的运行结果。

3.5 实验仪器设备和材料

软件实验室。

编程环境:Anyview C可视化编程环境、TC++、C++Builder或者VC++。

3.6 调试及结果测试

调试内容应包括:调试过程中遇到的问题是如何解决的以及对实验的讨论与分析;基本操作的时间复杂度和空间复杂度的分析和改进设想。列出对每一个基本操作的测试结果,包括输入和输出,测试数据应完整和严格。

3.7 考核形式

考核形式以实验过程和实验报告相结合的方式进行。在实验完成后,应当场运行和答辩,由指导教师验收,只有在验收合格后才能算实验部分的结束。实验报告作为整个设计性实验评分的书面依据。设计性实验的成绩评定以选定题目的难易度、完成情况和实验报告为依据综合评分。从总体来说,所实现的抽象数据类型应该全部符合要求,类型定义,各基本操作的算法以及存储结构清晰;各模快测试运行正确;程序的结构合理;设计报告符合规范。

3.8 实验报告要求

实验结束后要写出实验报告,以作为整个设计性实验评分的书面依据和存档材料。实验报告是反映学生实验效果的最主要的依据,也是学生正确地表达问题、综合问题和发现问题的能力的基本培养手段,因而是非常重要的内容。本设计性实验的报告要包括以下几项内容:

(1)设计任务、要求及所用软件环境或工具;

(2)抽象数据类型定义以及各基本操作的简要描述;

(3)所选择的存储结构描述及在此存储结构上各基本操作的实现; (4)程序清单(计算机打印),输入的数据及各基本操作的测试结果; (5)实验总结和体会。

实验报告以规定格式的电子文档书写、打印并装订,排版及图表要清楚、工整。

3.9 思考题

对设计性实验进行总结和讨论,包括本实验的优、缺点,数据存储结构的特点,与其它存储结构之间的比较等。通过总结,可以对抽象数据类型有更全面、深入的认识,这是设计性实验不可缺少的重要内容。这部分内容应作为实验报告中的一个组成部分。

3.10 示例

1. 题目

采用字符类型为元素类型和无头结点单链表为存储结构,实现抽象数据类型List 。 ADT List{

数据对象:D ={ ai | ai ∈ElemSet, i=1,2,...,n, n≥0 } 数据关系:R1={ |ai-1, ai ∈D, i=2,...,n } 基本操作:

SetEmpty(&L)

操作结果:构造一个空的线性表L 。 Destroy(&L)

初始条件:线性表L 已存在。 操作结果:销毁线性表L 。 Length(L)

初始条件:线性表L 已存在。 操作结果:返回L 中元素个数。 Get(L, i, &e)

初始条件:线性表L 已存在,1≤i≤LengthList(L)。 操作结果:用e 返回L 中第i 个元素的值。 Locate(L, e, compare())

初始条件:线性表L 已存在,compare()是元素判定函数。

操作结果:返回L 中第1个与e 满足关系compare()的元素的位序。

若这样的元素不存在,则返回值为0。

Insert(&L, i, e)

初始条件:线性表L 已存在,1≤i≤LengthList(L)+1。

操作结果:在L 的第i 个元素之前插入新的元素e ,L 的长度加1。 Delete(&L, i, &e)

初始条件:线性表L 已存在且非空,1≤i≤LengthList(L)。

操作结果:删除L 的第i 个元素,并用e 返回其值,L 的长度减1。 Display(L)

初始条件:线性表L 已存在。

操作结果:依次输出L 的每个元素。

} ADT List

2.存储结构定义

公用头文件DS0.h:

#include #include #include #include #include

#define TRUE 1 #define FALSE 0 #define OK 1

#define ERROR 0

#define IBFEASIBLE -1 #define OVERFLOW -2

#define MAXLEN 20 #define MAXSIZE 20

typedef int Status;

typedef char ElemType; /* 元素类型为字符类型*/

(1) 顺序存储结构

#define LIST_INIT_SIZE 20 /*线性表存储空间的初始分配量*/ #define LISTINCREMENT 10 /*线性表存储空间的分配增量*/ typedef struct{

ElemType *elem; /*存储空间基址*/ int length; /*当前长度*/

int listsize; /*当前分配的存储容量*/ } SqList;

(2) 无头结点单链表存储结构

typedef struct LNode {

ElemType data;

struct LNode *next;

} LNode, *LList; /* 不带头结点单链表类型*/

(3) 带头结点单链表存储结构

typedef struct LNode { /* 结点类型 */ ElemType data;

struct LNode *next;

} LNode, *Link, *Position;

typedef struct LinkList { /* 链表类型 */

Link head,tail; /* 分别指向线性链表中的头结点和最后一个结点 */

int len; /* 指示线性链表中数据元素的个数 */ } LinkList;

3. 算法设计

(1) 顺序存储结构

Status SetEmpty(SqList &L) { /*构造一个空的顺序线性表 */

L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));

if (!L.elem)

return OVERFLOW; /* 存储分配失败 */

L.length=0; /* 空表长度为0 */

L.listsize=LIST_INIT_SIZE; /* 初始存储容量 */ return OK; }

Status Destroy (SqList &L) { /*销毁顺序线性表L */ free(L.elem); L.elem=NULL; L.length=0; L.listsize=0; return OK; }

int Length(SqList L) { /* 求表长*/ return L.length; }

Status Get(SqList &L, int i, ElemType &e) { /* 获取第i 元素 */

if (iL.length) return ERROR; e=*(L.elem+i-1); return OK; }

int Locate(SqList L, ElemType x) { /* 确定x 在表中的位序 */ ElemType *p;

int i=1; /* i的初值为第1个元素的位序 */

p=L.elem; /* p的初值为第1个元素的存储位置 */ while (i

if (i

return 0; }

Status Insert(SqList &L, int i, ElemType e) {

/* 操作结果:在L 中第i 个位置之前插入新的数据元素e ,L 的长度加1 */

ElemType *newbase,*q,*p;

if (iL.length+1) /* i值不合法 */ return ERROR;

if (L.length>= L.listsize) { /* 当前存储空间已满, 增加分配 */

newbase=(ElemType *) realloc(L.elem,

(L.listsize+LISTINCREMENT)*sizeof(ElemType));

if (!newbase) return 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 Delete(SqList &L, int i, ElemType &e) {

/* 初始条件:顺序线性表L 已存在,1≤i ≤ListLength(L) */ /* 操作结果:删除L 的第i 个数据元素,并用e 返回其值,L 的长度减1 */

ElemType *p,*q;

if (i L.length) /* i值不合法 */ return ERROR;

p= L.elem+i-1; /* p为被删除元素的位置 */ e=*p; /* 被删除元素的值赋给e */

q= L.elem+L.length-1; /* 表尾元素的位置 */

for (++p; p

L.length--; /* 表长减1 */ return OK; }

Status Display(SqList L) { /* 依次显示表中元素 */ ElemType *p; int i; p=L.elem;

printf("( ");

for (i=1; i

(2) 无头结点单链表

void SetEmpty(LList &L) { /* 置无头结点的空单链表*/ L=NULL; }

Status Destroy (LList &L) { /* 销毁链表*/ LList q=L; while (L) { L=L->next;

free(q); q=L; }

return OK; }

int Length(LList L) { /* 求表长*/ int n=0;

while (L!=NULL) { n++;

L=L->next; }

return n; }

Status Get(LList L, int i, ElemType &e) { /* 获取第i 元素 */

int j=1;

while (jnext; j++; }

if(L!=NULL) { e=L->data; return OK; } else return ERROR; /* 位置参数i 不正确 */ }

int Locate(LList L, ElemType x) { /* 确定x 在表中的位序 */ int n=1;

while (L!=NULL && L->data!=x) { L=L->next; n++; }

if (L==NULL) return 0; else return n; }

Status Insert(LList &L, int i, ElemType e) { /* 插入第i 元素*/

int j=1; LList s,q;

s=(LList)malloc(sizeof(LNode)); s->data=e; q=L;

if (i==1) { s->next=q; L=s; return OK;} else {

while (jnext!=NULL) { q=q->next; j++;

if (j==i-1) {

s->next=q->next; q->next=s; return OK; }

else return ERROR; /* 位置参数i 不正确 */ } }

Status Delete(LList &L, int i, ElemType &e) { /* 删除第i 元素*/

int j=1;

LList q=L,t; if (i==1) { e=q->data; L=q->next; free(q); return OK; }

else {

while (jnext!=NULL) { q=q->next; j++; }

if (q->next!=NULL && j==i-1) { t=q->next;

q->next=t->next; e=t->data; free(t); return OK; }

else return ERROR; /* 位置参数i 不正确*/ } }

void Display(LList L) { /* 依次显示表中元素 */ printf("单链表显示: "); if (L==NULL)

printf("链表为空!"); else if (L->next==NULL)

printf("%c\n", L->data); else {

while(L->next!=NULL) {

printf("%c->", L->data); L=L->next;

printf("%c", L->data); }

printf("\n"); }

(3) 带头结点单链表

Status SetEmpty(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 Destroy(LinkList &L) { /* 销毁线性链表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); }

free(L.head);

L.head=L.tail=NULL; L.len=0; return OK; }

int Length(LinkList L) { /* 返回线性链表L 中元素个数 */ return L.len; }

Status Get(LinkList L, int i, ElemType &e) { /* 获取第i 元素 */

/* i=0为头结点 */ Link p; int j;

if (iL.len)

return ERROR; else {

p=L.head;

for (j=1;jnext; e=p->data; return OK; } }

int Locate(LinkList L, ElemType x) { /* 确定x 在表中的位序 */

int i=0;

Link p=L.head; do {

p=p->next; i++;

} while(p && p->data!=x); /* 没到表尾且没找到满足关系的元素 */

if (!p)

return 0; else

return i; }

Status Insert(LinkList &L, int i, ElemType e) { /* 插入第i 元素*/ int j=0; Link s,q;

s=(Link)malloc(sizeof(LNode)); s->data=e; q=L.head;

while (jnext!=NULL) { q=q->next; j++; }

if (j==i-1) {

s->next=q->next; q->next=s;

if (L.tail==q) L.tail=s; L.len++; return OK; }

else return ERROR; /* 位置参数i 不正确 */ }

Status Delete(LinkList &L, int i, ElemType &e) {

/* 删除第i 元素*/

int j=0;

Link q=L.head,t;

while (jnext!=NULL) {

q=q->next;

j++;

}

if (q->next!=NULL && j==i-1) {

t=q->next;

q->next=t->next;

e=t->data;

if (L.tail==t) L.tail=q;

free(t);

L.len--;

return OK;

}

else return ERROR; /* 位置参数i 不正确*/

}

void Display(LinkList L) { /* 依次显示表中元素 */

Link p;

printf("单链表显示: ");

if (L.head==L.tail)

printf("链表为空!");

else {

p=L.head->next;

while (p->next!=NULL) {

printf("%c->", p->data);

p=p->next;

}

printf("%c", p->data);

}

printf("\n");

}

4.测试

(1) 顺序存储结构

SqList head;

void main() { /* 主函数*/

char e,c;

int i,n,select,x1,x2,x3,x4,m,g;

SetEmpty(head);

n=random(8); /* 随机产生表长 */

for (i=1; i

c='A'+random(26);

Insert(head,i,c);

}

do {

Display(head);

printf("select 1 求长度 Length()\n");

printf("select 2 取结点 Get()\n");

printf("select 3 求值查找 Locate()\n");

printf("select 4 删除结点 Delete()\n");

printf("input your select: ");

scanf("%d",&select);

switch (select) {

case 1: x1=Length(head);

printf("顺序表的长度:%d ",x1);

break ;

case 2: printf("请输入要取的结点序号: ");

scanf("%d",&m);

if (Get(head,m,x2)) printf("%c\n",x2);

else printf("错误\n");

break ;

case 3: printf("请输入要查找的数据元素: ");

scanf("\n%c",&e);

x3=Locate(head,e);

printf("%d\n",x3);

break ;

case 4: printf("请输入要删除的元素序号: ");

scanf("%d",&g);

if (Delete(head,g,x4))

printf("%c\n",x4);

else printf("错误\n");

break ;

}

} while (select>0 && select

}

(2) 无头结点单链表

LList head;

void main() { /* 主函数*/

char e,c;

int i,n,select,x1,x2,x3,x4,m,g;

SetEmpty(head);

n=random(8); /* 随机产生表长 */

for (i=1; i

c='A'+random(26);

Insert(head,i,c);

}

do {

Display(head);

printf("select 1 求长度 Length()\n");

printf("select 2 取结点 Get()\n");

printf("select 3 求值查找 Locate()\n");

printf("select 4 删除结点 Delete()\n");

printf("input your select: ");

scanf("%d",&select);

switch (select) {

case 1: x1=Length(head);

printf("顺序表的长度:%d ",x1);

break ;

case 2: printf("请输入要取的结点序号: ");

scanf("%d",&m);

if (Get(head,m,x2)) printf("%c\n",x2);

else printf("错误\n");

break ;

case 3: printf("请输入要查找的数据元素: ");

scanf("\n%c",&e);

x3=Locate(head,e);

printf("%d\n",x3);

break ;

case 4: printf("请输入要删除的元素序号: ");

scanf("%d",&g);

if (Delete(head,g,x4))

printf("%c\n",x4);

else printf("错误\n");

break ;

}

} while (select>0 && select

}

(3) 带头结点单链表

LinkList head;

void main() { /* 主函数*/

char e,c;

int i,n,select,x1,x2,x3,x4,m,g;

SetEmpty(head);

n=random(8); /* 随机产生表长 */

for (i=1; i

c='A'+random(26);

Insert(head,i,c);

}

do {

Display(head);

printf("select 1 求长度 Length()\n");

printf("select 2 取结点 Get()\n");

printf("select 3 求值查找 Locate()\n");

printf("select 4 删除结点 Delete()\n");

printf("input your select: ");

scanf("%d",&select);

switch (select) {

case 1: x1=Length(head);

printf("顺序表的长度:%d ",x1);

break ;

case 2: printf("请输入要取的结点序号: ");

scanf("%d",&m);

if (Get(head,m,x2)) printf("%c\n",x2);

else printf("错误\n");

break ;

case 3: printf("请输入要查找的数据元素: ");

scanf("\n%c",&e);

x3=Locate(head,e);

printf("%d\n",x3);

break ;

case 4: printf("请输入要删除的元素序号: ");

scanf("%d",&g);

if (Delete(head,g,x4))

printf("%c\n",x4);

else printf("错误\n");

break ;

}

} while (select>0 && select

}

5.三种存储结构的比较

6.思考与小结

(1)无头结点单链表的插入和删除操作的实现,要区分该表是否为空,并编写相应的代码。

(2)在算法设计时,要注意判断有关参数值的合法性。

(3)三种存储结构的主函数相同。设计主函数及测试运行时,要考虑测试的完备性。

7.预习报告和实验报告

(1)预习报告:包括1-4步的初稿。

(2)实验报告:在预习报告的基础上,增加在实验中,对算法修改核调试的收获体会,以及思考和小结的内容。

第3章 抽象数据类型的实现

3.1 实验概要

实验项目名称: 抽象数据类型的实现 实验项目性质: 设计性实验 所属课程名称: 数据结构 实验计划学时: 6

3.2 实验目的

对某个具体的抽象数据类型,运用课程所学的知识和方法,设计合理的数据结构,并在此基础上实现该抽象数据类型的全部基本操作。通过本设计性实验,检验所学知识和能力,发现学习中存在的问题。 进而达到熟练地运用本课程中的基础知识及技术的目的。

3.3 预习与参考

1.确定要实现的抽象数据类型,并对基本操作做适当的选取和增加; 2.选择存储结构,并写出相应的类型定义;

3.设计各基本操作的实现算法,并表达为函数形式; 4.设计测试方案,编写主函数;

5.将上述4步的结果写成预习报告。

3.4 实验要求和设计指标

以教材中线性表,串,稀疏矩阵,广义表,二叉树,树,图以及查找表等抽象数据类型为对象,利用C 语言的数据类型表示和实现其中某个抽象数据类型。

可选的抽象数据类型如下表所列:

注:如果基本操作数量较多,可选择实现其中一个基本操作子集。

实验要求如下: 1.参加实验的学生应首先了解设计的任务,然后根据自己的基础和能力从中选择一题。一般来说,选择题目应以在规定的时间内能完成,并能得到应有的锻炼为原则。 若学生对教材以外的相关题目较感兴趣,希望选作实验的题目时,应征得指导教师的认可,并写出明确的抽象数据类型定义及说明。

2. 实验前要作好充分准备,包括:理解实验要求,掌握辅助工具的使用,了解该抽象数据类型的定义及意义,以及其基本操作的算法并设计合理的存储结构。

3. 实验时严肃认真,要严格按照要求独立进行设计,不能随意更改。注意观察并记录各种错误现象,纠正错误,使程序满足预定的要求,实验记录应作为实验报告的一部分。

4. 实验后要及时总结,写出实验报告,并附所打印的问题解答、程序清单,所输入的数据及相应的运行结果。

3.5 实验仪器设备和材料

软件实验室。

编程环境:Anyview C可视化编程环境、TC++、C++Builder或者VC++。

3.6 调试及结果测试

调试内容应包括:调试过程中遇到的问题是如何解决的以及对实验的讨论与分析;基本操作的时间复杂度和空间复杂度的分析和改进设想。列出对每一个基本操作的测试结果,包括输入和输出,测试数据应完整和严格。

3.7 考核形式

考核形式以实验过程和实验报告相结合的方式进行。在实验完成后,应当场运行和答辩,由指导教师验收,只有在验收合格后才能算实验部分的结束。实验报告作为整个设计性实验评分的书面依据。设计性实验的成绩评定以选定题目的难易度、完成情况和实验报告为依据综合评分。从总体来说,所实现的抽象数据类型应该全部符合要求,类型定义,各基本操作的算法以及存储结构清晰;各模快测试运行正确;程序的结构合理;设计报告符合规范。

3.8 实验报告要求

实验结束后要写出实验报告,以作为整个设计性实验评分的书面依据和存档材料。实验报告是反映学生实验效果的最主要的依据,也是学生正确地表达问题、综合问题和发现问题的能力的基本培养手段,因而是非常重要的内容。本设计性实验的报告要包括以下几项内容:

(1)设计任务、要求及所用软件环境或工具;

(2)抽象数据类型定义以及各基本操作的简要描述;

(3)所选择的存储结构描述及在此存储结构上各基本操作的实现; (4)程序清单(计算机打印),输入的数据及各基本操作的测试结果; (5)实验总结和体会。

实验报告以规定格式的电子文档书写、打印并装订,排版及图表要清楚、工整。

3.9 思考题

对设计性实验进行总结和讨论,包括本实验的优、缺点,数据存储结构的特点,与其它存储结构之间的比较等。通过总结,可以对抽象数据类型有更全面、深入的认识,这是设计性实验不可缺少的重要内容。这部分内容应作为实验报告中的一个组成部分。

3.10 示例

1. 题目

采用字符类型为元素类型和无头结点单链表为存储结构,实现抽象数据类型List 。 ADT List{

数据对象:D ={ ai | ai ∈ElemSet, i=1,2,...,n, n≥0 } 数据关系:R1={ |ai-1, ai ∈D, i=2,...,n } 基本操作:

SetEmpty(&L)

操作结果:构造一个空的线性表L 。 Destroy(&L)

初始条件:线性表L 已存在。 操作结果:销毁线性表L 。 Length(L)

初始条件:线性表L 已存在。 操作结果:返回L 中元素个数。 Get(L, i, &e)

初始条件:线性表L 已存在,1≤i≤LengthList(L)。 操作结果:用e 返回L 中第i 个元素的值。 Locate(L, e, compare())

初始条件:线性表L 已存在,compare()是元素判定函数。

操作结果:返回L 中第1个与e 满足关系compare()的元素的位序。

若这样的元素不存在,则返回值为0。

Insert(&L, i, e)

初始条件:线性表L 已存在,1≤i≤LengthList(L)+1。

操作结果:在L 的第i 个元素之前插入新的元素e ,L 的长度加1。 Delete(&L, i, &e)

初始条件:线性表L 已存在且非空,1≤i≤LengthList(L)。

操作结果:删除L 的第i 个元素,并用e 返回其值,L 的长度减1。 Display(L)

初始条件:线性表L 已存在。

操作结果:依次输出L 的每个元素。

} ADT List

2.存储结构定义

公用头文件DS0.h:

#include #include #include #include #include

#define TRUE 1 #define FALSE 0 #define OK 1

#define ERROR 0

#define IBFEASIBLE -1 #define OVERFLOW -2

#define MAXLEN 20 #define MAXSIZE 20

typedef int Status;

typedef char ElemType; /* 元素类型为字符类型*/

(1) 顺序存储结构

#define LIST_INIT_SIZE 20 /*线性表存储空间的初始分配量*/ #define LISTINCREMENT 10 /*线性表存储空间的分配增量*/ typedef struct{

ElemType *elem; /*存储空间基址*/ int length; /*当前长度*/

int listsize; /*当前分配的存储容量*/ } SqList;

(2) 无头结点单链表存储结构

typedef struct LNode {

ElemType data;

struct LNode *next;

} LNode, *LList; /* 不带头结点单链表类型*/

(3) 带头结点单链表存储结构

typedef struct LNode { /* 结点类型 */ ElemType data;

struct LNode *next;

} LNode, *Link, *Position;

typedef struct LinkList { /* 链表类型 */

Link head,tail; /* 分别指向线性链表中的头结点和最后一个结点 */

int len; /* 指示线性链表中数据元素的个数 */ } LinkList;

3. 算法设计

(1) 顺序存储结构

Status SetEmpty(SqList &L) { /*构造一个空的顺序线性表 */

L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));

if (!L.elem)

return OVERFLOW; /* 存储分配失败 */

L.length=0; /* 空表长度为0 */

L.listsize=LIST_INIT_SIZE; /* 初始存储容量 */ return OK; }

Status Destroy (SqList &L) { /*销毁顺序线性表L */ free(L.elem); L.elem=NULL; L.length=0; L.listsize=0; return OK; }

int Length(SqList L) { /* 求表长*/ return L.length; }

Status Get(SqList &L, int i, ElemType &e) { /* 获取第i 元素 */

if (iL.length) return ERROR; e=*(L.elem+i-1); return OK; }

int Locate(SqList L, ElemType x) { /* 确定x 在表中的位序 */ ElemType *p;

int i=1; /* i的初值为第1个元素的位序 */

p=L.elem; /* p的初值为第1个元素的存储位置 */ while (i

if (i

return 0; }

Status Insert(SqList &L, int i, ElemType e) {

/* 操作结果:在L 中第i 个位置之前插入新的数据元素e ,L 的长度加1 */

ElemType *newbase,*q,*p;

if (iL.length+1) /* i值不合法 */ return ERROR;

if (L.length>= L.listsize) { /* 当前存储空间已满, 增加分配 */

newbase=(ElemType *) realloc(L.elem,

(L.listsize+LISTINCREMENT)*sizeof(ElemType));

if (!newbase) return 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 Delete(SqList &L, int i, ElemType &e) {

/* 初始条件:顺序线性表L 已存在,1≤i ≤ListLength(L) */ /* 操作结果:删除L 的第i 个数据元素,并用e 返回其值,L 的长度减1 */

ElemType *p,*q;

if (i L.length) /* i值不合法 */ return ERROR;

p= L.elem+i-1; /* p为被删除元素的位置 */ e=*p; /* 被删除元素的值赋给e */

q= L.elem+L.length-1; /* 表尾元素的位置 */

for (++p; p

L.length--; /* 表长减1 */ return OK; }

Status Display(SqList L) { /* 依次显示表中元素 */ ElemType *p; int i; p=L.elem;

printf("( ");

for (i=1; i

(2) 无头结点单链表

void SetEmpty(LList &L) { /* 置无头结点的空单链表*/ L=NULL; }

Status Destroy (LList &L) { /* 销毁链表*/ LList q=L; while (L) { L=L->next;

free(q); q=L; }

return OK; }

int Length(LList L) { /* 求表长*/ int n=0;

while (L!=NULL) { n++;

L=L->next; }

return n; }

Status Get(LList L, int i, ElemType &e) { /* 获取第i 元素 */

int j=1;

while (jnext; j++; }

if(L!=NULL) { e=L->data; return OK; } else return ERROR; /* 位置参数i 不正确 */ }

int Locate(LList L, ElemType x) { /* 确定x 在表中的位序 */ int n=1;

while (L!=NULL && L->data!=x) { L=L->next; n++; }

if (L==NULL) return 0; else return n; }

Status Insert(LList &L, int i, ElemType e) { /* 插入第i 元素*/

int j=1; LList s,q;

s=(LList)malloc(sizeof(LNode)); s->data=e; q=L;

if (i==1) { s->next=q; L=s; return OK;} else {

while (jnext!=NULL) { q=q->next; j++;

if (j==i-1) {

s->next=q->next; q->next=s; return OK; }

else return ERROR; /* 位置参数i 不正确 */ } }

Status Delete(LList &L, int i, ElemType &e) { /* 删除第i 元素*/

int j=1;

LList q=L,t; if (i==1) { e=q->data; L=q->next; free(q); return OK; }

else {

while (jnext!=NULL) { q=q->next; j++; }

if (q->next!=NULL && j==i-1) { t=q->next;

q->next=t->next; e=t->data; free(t); return OK; }

else return ERROR; /* 位置参数i 不正确*/ } }

void Display(LList L) { /* 依次显示表中元素 */ printf("单链表显示: "); if (L==NULL)

printf("链表为空!"); else if (L->next==NULL)

printf("%c\n", L->data); else {

while(L->next!=NULL) {

printf("%c->", L->data); L=L->next;

printf("%c", L->data); }

printf("\n"); }

(3) 带头结点单链表

Status SetEmpty(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 Destroy(LinkList &L) { /* 销毁线性链表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); }

free(L.head);

L.head=L.tail=NULL; L.len=0; return OK; }

int Length(LinkList L) { /* 返回线性链表L 中元素个数 */ return L.len; }

Status Get(LinkList L, int i, ElemType &e) { /* 获取第i 元素 */

/* i=0为头结点 */ Link p; int j;

if (iL.len)

return ERROR; else {

p=L.head;

for (j=1;jnext; e=p->data; return OK; } }

int Locate(LinkList L, ElemType x) { /* 确定x 在表中的位序 */

int i=0;

Link p=L.head; do {

p=p->next; i++;

} while(p && p->data!=x); /* 没到表尾且没找到满足关系的元素 */

if (!p)

return 0; else

return i; }

Status Insert(LinkList &L, int i, ElemType e) { /* 插入第i 元素*/ int j=0; Link s,q;

s=(Link)malloc(sizeof(LNode)); s->data=e; q=L.head;

while (jnext!=NULL) { q=q->next; j++; }

if (j==i-1) {

s->next=q->next; q->next=s;

if (L.tail==q) L.tail=s; L.len++; return OK; }

else return ERROR; /* 位置参数i 不正确 */ }

Status Delete(LinkList &L, int i, ElemType &e) {

/* 删除第i 元素*/

int j=0;

Link q=L.head,t;

while (jnext!=NULL) {

q=q->next;

j++;

}

if (q->next!=NULL && j==i-1) {

t=q->next;

q->next=t->next;

e=t->data;

if (L.tail==t) L.tail=q;

free(t);

L.len--;

return OK;

}

else return ERROR; /* 位置参数i 不正确*/

}

void Display(LinkList L) { /* 依次显示表中元素 */

Link p;

printf("单链表显示: ");

if (L.head==L.tail)

printf("链表为空!");

else {

p=L.head->next;

while (p->next!=NULL) {

printf("%c->", p->data);

p=p->next;

}

printf("%c", p->data);

}

printf("\n");

}

4.测试

(1) 顺序存储结构

SqList head;

void main() { /* 主函数*/

char e,c;

int i,n,select,x1,x2,x3,x4,m,g;

SetEmpty(head);

n=random(8); /* 随机产生表长 */

for (i=1; i

c='A'+random(26);

Insert(head,i,c);

}

do {

Display(head);

printf("select 1 求长度 Length()\n");

printf("select 2 取结点 Get()\n");

printf("select 3 求值查找 Locate()\n");

printf("select 4 删除结点 Delete()\n");

printf("input your select: ");

scanf("%d",&select);

switch (select) {

case 1: x1=Length(head);

printf("顺序表的长度:%d ",x1);

break ;

case 2: printf("请输入要取的结点序号: ");

scanf("%d",&m);

if (Get(head,m,x2)) printf("%c\n",x2);

else printf("错误\n");

break ;

case 3: printf("请输入要查找的数据元素: ");

scanf("\n%c",&e);

x3=Locate(head,e);

printf("%d\n",x3);

break ;

case 4: printf("请输入要删除的元素序号: ");

scanf("%d",&g);

if (Delete(head,g,x4))

printf("%c\n",x4);

else printf("错误\n");

break ;

}

} while (select>0 && select

}

(2) 无头结点单链表

LList head;

void main() { /* 主函数*/

char e,c;

int i,n,select,x1,x2,x3,x4,m,g;

SetEmpty(head);

n=random(8); /* 随机产生表长 */

for (i=1; i

c='A'+random(26);

Insert(head,i,c);

}

do {

Display(head);

printf("select 1 求长度 Length()\n");

printf("select 2 取结点 Get()\n");

printf("select 3 求值查找 Locate()\n");

printf("select 4 删除结点 Delete()\n");

printf("input your select: ");

scanf("%d",&select);

switch (select) {

case 1: x1=Length(head);

printf("顺序表的长度:%d ",x1);

break ;

case 2: printf("请输入要取的结点序号: ");

scanf("%d",&m);

if (Get(head,m,x2)) printf("%c\n",x2);

else printf("错误\n");

break ;

case 3: printf("请输入要查找的数据元素: ");

scanf("\n%c",&e);

x3=Locate(head,e);

printf("%d\n",x3);

break ;

case 4: printf("请输入要删除的元素序号: ");

scanf("%d",&g);

if (Delete(head,g,x4))

printf("%c\n",x4);

else printf("错误\n");

break ;

}

} while (select>0 && select

}

(3) 带头结点单链表

LinkList head;

void main() { /* 主函数*/

char e,c;

int i,n,select,x1,x2,x3,x4,m,g;

SetEmpty(head);

n=random(8); /* 随机产生表长 */

for (i=1; i

c='A'+random(26);

Insert(head,i,c);

}

do {

Display(head);

printf("select 1 求长度 Length()\n");

printf("select 2 取结点 Get()\n");

printf("select 3 求值查找 Locate()\n");

printf("select 4 删除结点 Delete()\n");

printf("input your select: ");

scanf("%d",&select);

switch (select) {

case 1: x1=Length(head);

printf("顺序表的长度:%d ",x1);

break ;

case 2: printf("请输入要取的结点序号: ");

scanf("%d",&m);

if (Get(head,m,x2)) printf("%c\n",x2);

else printf("错误\n");

break ;

case 3: printf("请输入要查找的数据元素: ");

scanf("\n%c",&e);

x3=Locate(head,e);

printf("%d\n",x3);

break ;

case 4: printf("请输入要删除的元素序号: ");

scanf("%d",&g);

if (Delete(head,g,x4))

printf("%c\n",x4);

else printf("错误\n");

break ;

}

} while (select>0 && select

}

5.三种存储结构的比较

6.思考与小结

(1)无头结点单链表的插入和删除操作的实现,要区分该表是否为空,并编写相应的代码。

(2)在算法设计时,要注意判断有关参数值的合法性。

(3)三种存储结构的主函数相同。设计主函数及测试运行时,要考虑测试的完备性。

7.预习报告和实验报告

(1)预习报告:包括1-4步的初稿。

(2)实验报告:在预习报告的基础上,增加在实验中,对算法修改核调试的收获体会,以及思考和小结的内容。


相关文章

  • 企业面试题集绵
  • (一) Java中有没有goto关键字? (二) 基本数据类型有哪些?String是不是基本数据类型? 基本数据类型:byte, char, short, int, long, float, double, boolean String不属 ...查看


  • 北航程序设计语言原理教材第02章
  • 第2章程序设计语言的设计概述 本章介绍程序设计语言的设计目标以及为实现这些目标所遵循的设计准则,设计语言最后要给出语言的参考手册,为此,从表示的角度介绍与语法,语义和上下文约束有关的概念和表示法.目前在程序语言语法文本中,语法形式表示是完整 ...查看


  • [软件工程导论]考试夹带
  • 1.软件危机的概念:软件危机是指在计算机软件的开发和维护过程中所遇到的一系 列严重的问题. 2.产生软件危机的原因:一方面与软件本身的特点有关,另一方面也和软件开发与 维护的方法不正确有关. 3.软件工程的定义:是指导计算机软件开发和维护的 ...查看


  • 基于模板的专题制图数学模型构建和应用
  • 第19卷第6期 测 2010年12月 ENGINEERING OF 绘 工 程 V o l. 19l . 6SURV EYING AND M APPIN G Dec. , 2010基于模板的专题制图数学模型构建和应用 冯 涛1, 张亚军1, ...查看


  • infosys面试总结
  • 1. 作用域public,private,protected,以及不写时的区别 区别如下: 作用域 当前类 同一package 子孙类 其他package public √ √ √ √ protected √ √ √ × friendly ...查看


  • 非物质设计符号系统的框架设计研究
  • 摘 要:随着计算机技术应用的不断提高,在我们日常生活中的作用也越来越大,本文就是在此基础上进行研究与探讨,分析如何在进行符号系统中利用计算机技术对一些非物质符号的设计进行有效的管理,然后进行有效的利用. 关键词:图形管理系统:数据库:C# ...查看


  • 航空公司管理系统(uml建模)
  • 航空公司管理系统 UML 分析与设计文档 组长: ******** 组员:******** *****学院 ****** 目录 目录 ..................................................... ...查看


  • net互联网软件开发工程师 new-2
  • .NET互联网软件开发工程师 岗位描述: 字不能放在变量名首位 8.C# 数组从零开始建立索引,即数组索引从零开始.C# 中数组的工作方式与在大多数其他流行语言中的工作方式类似.但还有一些差异应引起注意. 声明数组时,方括号 ([]) 必须 ...查看


  • 一种基于元数据仓储与信息资源目录的信息资源管理方法
  • 作者:王宏鼎张智江张范朱小燕 图书情报工作 2009年01期 [分类号]TP315 1 引言 经过多年的信息化建设,我国金融.电信等行业积累了大量信息资源,如何有效开发利用它们已成为我国当前信息化工作的重点[1].目前国内企业信息资源的现状 ...查看


热门内容