线性表的数组实现

线性表是一种基础的数据结构,我们编写该数据结构需要实现几个基本的功能:

  1. 新建线性表
  2. 插入元素到线性表中
  3. 删除线性表的某一个元素
  4. 寻找某一个元素
  5. 判短是否满
  6. 改变长度
  7. 输出线性表

还有一些"高阶"的功能:

  1. 两个线性表的合并
  2. 删除线性表一段范围内的元素

线性表类

class List
{
private:
	int *list;
	int size;     //元素个数
	int MAXSIZE;  //数组的最大长度
public:
	List(int ms = 0);//新建线性表
	void InsertList(int item, int rc);//在rc的位置插入item
	void DeleteList1(int item);//删除值为item的元素
	void DeleteList2(int rc);//删除位置为rc的元素
	void DeleteList3(int x, int y);//删除位置位于x和y之间的元素
	int FindList(int item);//寻找值为item的元素,并返回其位置
	void OutputList();//输出线性表
	bool IsFull() { return size == MAXSIZE; }//判空
	void ChanegLenth(int size);//将线性表的长度改为size
	List & operator + (List &a);//重载+,使两线性表合并
	int ReturnSize() { return size; }
	int ReturnElement(int i) { return list[i]; }
	//有序--升序
};

基本的信息都在注释里面

新建线性表函数

新建线性表函数在这里就是线性表类的构造函数
需要传入参数ms,为初始化线性表的长度

List::List(int ms)
{//ms为数组的长度
	list = new int[ms];
	size = 0;
	MAXSIZE = ms;
}

利用new函数创建一个长度为ms的int型数组,在把数组的地址赋给list(成员变量)

寻找函数

因为后面的一些函数需要内部调用该函数,所以先写这个寻找函数
需要传入参数item,会返回item的位置

int List::FindList(int item)
{//item为要找的元素
	for (int i = 0; i < size; i++)
	{
		if (list[i] == item)
			return i;
	}

	return -1;//无该元素
}

若发现返回的是-1,则说明没有该函数
已知问题:只能找到值为item的第一个元素,后面值为item的元素是找不到的
如果你有解决办法,欢迎告诉我

改变长度函数

改变长度的思路是new一个长度为新长度的数组,在把原数组的数据一个个的复制过来。
其实还可以用malloc和realloc的组合,这样不用一个个复制过去的操作

void List::ChanegLenth(int size)
{//size为改变之后的大小,可能变小也可能变大
	int *NewList = new int[size];
	int Lenth = this->size < size ? this->size : size;
	for (int i = 0; i < Lenth; i++)
	{
		NewList[i] = list[i];
	}
	this->MAXSIZE = size;
	delete[] list;
	list = NewList;
}

Lenth的值取决于新旧长度那个小,如果新地址小的话,就只会复制数组的一部分过去
需要将之前的数组delete掉,然后在赋新地址

插入函数

插入函数输入要插入的元素值item和插入的位置rc,就可以将item插入rc的位置

void List::InsertList(int item, int rc)
{//item为插入的元素,rc为插入的位置,!!!!不是数组的下标,这里从1开始!!!!!
	if (IsFull())
		ChanegLenth(MAXSIZE + ADD_SIZE);

	for (int i = size; i > rc - 1; i--)
	{
		list[i] = list[i - 1];
	}

	list[rc - 1] = item;
	size++;
}

插入的最后不要忘记将size加一

删除函数

从类的定义可以看到,这里的删除函数有两个版本

  1. 输入位置然后删除
  2. 输入元素值然后删除

线性表的删除就是从删除位开始,全部向前移一位,就可以把要删除的元素填掉

输入位置然后删除


void List::DeleteList2(int rc)
{//rc为删除元素的位置,!!!!!同上!!!!!
	for (int i = rc; i < size - 1; i++)
	{
		list[i] = list[i + 1];
	}
	size--;
}

输入元素值然后删除
这个方法完全基于前面的函数
先调用寻找函数找出位置,再调用上面的输入位置的删除函数就完成了

void List::DeleteList1(int item)
{//item为要删除的的元素
	int location = FindList(item);
	if (location != -1)
	{
		DeleteList2(location + 1);
	}
	else
	{
		throw "无法找到该元素";
	}
}

这里加了一个throw,可以在元素不存在的时候抛出异常

输出函数

输出函数就是利用循环,遍历输出线性表的元素

void List::OutputList()
{
	cout << "该顺序表的元素如下:" << endl;
	for (int i = 0; i < size; i++)
	{
		cout << list[i] << "\t";
	}
	cout << endl << endl;
}

判断是否满的函数

判空就是利用成员变量size,如果size等于MAXSIZE,就说明线性表是满的

因为函数很短,所以用了内联函数

bool IsFull() { return size == MAXSIZE; }
//类里的定义

删除一定范围的元素

void List::DeleteList3(int x, int y)
{//x为开始,y结束,删除范围包括x和y  !!!!!!x和y的意义同上!!!!
	if (x < y && y <= size)
	{
		for (int i = x - 1; i < y - 1 && i < size - 1; i++)
			{
				list[i] = list[i + y - x + 1];
			}
			size = size - (y - x + 1);
	}
	else
	{
		throw "输入的范围非法";
	}
}

x到y之间一共有x-y+1长度的元素,要删除这个范围,就需要把后面相同范围的元素一齐向前移
有两种可能

  1. 在y之后有足够的长度可以填满x到y的区间
  2. 在y之后没有足够的长度可以填满x到y的区间,提前遇到了线性表的尾巴

这两种情况的判断写在for循环的判断里面

 i < y - 1 && i < size - 1

如果提前遇到线性表尾,就会不满足第二个条件,结束循环,如果有足够的长度,就不会触发第二个判断,等到移动了x-y+1个元素后,触发第一个条件,结束循环。

线性表的合并

List & List::operator + (List &a)
{//重载运算符,直接 + 就行
	List t(5);
	int size_1 = this->size;
	int size_2 = a.ReturnSize();

	int Element = 0;
	
	int i = 0;
	int j = 0;

	for (; i < size_1, j < size_2;)
	{
		if (list[i] < a.ReturnElement(j))
		{
			Element = list[i];
			i++;
		}
		else
		{
			Element = a.ReturnElement(j);
			j++;
		}
		if (i + j == 1 || t.ReturnElement(t.ReturnSize() - 1) != Element)
			t.InsertList(Element,t.ReturnSize() + 1);
	}

	return t;
}

这个函数是需要线性表有序的!!!
利用运算符重载,可以直接用+号就可以合并两个线性表

开始先创建一个线性表,用来储存合并后的线性表,长度为5(这个是随便写的,任意合法的长度都是可以的)
同时遍历两个线性表,这里我设定的有序是升序,先比较两个线性表的第一个,把最小的一个放入新建的线性表的第一个,在把i或j加1,以此循环
最后返回新建的线性表

函数的调用

int main()
{
	List a(5); // 初始化顺序表
	cout << "初始的顺序表为0-49" << endl;
	for (int i = 0; i < 50; i++)
	{
		a.InsertList(i, i + 1);
	}//调用插入函数
	a.OutputList(); //输出

	cout << "删除元素值为10,20,30的元素:" << endl;
	a.DeleteList1(10);
	a.DeleteList1(20);
	a.DeleteList1(30);
	a.OutputList(); //输出

	cout << "删除位置为25的元素" << endl;
	a.DeleteList2(25);
	a.OutputList();

	List b(a); //新建一个顺序表,用于后面的加法

	cout << "删除位置为5-20之间的元素,包括5和20" << endl;
	a.DeleteList3(5, 20);
	a.OutputList();//输出


	cout << "两个顺序表的加法" << endl;
	List c = a + b;
	c.OutputList();//输出

	return 0;
}

简单的调用上面的各种函数,较为简单,就不一一讲解了

欢迎指错:)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值