线性表是n个数据元素的有限序列,数据之间存在顺序关系,一般同一个线性表属于同一类数据对象(例如A~Z的字母表)。线性表存在唯一一个首位元素和末位元素,除了第一个元素和最后一个元素,每个元素存在着一个前驱和一个后继(A的后继是B,B的前驱是A)。线性表主要有顺序表和链表两种存储形式,线性表是一种逻辑结构,顺序表和链表是物理存储结构。本篇主要讲的是顺序表的实现。
顺序表是线性表的顺序表示,用一组地址连续的存储单元依次存储线性表的数据元素,本文主要用数组实现最简单的顺序表。
顺序表的类定义如下:
#include<iostream> using namespace std; #define ok 0 #define error -1 //顺序表类定义 class SeqList { private: int *list; //存储元素的数组 int maxsize; //顺序表可以存储的最大长度 int size; //顺序表的实际长度 public: SeqList(); //构造函数 ~SeqList(); //析构函数,用于回收存储空间 int list_size(); //获取顺序表实际长度,用于增、删等操作 int list_insert(int i, int item); //在i位置插入一个元素item int list_del(int i); //删除i位置的元素 int list_get(int i); //获取i位置的元素 void list_display(); //输出顺序表 }; SeqList::SeqList() { maxsize = 1000; size = 0; list = new int[maxsize]; //创建一个大小为1000的顺序表 } SeqList::~SeqList() { delete []list; //回收空间 }
为了对顺序表进行操作,我们需要增、删、查、改等功能,基础语法这里就不解释了。size=0初始了顺序表的实际大小为0,因为这个时候创建的顺序表是空的,在后续的操作中插入一个数据size便加1,删除一个便减1。
下面是插入功能的实现:
int SeqList::list_insert(int i, int item) { if(size == maxsize || i<1 || i>size+1) return error; //检查顺序表是否已满,输入参数的位置是否在实际范围内 else { int temp; for(temp=size-1; temp>=i-1; temp--) //temp=size-1是因为数组是从0开始的,例如一个数组a有3个元素:a[0],a[1],a[2],此时size=3,最后一个元素下标=size-1 list[temp+1]=list[temp]; //将要插入元素位置的后续元素全部往后移动一个位置,从最后一个元素开始移动 list[i-1]=item; //将插入的元素item覆盖到i个元素的位置上(i-1同理temp) size++; return ok; } }
插入的操作原理是让插入位置后续的元素全部后移一个位置,顺序表实际长度增加1,然后让待插入的元素覆盖插入位置原有的元素。所以对于需要频繁修改的线性表,顺序表需要比较多次的计算,后面会讲的链表的链式存储结构更适合需要高频改动的场景。
需要稍微转换一下思维的就是数组下标是从0开始存储数据的,在注释里我解释了。
下面是删除的操作,删除的原理是让要删除的位置后面的元素一个个覆盖上去,相当于后面的元素全部往前移动一个位置。
int SeqList::list_del(int i) { if(size == 0 || i<1 || i>size+1) return error; else { int temp; for(temp=i-1; temp<size-1; temp++) //从i-1后面的元素全部往前移动1个位置,覆盖掉要删除的元素位置 list[temp]=list[temp+1]; list[size-1]=0; //将最后一个多出来的元素设为0 size--; return ok; } }
下面是其它基本操作:
int SeqList::list_size(){ //获取顺序表实际长度 return size; } void SeqList::list_display() //用于输出整个顺序表 { int i; cout << size << ' '; //首先输出顺序表大小,再输出内容 for(i=0;i<size-1;i++) cout << list[i] << ' '; cout << list[size-1] << ' ' << endl; } int SeqList::list_get(int i) //获取指定位置i的元素值 { if (i<1||i>size+1) return error; else{ cout << list[i-1] << endl; return ok; } }
接下来结合实验题目:
实现顺序表的用C++语言和类实现顺序表
属性包括:数组、实际长度、最大长度(设定为1000)
操作包括:创建、插入、删除、查找
输入
第1行先输入n表示有n个数据,即n是实际长度;接着输入n个数据
第2行输入要插入的位置和新数据
第3行输入要插入的位置和新数据
第4行输入要删除的位置
第5行输入要删除的位置
第6行输入要查找的位置
第7行输入要查找的位置
输出
数据之间用空格隔开
第1行输出创建后的顺序表内容,包括顺序表实际长度和数据
每成功执行一次操作(插入或删除),输出执行后的顺序表内容
每成功执行一次查找,输出查找到的数据
如果执行操作失败(包括插入、删除、查找等失败),输出字符串error,不必输出顺序表内容
样例输入
6 11 22 33 44 55 66
3 777
1 888
1
9
0
5
样例输出
6 11 22 33 44 55 66
7 11 22 777 33 44 55 66
8 888 11 22 777 33 44 55 66
7 11 22 777 33 44 55 66
error
error
44
因为具体操作函数我们在上面已经写好了,接下来在主函数调用就可以了。
int main()
{ int i,t,ln,flag; SeqList sl; cin >> t; for(i=1;i<=t;i++) //输入初始顺序表 { cin >> ln; sl.list_insert(i,ln); } sl.list_display(); //输出第1行:输入的数据 cin >> t >> ln; //第2行输入要插入的位置和新数据 flag = sl.list_insert(t,ln); if (flag==error) cout << "error" << endl; else sl.list_display(); cin >> t >> ln; //第3行输入要插入的位置和新数据 flag = sl.list_insert(t,ln); if (flag==error) cout << "error" << endl; else sl.list_display(); cin >> t; //第4行输入要删除的位置 flag = sl.list_del(t); if (flag==error) cout << "error" << endl; else sl.list_display(); cin >> t; //第5行输入要删除的位置 flag = sl.list_del(t); if (flag==error) cout << "error" << endl; else sl.list_display(); cin >> t; //第6行输入要查找的位置 flag = sl.list_get(t); if (flag==error) cout << "error" << endl; cin >> t; //第7行输入要查找的位置 flag = sl.list_get(t); if (flag==error) cout << "error" << endl; return 0; }
篇幅差不多了,因为本文主要读者是给刚开始学习数据结构的同学,所以更多关于顺序表的操作下一篇会讲。第一篇编程博客文章,虽然是简单的内容但发现写下来发现还是挺需要时间的,不知道开学后有没有空余的时间呢。
作者:Nathaneko