您的位置:首页 > 理论基础 > 数据结构算法

数据结构二:线性表的顺序结构实现

2014-10-26 10:49 603 查看
此程序根据高一凡大神的源程序修改而成。
/*************************************************************
FileName:c2-1.h
Function:定义线性表的动态分配顺序存储结构(动态分配的一维数组)
*************************************************************/

#pragma	once

#ifndef __C2_1_H__
#define __C2_1_H__

#define LIST_INIT_SIZE	10		// 线性表存储空间的初始分配量
#define LIST_INCREMENT	2		// 线性表存储空间的分配增量

typedef int ElemType;	//定义抽象数据类型ElemType在本程序中为整型

struct SqList
{
ElemType * elem;	// 存储空间基址
int length;			// 当前长度
int listsize;		// 当前分配的存储容量(以sizeof(ElemType)为单位)
};

#endif


/*************************************************************
FileName:bo2-1.h
Function:顺序表示的线性表的基本操作(12个),包括算法2.3,2.4,2.5,2.6
*************************************************************/

#pragma	once

#ifndef _BO2_1_H__
#define _BO2_1_H__

#include "c1.h"
#include "c2-1.h"

// 构造一个空的顺序线性表
void InitList_Sq(SqList &L);

// 销毁顺序线性表L
void DestroyList_Sq(SqList &L);

// 将顺序线性表L重置为空表
void ClearList_Sq(SqList &L);

// 操作结果:若 L为空表,则返回 TRUE;否则返回 FALSE
Status ListEmpty_Sq(SqList L);

// 返回顺序顺序线性表中数据元素的个数
int ListLength_Sq(SqList L);

// 用e返回L中第i个数据元素的值
Status GetElem_Sq(SqList L, int i, ElemType &e);

// 返回L中第一个与e满足关系compare()的数据元素的位序
int LocateElem_Sq(SqList L, ElemType e, Status (*compare)(ElemType, ElemType));

// 若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱
Status PriorElem_Sq(SqList L, ElemType cur_e, ElemType &pre_e);

// 若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继
Status NextElem_Sq(SqList L, ElemType cur_e, ElemType &next_e);

// 在L中第i个位置之前插入新的数据元素e,L的长度加1
Status ListInsert_Sq(SqList &L, int i, ElemType e);

// 删除L的第i个数据元素,并用e返回其值,L的长度减1
Status ListDelete_Sq(SqList &L, int i, ElemType &e);

// 依次对L的每个数据元素调用函数vi()
void ListTraverse_Sq(SqList L, void (*vi)(ElemType &));

#endif


/*******************************************************************
FileName:bo2-1.cpp
Function:实现顺序表示的线性表的基本操作(12个),包括算法2.3,2.4,2.5,2.6
*******************************************************************/

#include "c2-1.h"
#include "bo2-1.h"
#include "c1.h"

// 构造一个空的顺序线性表
void InitList_Sq(SqList &L)
{
L.elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if( !L.elem )
exit(OVERFLOW);				// 内存分配失败
L.length = 0;					// 空表长度为0
L.listsize = LIST_INIT_SIZE;	// 初始存储容量
}

// 销毁顺序线性表L
void DestroyList_Sq(SqList &L)
{
free(L.elem);
L.elem = NULL;
L.length = 0;
L.listsize = 0;
}

// 将顺序线性表L重置为空表
void ClearList_Sq(SqList &L)
{
L.length = 0;
}

// 操作结果:若 L为空表,则返回 TRUE;否则返回 FALSE
Status ListEmpty_Sq(SqList L)
{
if( L.length == 0 )
return TRUE;
else
return FALSE;
}

// 返回顺序顺序线性表中数据元素的个数
int ListLength_Sq(SqList L)
{
return L.length;
}

// 用e返回L中第i个数据元素的值
Status GetElem_Sq(SqList L, int i, ElemType &e)
{
if( i < 1 || i > L.length )
return ERROR;
e = *(L.elem + i - 1);
return OK;
}

// 返回L中第一个与e满足关系compare()的数据元素的位序
int LocateElem_Sq(SqList L, ElemType e, Status (*compare)(ElemType, ElemType))
{
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;			// 表示未找到与e匹配的数据元素
}

// 若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱
Status PriorElem_Sq(SqList L, ElemType cur_e, ElemType &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;
}
}

// 若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继
Status NextElem_Sq(SqList L, ElemType cur_e, ElemType &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;
}
}

// 在L中第i个位置之前插入新的数据元素e,L的长度加1
Status ListInsert_Sq(SqList &L, int i, ElemType e)
{
ElemType * newbase, *q, *p;
if( (i < 1) || (i > L.length + 1) )		// i值不合法
return ERROR;
if( L.length >= L.listsize ){			// 当前存储空间已满,增加分配
if( !(newbase = (ElemType *)realloc(L.elem, (L.listsize + LIST_INCREMENT) * sizeof(ElemType))) )
exit(OVERFLOW);					// 内存分配失败
L.elem = newbase;					// 新基址
L.listsize += LIST_INCREMENT;		// 增加存储容量
}
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;
}

// 删除L的第i个数据元素,并用e返回其值,L的长度减1
Status ListDelete_Sq(SqList &L, int i, ElemType &e)
{
ElemType *p, *q;
if( (i < 1) || (i > L.length) )
return ERROR;
p = L.elem + i - 1;				// p为被删除的元素的位置
e = *p;							// 被删除的元素的值赋给e
q = L.elem + L.length - 1;		// 表尾的元素
for( ++ p; p <= q; ++ p)		// 被删除元素之后的元素左移
*(--p) = *p;
L.length --;					// 表长减1
return OK;
}

// 依次对L的每个数据元素调用函数vi()
void ListTraverse_Sq(SqList L, void (*vi)(ElemType &))
{
ElemType *p;
int i;
p = L.elem;
for( i = 1; i <= L.length; i ++ )
vi(*p++);
}


/**************************************************
FileName:func2-3.h
Function: 测试顺序线性表中使用的几个常用的函数
**************************************************/

#pragma once

#ifndef	__FUNC2_3__
#define __FUNC2_3__

#include "c1.h"
#include "c2-1.h"

// 判断是否相等的函数
Status equal(ElemType c1,ElemType c2);

// 根据 a<、 =或 >b,分别返回 -1、 0或 1
int comp(ElemType a,ElemType b);

void print(ElemType c);

void print2(ElemType c);

void print1(ElemType &c);

#endif


/**************************************************
FileName:func2-3.cpp
Function: 实现测试顺序线性表中使用的几个常用的函数
**************************************************/

#include "func2-3.h"
#include "c2-1.h"
#include <stdio.h>

// 判断是否相等的函数
Status equal(ElemType c1, ElemType c2)
{
if(c1==c2)
return TRUE;
else
return FALSE;
}

// 根据 a<、 =或 >b,分别返回 -1、 0或 1
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 print2(ElemType c)
{
printf("%c ", c);
}
void print1(ElemType &c)
{
printf("%d ", c);
}


/**********************************************
Function: 定义结果状态值(OK...)
包含常用头文件

Description: 包含的头文件很多,实际使用的时候
自行修改
**********************************************/
#pragma once

#ifndef __C1_H__
#define __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()
#include<iostream>	// cout cin

//函数结果状态代码
#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

#endif


/********************************************************
FileName: main2-1.cpp
Function: 测试顺序线性表的12种操作函数
********************************************************/

#include "c1.h"
#include "c2-1.h"
#include "bo2-1.h"
#include "func2-3.h"

// 数据元素判定函数 (平方关系 ) , LocateElem() 调用的函数
Status sq(ElemType c1, ElemType c2);

// ListTraverse() 调用的另一函数 (元素值加倍 )
void dbl(ElemType &c);

void main()
{
SqList L;
ElemType e,e0;
Status i;
int j,k;

// 测试初始化线性表的函数:InitList_Sq()
InitList_Sq(L);
printf("初始化 L后: L.elem=%u L.length=%d L.listsize=%d\n\n",L.elem,L.length,L.listsize);

// 通过在表头前插入元素,测试插入新元素的函数:ListInsert_Sq()
for(j=1;j<=5;j++)
i=ListInsert_Sq(L,1,j);
printf("在 L的表头依次插入 1~ 5后: *L.elem=");
for(j=1;j<=5;j++)
std::cout<<*(L.elem+j-1)<< ' ';
std::cout<<std::endl;
printf("L.elem=%u L.length=%d L.listsize=%d\n\n",L.elem,L.length,L.listsize);

// 测试判断线性表是否为空的函数:ListEmpty_Sq()
i=ListEmpty_Sq(L);
printf("L是否空: i=%d(1: 是 0: 否 )\n\n",i);

// 测试清空线性表的函数:ClearList_Sq()
ClearList_Sq(L);
printf("清空 L后: L.elem=%u L.length=%d L.listsize=%d",L.elem,L.length,L.listsize);
i=ListEmpty_Sq(L);
printf("L是否空: i=%d(1: 是 0: 否 )\n\n",i);

// 通过在表尾后插入元素,测试插入新元素的函数:ListInsert_Sq()
for(j=1;j<=10;j++)
ListInsert_Sq(L,j,j);
printf("在 L的表尾依次插入 1~ 10后: *L.elem=");
for(j=1;j<=10;j++)
std::cout<<*(L.elem+j-1)<< ' ' ;
std::cout<<std::endl;
printf("L.elem=%u L.length=%d L.listsize=%d\n",L.elem,L.length,L.listsize);

// 测试当插入的数据元素超过初始分配的内存空间的情况
ListInsert_Sq(L,1,0);
printf("在 L的表头插入 0后: *L.elem=");
for(j=1; j<=ListLength_Sq(L); j++)		// ListLength(L) 为元素个数
std::cout<<*(L.elem+j-1)<< ' ' ;
std::cout<<std::endl;
printf("L.elem=%u(有可能改变 ) L.length=%d(改变 ) L.listsize=%d(改变 )\n\n", L.elem, L.length, L.listsize);

// 测试获取线性表元素的函数:GetElem_Sq()
GetElem_Sq(L,6,e);
printf("第 6个元素的值为 %d\n\n",e);

// 测试返回L中第一个与e满足关系compare()的数据元素的位序的函数:LocateElem_Sq()
for(j=10;j<=11;j++)
{
k=LocateElem_Sq(L,j,equal);
if(k)			// k不为 0,表明有符合条件的元素,且其位序为 k
printf("第 %d个元素的值为 %d\n",k,j);
else
printf("没有值为 %d的元素 \n",j);
}

for(j=3;j<=4;j++)
{
k=LocateElem_Sq(L,j,sq);
if(k)			// k不为 0,表明有符合条件的元素,且其位序为 k
printf("第 %d个元素的值为 %d的平方 \n",k,j);
else
printf("没有值为 %d的平方的元素 \n",j);
}

// 测试找前驱的函数:PriorElem_Sq()
for( j=1; j<=2; j++ )			// 测试头两个数据
{
GetElem_Sq(L, j, e0);		// 把第 j个数据赋给 e0
i=PriorElem_Sq(L, e0, e);	// 求 e0的前驱
if( i == INFEASIBLE )
printf("元素 %d无前驱 \n",e0);
else
printf("元素 %d的前驱为 %d\n",e0,e);
}

// 测试找后继的函数:NextElem_Sq()
for( j = ListLength_Sq(L) - 1; j <= ListLength_Sq(L); j ++ )	// 最后两个数据
{
GetElem_Sq(L, j, e0);		// 把第 j个数据赋给 e0
i=NextElem_Sq(L, e0, e);	// 求 e0的后继
if(i==INFEASIBLE)
printf("元素 %d无后继 \n",e0);
else
printf("元素 %d的后继为 %d\n",e0,e);
}

// 测试删除线性表元素的函数:ListDelete_Sq()
k=ListLength_Sq(L);				// k为表长
for( j = k + 1; j >= k; j --)
{
i = ListDelete_Sq(L, j, e);		// 删除第 j个数据
if( i == ERROR )
printf("\n删除第 %d个元素失败 \n",j);
else
printf("删除第 %d个元素成功,其值为 %d\n\n", j, e);
}

// 测试遍历线性表的函数:ListTraverse_Sq()
printf("依次输出 L的元素: ");
ListTraverse_Sq(L, print1);		// 依次对元素调用 print1() ,输出元素的值
printf("\n");

printf("L的元素值加倍后: ");
ListTraverse_Sq(L, dbl);		// 依次对元素调用 dbl() ,元素值乘 2
ListTraverse_Sq(L, print1);
printf("\n\n");

// 测试销毁线性表的函数:DestroyList_Sq()
DestroyList_Sq(L);
printf("销毁 L后: L.elem=%u L.length=%d L.listsize=%d\n",L.elem,L.length,L.listsize);

getchar();
}

// 数据元素判定函数 (平方关系 ) , LocateElem() 调用的函数
Status sq(ElemType c1, ElemType c2)
{
if(c1 == c2*c2)
return TRUE;
else
return FALSE;
}

// ListTraverse() 调用的另一函数 (元素值加倍 )
void dbl(ElemType &c)
{
c *= 2;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息