线性表是一种基础的数据结构,我们编写该数据结构需要实现几个基本的功能:
还有一些"高阶"的功能:
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加一
从类的定义可以看到,这里的删除函数有两个版本
线性表的删除就是从删除位开始,全部向前移一位,就可以把要删除的元素填掉
输入位置然后删除
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长度的元素,要删除这个范围,就需要把后面相同范围的元素一齐向前移
有两种可能
这两种情况的判断写在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;
}
简单的调用上面的各种函数,较为简单,就不一一讲解了
欢迎指错:)