线性表的顺序存储结构和实现

头文件 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;			//通过定义不同的类型来定义不同的存储类型

/*线性表的动态分配顺序存储结构 */
#define LIST_INIT_SIZE 100		/* 线性表存储空间的初始分配量 */
#define LISTINCREMENT 10		/* 线性表存储空间的分配增量 */

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 *));

Status ListUnion(SqList *A, SqList B);//例2-1

void MergeList(SqList A, SqList B, SqList *C);

函数实现文件 ADT_SQ_Com.c

#include"head.h"

//线性链表的实现
/* 顺序表示的线性表(存储结构由c2-1.h定义)的基本操作(12个) */

Status InitList(SqList *L)	/* 算法2.3 */
{
	//操作结果:构造一个空的顺序线性表 

	(*L).elem = (ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
	if (!(*L).elem)
	{
		printf("存储空间非配失败!");
		system("pause");
		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重置为空表,线性表中元素的个数n定义为线性表的长度,当n=0时称为空表 

	(*L).length = 0;

	return OK;
}

Boolean 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)
		{
			printf("又一次分配内存失败!");
			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;
}

測试文件 test.c

#include"head.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;
}

//例2-1, 两个线性表合并在一起,即求A=A U B;
Status ListUnion(SqList *A, SqList B)
{
	//初始条件:已知线性表A和线性表B
	//操作结果:将全部在线性表B但不在线性表A中的数据元素插入到线性表A中

	int sB = ListLength(B);//线性表B的长度
	int sA = ListLength(*A);//线性表A的长度
	int i = 0;
	int s = 0, s1 = 0;//返回状态值
	ElemType e;

	for (i = 1; i <= sB; i++)
	{
		s = GetElem(B, i, &e);
		if (s != 0)
		{
			if (!LocateElem(*A, e, comp))
			{
				ListInsert(A, (sA + 1), e);
				sA++;
			}
		}
		else
			return FALSE;
	}
	return OK;
}

//例2-2, 两个线性表合并在一起且非递减排序,线性表中的元素值可反复
void MergeList(SqList A, SqList B, SqList *C)
{
	//初始条件:已知A和B中的数据元素按值非递减排列
	//操作结果:归并A和B得到新的线性表C,C的数据元素也是按值非递减排列

	int sA = 1, sB = 1, sC = 1;
	ElemType e1, e2;
	int A_Len = ListLength(A);
	int B_Len = ListLength(B);
	Status s = 0;

	s = InitList(C);

	while ((sA <= A_Len) && (sB <= B_Len))
	{
		GetElem(A, sA, &e1);
		GetElem(B, sB, &e2);
		if (e1 < e2)
		{
			ListInsert(C, sC, e1);
			sA++;
		}
		else
		{
			ListInsert(C, sC, e2);
			sB++;
		}
		sC++;
	}

	while (sA <= ListLength(A))
	{
		GetElem(A, sA, &e1);
		ListInsert(C, sC, e1);
		sA++;
		sC++;
	}

	while (sB <= ListLength(B))
	{
		GetElem(B, sB, &e2);
		ListInsert(C, sC, e2);
		sC++;
		sB++;
	}
}

void main()
{
	SqList L;
	ElemType e, e0;
	Status i;
	int j, k;
	i = InitList(&L);
	printf("初始化L后:L.elem=%u\tL.length=%d \tL.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\tL.length=%d\tL.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\tL.length=%d\tL.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\tL.length=%d\tL.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(有可能改变)\tL.length=%d(改变)\tL.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);

	system("pause");
}

Running result:

初始化L后:L.elem=5210680       L.length=0      L.listsize=100
在L的表头依次插入1~5后:*L.elem=5 4 3 2 1
L.elem=5210680  L.length=5      L.listsize=100
L是否空:i=0(1:是 0:否)
清空L后:L.elem=5210680 L.length=0      L.listsize=100
L是否空:i=1(1:是 0:否)
在L的表尾依次插入1~10后:*L.elem=1 2 3 4 5 6 7 8 9 10
L.elem=5210680  L.length=10     L.listsize=100
在L的表头插入0后:*L.elem=0 1 2 3 4 5 6 7 8 9 10
L.elem=5210680(有可能改变)      L.length=11(改变)       L.listsize=100(改变)
第5个元素的值为:4
第1个元素的值为3的平方
第1个元素的值为4的平方
元素0无前驱
元素1的前驱为:0
元素9的后继为:10
元素10无后继
删除第12个数据失败
删除的元素值为:10
依次输出L的元素:0 1 2 3 4 5 6 7 8 9
L的元素值加倍后:
0 2 4 6 8 10 12 14 16 18
销毁L后:L.elem=0 L.length=0 L.listsize=0
请按随意键继续. . .
时间: 2024-11-06 07:13:07

线性表的顺序存储结构和实现的相关文章

线性表的顺序存储结构

1.顺序表: 线性表占用的存储空间=n*sizeof(ElemType) n为线性表的长度,ElemType为线性表的元素类型,sizeof(ElemType)为每个元素所占存储空间大小(即字节数) 线性表的顺序存储结构利用数组实现,数组的基本类型是线性表中元素类型,数组大小大于等于线性表的长度. 基本运算实现: (1)建立顺序表 void CreateList(SqList *&L,ElemType a[],int n)    //由a中的n个元素建立顺序表 {  int i;    L=(S

线性表之顺序存储结构实现(上)

一,线性表的概念以及数学定义 1.线性表的概念 零个或多个数据元素的有限序列.首先说明这是一个序列,也就是说数据元素之间是有顺序的,若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他每个元素都有且仅有一个前驱和后继. 2.数学定义 若将线性表记为(a1...ai-1,ai,ai+1....an),则线性表中,ai-1领先于ai,ai领先于ai+1,则称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素,当i=1,2....n-1的时候,ai有且仅有一个直接后继元素,当i=2,3

线性表之顺序存储结构(C语言动态数组实现)

线性表的定义:N个数据元素的有限序列 线性表从存储结构上分为:顺序存储结构(数组)和 链式存储结构(链表) 顺序存储结构:是用一段连续的内存空间存储表中的数据 L=(a1,a2,a3....an) 链式存储结构:是用一段一段连续的内存空间存储表中每一行的数据,段与段之间通过一个引用(指针)相互连接来,形成一个链式的存储结构 看到顺序存储结构的图示,我们可能会马上联想到C语言的数组.是的,数组就是一种典型的顺序存储数据结构.下面我通过一个实例,来实现对顺序存储结构中的数据增.删.改.查的操作. 首

线性表的顺序存储结构之顺序表类的实现_Java

在上一篇博文--线性表接口的实现_Java中,我们实现了线性表的接口,今天让我们来实现线性表的顺序存储结构--顺序表类. 首先让我们来看下顺序表的定义: 线性表的顺序存储是用一组连续的内存单元依次存放线性表的数据元素,元素在内存的物理存储次序与它们在线性表中的逻辑次序相同,即元素ai与其直接前驱ai-1及直接后继ai+1的存储位置相邻.顺序存储的线性表也成为顺序表(sequential list). 顺序表类SeqList提供线性表基于顺序存储结构的一种实现,它有两个私有成员变量table和n,

02.线性表(一)顺序存储结构

顺序存储结构 一.线性表基本概念 1.线性表定义 线性表(list)是指零个或多个数据元素的有限序列,所有数据元素为相同数据类型且一个数据元素可以由多个数据项组成.若将线性表记为(a1,..ai-1,ai,ai+1...,an),线性表元素的个数n(n>0,n=0时为空表)定义为线性表的长度,其中ai-1是ai 的直接前驱元素,ai+1是ai的直接后继元素. 2.线性表的抽象数据类型 ADT 线性表(List) Data 线性表的数据对象集合为{a1,a2,....an},每个元素的类型均匀Da

数据结构之线性表之顺序存储结构(3)

1 前言 经过前两张的理论基础,我相信大家都能简单的明白了数据结构和算法一些常用的概念了,从今天开始我们开始学习数据结构中线性表,一起叩响数据结构的大门. 2 详述 线性表(List):零个或者多个数据元素的有限序列. 如果用数学语言来进行定义: (声明:由于下标不是很好弄出来,所以只能表示下面这种方式了,请见谅!) 若线性表记作(a1,...ai-1,ai,ai+1,...,an),则表中ai-1领先于ai,ai领先于ai+1,称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素.当i

2.2_线性表的顺序存储结构

[线性表的顺序存储从结构] 指的是用一段连续的存储单元一次储存线性表的数据元素. [线性表的顺序存储的结构代码] #define MAXSIZE 20 /*存储空间初始分配量*/ typedef int ElemType; /*ElemType类型依实际情况而定*/ typedef struct { Element data[MAXSIZE]; /*数组存储数据元素,最大值为MAXSIZE*/ int length; /*线性表当前长度为length*/ }SqlList; [线性表的顺序存储结

简要比较线性表的顺序存储结构和链式存储结构

我们分别从存储分配方式.时间性能.空间性能三方面来做对比. 存储分配方式 顺序存储结构用一段连续的存储单元依次存储线性表的数据元素. 单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素. 时间性能 <1>查找 顺序存储结构O(1) 单链表O(n) <2>插入和删除 顺序存储结构需要平均移动表长一半的元素,时间为O(n) 单链表在计算出某位置的指针后,插入和删除时间仅为O(1) 空间性能 顺序存储结构需要预分配存储空间,分大了,容易造成空间浪费,分小了,容易发生溢出. 单链

《大话数据结构》笔记(2)--线性表的顺序存储结构

线性存储结构的Java实现代码: https://github.com/Lyu0709/data-structure/tree/master/src/com/coding/basic/array 第三章 线性表 定义 数学语言 若将线性表记为(a1, ..., ai-1, ai, ai+1, ..., an),则表中ai-1领先于ai,ai领先于ai+1,称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素.当i=1,2,..,n-1时,ai有且仅有一个直接后继,当n=2,3,...,n

线性表的顺序存储结构和链式存储结构

前言 上一篇<栈>中提到了栈的顺序存储结构和链式存储结构,现在就对此做个简单的比较.因为栈是线性表的一种,顺序存储结构和链式存储结构实际是线性表的两种存储方式.而栈和队列都是两种重要的线性表结构.所以本文标题直接为线性表的顺序存储结构和链式存储结构. 开始比较两种不同的存储方式 一.顺序存储结构(也可称为顺序表) 顺序表的特点是逻辑上相邻的数据元素,物理存储位置也相邻,并且,顺序表的存储空间需要预先分配. 优点: (1)方法简单,各种高级语言中都有数组,容易实现. (2)不用为表示节点间的逻辑