顺序表(C++实现)

数据结构(面向对象方法与C++语言描述)(第2版)线性表内容整理

顺序表

顺序表是基于数组的线性表的存储表示,其特点是用物理位置上的邻接关系来表示结点间的逻辑关系。

优点:

(1)无需为表示结点间的逻辑关系而增加额外的存储空间,存储利用率高;
(2)可以方便地随机存取表中的任一结点,存储速度快。

缺点:

(1)在表中插入新元素或删除无用元素时,为了保持其他元素的相对次序不变,平均需要移动一半元素,运行效率很低;
(2)由于顺序表要求占用连续的空间,如果预先进行存储分配(静态分配),则当表长度变化较大时,难以确定合适的存储空间大小,若按可能达到的最大长度预先分配表的空间,则容易造成一部分空间长期闲置而得不到充分利用。若实现对表长估计不足,则插入操作可能使表长超过预先分配的空间而造成溢出。如果采用指针方式定义数组,在程序运行时动态分配存储空间,一旦需要,可以用另外一个新的更大的数组来代替原来的数组,这样虽然能够扩充数组空间,但时间开销比较大。

代码实现

环境:vs2019
头文件:LinearList.h,SeqList.h
源文件:main.cpp

LinearList.h代码:

#pragma once

//线性表的抽象基类
template<typename T>
class LinearList {
public:
	LinearList() {};										//构造函数
	~LinearList() {};										//析构函数
	virtual int Size()const = 0;							//求表最大容量
	virtual int Length()const = 0;							//求表长度
	virtual int Search(T& x)const = 0;						//在表中搜索给定值x
	virtual int Locate(int i)const = 0;						//在表中定位第i个元素位置
	virtual bool getData(int i, T& x)const = 0;				//取第i个表项的值
	virtual void setData(int i, T& x) = 0;					//修改第i个表项的值为x
	virtual bool Insert(int i, T& x) = 0;					//在第i个表项插入x
	virtual bool Remove(int i, T& x) = 0;					//删除第i个表项,通过x返回
	virtual bool IsEmpty()const = 0;						//判表空
	virtual bool IsFull()const = 0;							//判表满
	virtual void Sort() = 0;								//排序
	virtual void input() = 0;								//输入
	virtual void output() = 0;								//输出
	//virtual LinearList operator=(LinearList& L) = 0;	//复制
};

SeqList.h代码:

#pragma once

#include 
#include "LinearList.h"

const int defaultSize = 100;

template<typename T>
class SeqList : public LinearList<T> {
protected:
	T* data;										//存放数组
	int maxSize;									//最大可容纳表项的项数
	int last;										//当前已存表项的最后位置(从0开始)
	void reSize(int newSize);						//改变data数组空间的大小
public:
	SeqList(int sz = defaultSize);					//构造函数
	SeqList(SeqList<T>& L);							//拷贝构造函数
	~SeqList() { delete[] data; }					//析构函数
	int Size()const { return maxSize; }				//计算表最大可容纳表项个数
	int Length()const { return last + 1; }			//计算表长度
	int Search(T& x)const;							//搜索x在表中位置,函数返回表项序号
	int Locate(int i)const;							//定位第i个表项,函数返回表项序号
	bool getData(int i, T& x)const					//取第i个表项的值
	{
		if (i > 0 && i <= last + 1) { x = data[i - 1]; return true; }
		else return false;
	}
	void setData(int i, T& x)						//修改第i个表项的值为x
	{
		if (i > 0 && i <= last + 1) data[i - 1] = x;
	}
	bool Insert(int i, T& x);						//在第i个表项插入x
	bool Remove(int i, T& x);						//删除第i个表项,通过x返回
	bool IsEmpty()const								//判表空
	{
		return (last == -1) ? true : false;
	}
	bool IsFull()const								//判表满
	{
		return (last == maxSize - 1) ? true : false;
	}
	void Sort()										//排序
	{

	}
	void input();									//输入
	void output();									//输出
	SeqList<T> operator=(SeqList<T>& L);			//表整体赋值
};

template<typename T>
SeqList<T>::SeqList(int sz)
{
	//构造函数,通过指定参数sz定义数组的长度。
	if (sz > 0)
	{
		maxSize = sz;
		last = -1;									//置表的实际长度为空
		data = new T[maxSize];						//创建顺序表存储数组
		if (data == nullptr)						//动态分配失败
		{
			std::cerr << "存储分配错误!" << std::endl;
			exit(1);
		}
	}
	else
	{
		maxSize = 0;
		last = -1;
		data = nullptr;
		std::cerr << "无效的数组大小!" << std::endl;
		exit(1);
	}	
}

template<typename T>
SeqList<T>::SeqList(SeqList<T>& L)
{
	//拷贝构造函数,用参数表中给出的已有顺序表初始化新建的顺序表。
	maxSize = L.Size();
	last = L.Length() - 1;
	T value;
	data = new T[maxSize];							//创建顺序表存储数组
	if (data == nullptr)							//动态分配失败
	{
		std::cerr << "存储分配错误!" << std::endl;
		exit(1);
	}
	for (int i = 1; i <= last + 1; i++)
	{
		L.getData(i, value);
		data[i - 1] = value;
	}
}

template<typename T>
void SeqList<T>::reSize(int newSize)
{
	//私有函数:扩充顺序表的存储数组空间大小,新数组的元素个数为newSize。
	if (newSize <= 0)								//检查参数的合理性
	{
		std::cerr << "无效的数组大小" << std::endl;
		return;
	}
	if (newSize != maxSize)							//修改
	{
		T* newarray = new T[newSize];				//建立新数组
		if (newarray == nullptr)
		{
			std::cerr << "存储分配错误" << std::endl;
			exit(1);
		}
		int n = last + 1;
		T* srcptr = data;							//源数组首地址
		T* destptr = newarray;						//目的数组首地址
		while (n--) *destptr++ = *srcptr++;			//复制
		delete[] data;								//删除老数组
		data = newarray;							//复制新数组
		maxSize = newSize;
	}
}

template<typename T>
int SeqList<T>::Search(T& x)const
{
	//搜索函数:在表中顺序搜索与给定值x匹配的表项,找到则函数返回该表项是第几个元素,
	//否则函数返回0,表示搜索失败
	for (int i = 0; i <= last; i++)
	{
		if (data[i] == x) return i + 1;				//顺序搜索
	}
	return 0;										//搜索失败
}

template<typename T>
int SeqList<T>::Locate(int i)const
{
	//定位函数:函数返回第i(1<=i<=last+1)个表项的位置,否则函数返回0,表示定位失败。
	if (i >= 1 && i <= last + 1) return i;
	else return 0;
}

template<typename T>
bool SeqList<T>::Insert(int i, T& x)
{
	//将新元素x插入到表中第i(1<=i<=last+1)个表项之后。函数返回插入成功的信息,若插入
	//成功,则返回true;否则返回false。i=0是虚拟的,实际上是插入到第1个元素位置。
	if (last == maxSize - 1) return false;			//表满,不能插入
	if (i < 0 || i > last + 1) return false;		//参数i不合理,不能插入
	for (int j = last; j >= i; j--)
		data[j + 1] = data[j];						//一次后移,空出第i号位置
	data[i] = x;									//插入
	last++;											//最后位置加1
	return true;									//插入成功
}

template<typename T>
bool SeqList<T>::Remove(int i, T& x)
{
	//从表中删除第i(1<=i<=last+1)个表项,通过引用型参数x返回删除的元素值。函数返回删除
	//成功的信息,若删除成功则返回true,否则返回false。
	if (last == -1) return false;					//表空,不能删除
	if (i < 0 || i > last + 1) return false;		//参数i不合理,不能删除
	x = data[i - 1];								//存被删元素的值
	for (int j = i; j <= last; j++)
		data[j - 1] = data[j];						//依次迁移,填补
	last--;											//最后位置减1
	return true;									//删除成功
}

template<typename T>
void SeqList<T>::input()
{
	//从标准输入(键盘)逐个数据输入,建立顺序表
	std::cout << "开始建立顺序表,请输入表中元素个数:";
	while (1)
	{
		std::cin >> last;							//输入元素最后位置
		last--;
		if (last >= 0 && last <= maxSize - 1) break;
		std::cout << "表元素个数输入有误,范围不能超过" << "1-" << maxSize << ":";
	}
	for (int i = 0; i <= last; i++)					//逐个输入表元素
	{
		std::cin >> data[i];
		std::cout << i + 1 << std::endl;
	}
}

template<typename T>
void SeqList<T>::output()
{
	//将顺序表全部元素输出到屏幕上。
	std::cout << "顺序表当前元素最后位置为:" << last << std::endl;
	for (int i = 0; i <= last; i++)
	{
		std::cout << "#" << i + 1 << ":" << data[i] << std::endl;
	}
}

template<typename T>
SeqList<T> SeqList<T>::operator= (SeqList<T>& L)
{
	//重载操作:顺序表整体赋值。若当前调用此操作的表对象为L1,代换形参L的表对象为L2,
	//则使用方式为L1=L2。实现代码可参照拷贝构造函数自行编写。
	if (maxSize != L.Size())
	{
		if(data != nullptr) delete[] data;
		maxSize = L.Size();
		data = new T[maxSize];						//创建顺序表存储数组
	}	
	last = L.Length() - 1;
	T value;
	
	if (data == nullptr)							//动态分配失败
	{
		std::cerr << "存储分配错误!" << std::endl;
		exit(1);
	}
	for (int i = 1; i <= last + 1; i++)
	{
		L.getData(i, value);
		data[i - 1] = value;
	}
	return *this;
}

main.cpp代码:(仅测试输入输出)

#include "SeqList.h"

int main()
{
	SeqList<int> L1;
	L1.input();
	L1.output();
	SeqList<int> L2;
	L2 = L1;
	L2.output();

	return 0;
}

控制台界面:
顺序表(C++实现)_第1张图片

你可能感兴趣的:(数据结构,c++,c语言,开发语言)