可扩容的线性表的C++实现

头文件:线性表的定义和包含的成员函数

#pragma once

typedef int ElemType;
const int DefaultCapacity = 5; 

class SequenceTable {
private:
	ElemType *data;
	int length;
	int capacity;
public:
	//建立线性表
	void CreateList(ElemType a[], int n);
	//初始化线性表
	void InitList();
	//销毁线性表
	void DestroyList();
	//判断线性表是否为空
	bool ListEmpty();
	//求线性表的长度
	int ListLength();
	//输出线性表
	void DispList();
	//求线性表中某个数据元素的值,
	bool GetElem(int, ElemType&);
	//求某个元素的位置
	int LocateElem(ElemType);
	//插入数据
	bool ListInsert(int, ElemType);
	//删除数据
	bool ListDelete(int, ElemType&);
	//扩容
	bool ListExpansion(int cap);
	//缩容
	bool ListShrinkage();
	//批量添加
	bool ListInsertAll(int ,ElemType*,int);
	//批量删除
	bool ListDeleteAll(int, int);
	//获取当前容量
	int ListCapacity();
};

部分函数实现逻辑

扩容ListExpansion(int )

扩容采用一个参数和原容量的1.5倍值进行比较,取较大值为扩容后的容量。开辟空间后将元素复制进去,并让data域指向新数组即可。

bool SequenceTable::ListExpansion(int cap)
{
	int newCapacity = capacity*1.5;//扩大1.5倍
	if (newCapacity < cap) newCapacity = cap;
	ElemType* temp = new ElemType[newCapacity*sizeof(int)];

	for (int i = 0; i < length; i++)
		temp[i] = data[i];

	data = temp;
	capacity = newCapacity;
	return true;
}
缩容ListShrinkage()

对需要缩容的线性表,采用缩小为原来的一半的策略。缩容过程与扩容过程基本相同,只是需要注意最后要更改当前容量capacity 的值。

//缩容
bool SequenceTable::ListShrinkage()
{
	if (capacity <= DefaultCapacity) return true;

	int newCapacity = capacity >> 1;
	if (newCapacity < DefaultCapacity) newCapacity = DefaultCapacity;
	ElemType* temp = new ElemType[newCapacity];
	for (int i = 0; i < length; i++)
		temp[i] = data[i];

	data = temp;
	capacity = newCapacity;
	return true;
}
有参构造函数CreateList(ElemType, int)

通过数组构造线性表,关于构造的过程都应该对容量进行控制,此处通过将传入的数组大小n与默认容量比较,取较大值,保证数组最低容量为DefaultCapacity


void SequenceTable::CreateList(ElemType a[], int n)
{
	if (n > DefaultCapacity) {
		data = new ElemType[n];
		capacity = n;
	}
	else {
		data = new ElemType[DefaultCapacity]; 
		capacity = DefaultCapacity;
	}

	for (int i = 0; i < n; i++)
		data[i] = a[i];
	length = n;
}
初始化函数InitList( )

使用默认容量,并对类中成员capacitylength 赋初值。

//初始化
void SequenceTable::InitList()
{
	data = new ElemType[DefaultCapacity];
	capacity = DefaultCapacity;
	length = 0;
}
获取某个元素第一次出现的位置LocateElem(ElemType)
int SequenceTable::LocateElem(ElemType e)
{
	for (int i = 0; i < length; i++) {
		if (data[i] == e)
			return i;
	}
	//如果不存在该元素,
	return -1;
}
插入一个元素ListInsert(int , ElemType )

插入过程需要对插入位置下标进行检查,同时对容量进行检查,如果需要扩容,传入一个0使得默认扩容为1.5倍。元素插入的方法采用后移,结束后length需要加一。

bool SequenceTable::ListInsert(int position, ElemType e)
{
	if (position < 0 || position >= length) {
		cout << "插入过程下标越界" << endl;
		return false;
	}
	if (length >= capacity)
		ListExpansion(0);

	for (int i = length; i > position; i--)
		data[i] = data[i - 1];
	data[position] = e;
	++length;
	return true;
}
删除一个元素ListDelete(int, ElemType&)

删除元素同插入元素一样,需要对下标进行检查,元素删除采用其之后元素前移的方式。删除后进行缩容判断并处理。

//position为待删除元素的下标,e为被删除的元素
bool SequenceTable::ListDelete(int position, ElemType&e)
{
	if (position < 0 || position >= length)
		return false;

	e = data[position];
	for (int i = position; i < length - 1; i++) {
		data[i] = data[i + 1];
	}
	length--;

	if (length * 2 < capacity)
		ListShrinkage(); 

	return true;
}
批量添加ListInsertAll(int, ElemType*,int )

需要对参数是否合法进行判断,对是否需要扩容进行判断。然后采用先将原来数组的index位置之后的元素(包括index)后移n个位置,然后将array中的元素放进腾出的空间中。

bool SequenceTable::ListInsertAll(int index, ElemType*array,int n)
{
	if (index < 0 || index >= length) return false;

	if (n + length > capacity)
		ListExpansion(n + length);

	for (int i = length - 1; i >= index; i--) {
		data[i + n] = data[i];
	}
	int i = 0;
	while (i < n) {
		data[index++] = array[i];
		i++;
	}
	length += n;

	return true;
}
//
批量删除ListDeleteAll(int , int )

对于参数做判断,并在删除元素后进行缩容判断。删除过程采用前移方式,将end(包括end)之后的元素前移begin-end个位置。

//删除[begin,end) 之间的所有元素
bool SequenceTable::ListDeleteAll(int begin, int end)
{
	if(begin>=end||begin<0||end>length)
	return false;

	int n = end - begin;//待删除的元素个数
	for (int i = begin; i < length; i++) {
		data[i] = data[i + n];
	}
	length -= n;
	//判断是否需要缩容
	if (length * 2 < capacity)
		ListShrinkage();

	return true;
}

部分简单函数的实现



//销毁线性表
void SequenceTable::DestroyList()
{
	delete[] data;
}
//判空
bool SequenceTable::ListEmpty()
{
	return length==0;
}
//当前表中元素长度
int SequenceTable::ListLength()
{
	return length;
}
//输出
void SequenceTable::DispList()
{
	if (ListEmpty()) return;
	for (int i = 0; i < length; i++)
		cout << data[i] << " ";
	cout << endl;
}
//获取某个位置的元素,将其通过e传出去
bool SequenceTable::GetElem(int position, ElemType& e)
{
	if(position<0|| position>=length) 
	return false;
	else {
		e = data[position];
		return true;
	}
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值