数据结构_顺序表SeqList(C++

数据结构_SeqList顺序表(C++实现

前言&注意事项
  1. 有些函数没有修改成员数据的要求,防止成员函数被修改,将只有读取要求的函数设为常函数(只读函数
  2. 用 C++实现,有很多优势,其中一个就是对象可以直接访问并修改数据成员,不用再想要修改的时候再传地址什么的
  3. 其他注意事项在代码注释以及code日记中体现
顺序表实现方法

seqList.h

#include<iostream>
#include<cassert>

class outofsize{};//专门作为异常信息的类(用于异常处理抛出);非法访问
class nullList{};//链表为空
class nullPointer{};//空指针

using namespace std;

template<class slDataType>
class seqList
{
private:
	slDataType* elem;//用数组实现顺序表
	int size;//顺序表实际大小
	int capacity;//顺序表容量(能存储的除了哨兵位的头结点之外的实际有效数据的个数
	void doubleCapacity();//扩容函数;不过这里没必要单独写出来,只有在添加数据的时候有可能会调用到,其他时候不会用到,所以不会产生函数的复用,不用单独构建这个函数,直接包含在添加数据的函数里面就行
public:
	seqList(int Size = 10);//初始化顺序表

	bool seqListEmpty()const;//判空,空则返回真,否则返回假

	bool seqListFull()const;//判满

	void seqListPushHead(slDataType x);//头插

	void seqListPushBack(slDataType x);//尾插

	void seqListPopHead();//头删

	void seqListPopBack();//尾删

	void seqListInsert(int pos , slDataType &data);//在任意位置pos插入;此处对元素数据运用了引用,不用再构建形参局部变量,可以减少一点空间开辟,不过个人感觉没有也无伤大雅

	void seqListErase(int pos);//删除pos的元素

	void seqListRemove(int pos, slDataType &e);//删除pos处的元素,并赋值给e(这里才体现引用的用处

	slDataType seqListGet(int pos)const;//返回pos处的元素

	int seqListFind(slDataType& data)const;//返回值等于data的元素的位置,没有则返回0

	int seqListLength()const;//返回顺序表长度

	void seqListDestory();//清除顺序表,使其成为空表

 ~seqList();//析构函数
};


seqList.cpp

#include"seqList.h"

template<class slDataType>
seqList<slDataType>::seqList(int Size)//初始化顺序表
{
	this->elem = new slDataType[Size];//开辟动态数组
	if (!elem)
		throw nullPointer();
	this->size = 0;
	this->capacity = Size-1;//保留第一个元素作为哨兵位的头结点(不过个人认为在顺序表这里没有必要,链表那里才能体现出哨兵位头结点的好处)
} 

template<class slDataType>
void seqList<slDataType>::doubleCapacity()//扩容函数
{
	assert(elem);//感觉判空的时候不如直接用assert,因为为了判空就用异常处理有些大材小用,而且只在判空的时候用assert,这样就直到程序一中断就说明是空指针
	//所以关于指针可能为空的情况,我在除了这个函数之外的地方都用的assert,这个用异常处理结构太麻烦了,直接暴力检查就ok

	slDataType* newElem = new slDataType[capacity * 2];

	if (!newElem)
		throw nullPointer();

	for (int i = 1;i < size; i++)
	{
		newElem[i] = elem[i];
	}

	delete []elem;
	elem = newElem;
	capacity = capacity * 2 - 1;//第一个结点要留给哨兵位,capacity是实际能存储的有效数据的个数
	//到了这里,感觉写顺序表用哨兵位的头结点真的是,麻烦又没有必要
}

template<class slDataType>
bool seqList<slDataType>::seqListEmpty()const//判空,空则返回真,否则返回假
{
	assert(elem);

	return size == 0;
}

template<class slDataType>
bool seqList<slDataType>::seqListFull()const//判满
{
	assert(elem);

	return size == capacity;
}

template<class slDataType>
void seqList<slDataType>::seqListPushHead(slDataType x)//头插
{
	assert(elem);

	if (size == capacity)
		doubleCapacity();//顺序表满了就扩容
	for (int i = size + 1; i > 1; i --)
	{
		elem[i] = elem[i - 1];
	}
	elem[1] = x;
	size++;
}

template<class slDataType>
void seqList<slDataType>::seqListPushBack(slDataType x)//尾插
{
	assert(elem);

	if (size == capacity)
		doubleCapacity();
	size++;
	elem[size] = x;
}

template<class slDataType>
void seqList<slDataType>::seqListPopHead()//头删
{
	assert(elem);

	if (size != 0)
	{
		for (int i = 1; i < size; i++)
			elem[i] = elem[i + 1];
		size--;
	}
	else
	{
		throw nullList();
	}
}

template<class slDataType>
void seqList<slDataType>::seqListPopBack()//尾删
{
	assert(elem);

	if (size != 0)
	{
		size--;
	}
	else
	{
		throw nullList();
	}
}

template<class slDataType>
void seqList<slDataType>::seqListInsert(int pos, slDataType& data)//在任意位置pos插入
{
	assert(elem);

	if (pos > size + 1 || pos < 1)			//pos=1的时候是头插,=size+1的时候是尾插
		throw outofsize();
	if (size == capacity)
		doubleCapacity();
	for (int i = size + 1; i > pos; i--)
	{
		elem[i] = elem[i - 1];
	}
	elem[pos] = data;
	size++;
}

template<class slDataType>
void seqList<slDataType>::seqListErase(int pos)//删除pos的元素
{
	assert(elem);

	if (pos > size + 1 || pos < 1)			//pos=1的时候是头删,=size+1的时候是尾删
		throw outofsize();
	if (size != 0 )
	{
		for (int i = pos; i < size; i++)
			elem[i] = elem[i + 1];
		size--;
	}
	else
	{
		throw nullList();
	}
}

template<class slDataType>
void seqList<slDataType>::seqListRemove(int pos, slDataType& e)//删除pos处的元素,并赋值给e(这里才体现引用的用处
{
	assert(elem);

	if (pos > size + 1 || pos < 1)			
		throw outofsize();

	e = elem[pos];
	seqListErase(pos);
}

template<class slDataType>
slDataType seqList<slDataType>::seqListGet(int pos)const//返回pos处的元素
{
	assert(elem);

	if (pos > size + 1 || pos < 1)			
		throw outofsize();
	return elem[pos];
}

template<class slDataType>
int seqList<slDataType>::seqListFind(slDataType& data)const//返回值等于data的元素的位置,没有则返回0(这里采用了一个比较有意思的方式
{
	assert(elem);

	int i;
	elem[0] = data;						//将需要查找的值赋给哨兵位头结点,哨兵位头结点中的数据不属于顺序表中的数据
	for (i = size; i >= 0; i--)		//这样的话只需要遍历一遍就好了,没找到的话就会遍历到底,i就直接等于0,比较巧妙
		if (elem[i] == data)
			break;
	return i;
}

template<class slDataType>
int seqList<slDataType>::seqListLength()const//返回顺序表长度
{
	assert(elem);

	return size;
}

template<class slDataType>
void seqList<slDataType>::seqListDestory()//清除顺序表,使其成为空表
{
	assert(elem);
	delete[]elem;
	elem = NULL;
	size = 0;
	capacity = 0;
}
总结
结束

That’s all, thanks for reading!💐

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值