用数组实现线性表

对于线性结构,有两种保存的方法,一种是使用C语言中内置的数组,这样的结构成为顺序表;另一种使用指针,这样的结构成为链表。

对于线性结构,有12种基本的操作,分别是:初始化、删除、清空、判断是否为空、遍历、求表的长度、求某个元素在表中的位置、返回特定序号的元素、求某个元素的前一个元素、求某个元素的后一个元素、插入一个元素、删除一个元素。

这一小节介绍如何利用数组实现线性表。

先看程序:

#include <stdio.h>
#include <malloc.h>

typedef int ElemType;


typedef struct arraylist
{

	//实际存放元素的数组
	ElemType *Array;
	//数组中已经使用了多少元素
	int length;
	//数组的容量
	int size;

}arrayList;

//初始化顺序表:给出初始化长度
bool initialArray(arrayList *arrLst,int len)
{
	arrLst->length = 0;
	arrLst->size = len;	
	arrLst->Array = (ElemType*)malloc(len*sizeof(ElemType));
	if(NULL == arrLst->Array)
		return false;
	else
		return true;

}

//删除顺序表
void deleteArray(arrayList *arrLst)
{
	arrLst->length = 0;
	arrLst->size = 0;
	free(arrLst->Array);
	arrLst->Array = NULL;
}

//清空顺序表
void clearArray(arrayList *arrLst)
{
	arrLst->length = 0;
}

//判断是否为空
bool is_empty(arrayList *arrLst)
{
	
	if(0 == arrLst->length)
	{
		printf("the arrayList is empty!\n");
		return true;
	}
	else
	{
		printf("the arrayList is not empty!\n");
		return false;		
	}
}

//求有多少个元素
int arrayLength(arrayList *arrLst)
{
	return arrLst->length;
}

//取出某个元素
bool getElem(arrayList *arrLst,int index,ElemType *e)
{
	if(index < 0 || index > arrayLength(arrLst)-1)
		return false;
	else
	{
		*e = arrLst->Array[index];
		return true;
	}

}

//遍历顺序表,并打印
void printArray(arrayList *arrLst)
{
	printf("array elements are: ");
	for(int i = 0; i < arrayLength(arrLst);++i)
	{
		printf("%d\t",arrLst->Array[i]);
	}
	printf("\n");
}

//判断某个元素的位置
int locateElem(arrayList *arrLst,ElemType e)
{
	for(int i = 0; i < arrayLength(arrLst);++i)
	{
		if(e == arrLst->Array[i])
			return i;
	}
	return -1;

}

//求某个元素的前驱:如果没找到返回-2;如果是第一个元素。返回-1;否则返回前驱元素的下标
int preElement(arrayList *arrLst,ElemType e,ElemType *preElem)
{
	for(int i = 0 ; i < arrayLength(arrLst); ++i)
	{
		//如果找到了
		if(e == arrLst->Array[i])
		{
			//如果是第一个元素
			if(0 == i)
			{
				return -1;
			}
			else
			{
				*preElem = arrLst->Array[i-1];
				return i-1;
			}
		}
	}
	return -2;
}


//求某个元素的后继:如果没找到,返回-2,如果是最后一个元素,返回-1;否则返回后继元素的下标
int nextElement(arrayList *arrLst,ElemType e,ElemType *nxtElem)
{
	for(int i = 0; i < arrayLength(arrLst); ++i)
	{
		if(e == arrLst->Array[i])
		{
			if(arrayLength(arrLst) -1 == i)
			{
				return -1;
			}
			else
			{
				*nxtElem = arrLst->Array[i+1];
				return i+1;
			}
		}
	}
	return -2;
}

//将元素插入到指定位置
bool insertElem(arrayList *arrLst,int index ,ElemType e )
{
	//先判断插入位置是否合法
	if(0 > index ||  arrayLength(arrLst) < index)
		return false;

	//如果顺序表存储空间已满,则需要重新分配内存
	if(arrLst->length == arrLst->size)
	{
		arrLst->Array = (ElemType*)realloc(arrLst->Array,2*arrLst->size*sizeof(arrayList));
		if(NULL == arrLst->Array)
			//分配失败,程序退出
			return false;
		else
			//分配成功,扩容
			arrLst->size *= 2;
	}
	//将插入点之后的元素后移
	for(int i = arrayLength(arrLst); i > index; --i)
		arrLst->Array[i] = arrLst->Array[i-1];
	//插入元素
	arrLst->Array[index] = e;
	//顺序表长度自增
	++arrLst->length;
	return true;
}


bool deleteElem(arrayList *arrLst,int index ,ElemType *e)
{
	if(index < 0 || index > arrayLength(arrLst)-1)
		return false;
	*e = arrLst->Array[index];
	//将删除点的元素依次左移
	for(int i = index; i < arrayLength(arrLst);++i)
	{
		arrLst->Array[i] = arrLst->Array[i+1];
	}
	--arrLst->length;;
	return true;
}


大部分程序都很简单,唯一需要说明的是,再插入元素时,如果线性表已满,需要重新分配内存空间,新分配的内存空间设定为原来的2倍。这个倍数也不是我随便给出的,我是参考C++中STL里面的vector给出的。相信那些专家,肯定考虑了倍数过小而导致多次分配内存与内存分配太大的折中,我也就照猫画虎的这样做了。

其他的复杂的操作,大多数都能通过这些基本操作来完成,这里就不在列出了。

我们可以看出,利用数组来表示线性结构,最大的优点在于由于数组是连续储存的,所以随机访问速度非常快,只需要用数组的首地址+下标*sizeof(结构体)就能计算指定元素的地址了。而它的缺点也很明显:就是插入、删除时效率很低,因为要移动大量的元素,甚至需要重新分配内存。

最后说一句,程序是没有标准答案的,我自己写的程序也难免有各种错误,如果指出错误,我将不胜感激。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值