第1关 顺序表基本操作
任务描述
本关任务要求针对线性结构的顺序存储方式完成其七个操作函数,分别实现线性表中数据的插入、删除、扩容、查找、访问、遍历和转置等功能。
相关知识
线性表是最基本的数据结构之一,数据元素之间有序连接。线性表可以采用不同的存储形式,顺序表就是其中之一。顺序表的实现方法简单,可以利用高级语言中的数组实现,元素间的逻辑次序与物理次序一致。
线性表存储在一片连续空间里,并通过data、curLength和maxSize三个元素记录线性结构相关属性。
data: 给出线性表存储空间的起始地址
maxSize: 指明线性表存储空间最多可存储的数据元素个数
curLength: 当前线性表里的数据元素个数
顺序表涉及的主要操作如下:
构造函数创建线性表:创建一个最多可存储maxSize个数据元素的顺序存储的线性表,并将其初始状态设置为curLength=0。该操作函数具体定义如下:
SeqList(int maxSize)
析构函数释放线性表存储空间:释放data所指向的用于存储线性表数据元素的存储空间。该操作函数具体定义如下:
~SeqList( )
清空线性表:将当前线性表变为一个空表,只需将curLength设置为0。该操作函数具体定义如下:
void clear( )
获取顺序表当前存储元素个数:返回线性表的当前长度curLength。该操作函数具体定义如下:
int size( )
判断线性表是否为空:若当前线性表是空表,则返回false,否则返回true。该操作函数具体定义如下:
bool empty( )
访问顺序表第i个数据元素:返回位于线性表的第i个数据元素data[i]。该操作函数具体定义如下:
elemType visit(int i)
在顺序表位置i插入元素value: 将value插入data[i]之前。若插入i>curLength 或i<0时,无法插入;若插入i=curLength,则先进行扩容;其余合法位置则正常插入元素value。该操作函数具体定义如下:
void insert(int i, const elemType &value)
删除位置序i处的元素: 删除线性表的i号数据元素。输入参数i范围应在[0,curLength-1]内,否则会产生不能预料的异常或错误。根据用户需要选择是否返回被删除的数据元素值。若无需返回,则该操作函数具体定义如下:
void remove(int i)
查找顺序表中第一次出现值为value的元素位置: 找到线性表中第一个值为value的数据元素的编号。返回值-1表示没有找到,返回值>=0表示该元素位置。该操作函数具体定义如下:
int search(const elemType &value)
删除顺序表中第一个值为x的数据元素: 删除第一个值为x的数据元素,返回该数据元素的编号。如果不存在值为x的数据元素,则返回-1。该操作函数具体定义如下:
int SL_DelValue(SeqList* slist, T x)
遍历顺序表: 打印整个线性表。该操作函数具体定义如下:
void traverse( )
逆置顺序表:将整个顺序表进行逆置存储。该操作函数具体定义如下:
void inverse( )
编程要求
本关任务是实现step1:顺序表/SeqList.h中的insert、remove、resize、search、visit、traverse和inverse七个基本操作。请注意,为了能够更好的比对输出结构,在参考教材代码的同时,请删除所有提示信息的输出! 基本操作具体要求如下:
* insert: 在顺序表的位置i插入结点x, 插入d[i]之前,i的有效范围[0,curLength]
* remove:删除顺序表第i号结点, i的有效范围应在[0,curLength-1],否则会产生异常或错误。
* search:查找第一个值为value的结点,存在则返回结点坐标, 未找到返回-1
* resize:对现有顺序表扩容,扩容后大小为原来的2倍。
* visit:访问顺序表第i号结点, i的有效范围应在[0,curLength-1],否则会产生异常或错误。找到则返回元素值,
* traverse:遍历输出顺序表中元素。
* inverse:逆置顺序表中元素。
输入输出格式请参见后续测试样例
注意:在实现本关任务的七个操作函数时,可调用以完成的其他操作。
测试说明
本关的测试文件是step1:顺序表/main.cpp,负责对实现的代码进行测试。具体代码,可以切换平台代码文件查看。
注意:step1:顺序表/main.cpp的代码不能被修改。
以下是平台对step1:顺序表/main.cpp的测试样例:
样例输入:
4 //输入线性表的长度
0 0 //0号位置出入元素0
1 1 //1号位置出入元素1
2 2 //2号位置出入元素2
3 3 //3号位置出入元素3
2 //设置j值
0 //设置val值
样例输出
0 1 2 3 //输出当前线性表的数据元素
0 //输出值为0的元素所在位置
2 //输出j位置元素值
0 1 3 //删除j位置元素后,输出线性表
3 1 0 //逆置当前线性表后输出
开始你的任务吧,祝你成功!
代码
seqList.h
#ifndef _SEQLIST_H_
#define _SEQLIST_H_
#include "List.h"
template <class elemType> // elemType为顺序表存储的元素类型
class seqList: public List<elemType>
{
private:
elemType *data; // 利用数组存储数据元素
int curLength; // 当前顺序表中存储的元素个数
int maxSize; // 顺序表的最大长度
void resize(); // 表满时扩大表空间
public:
seqList(int initSize = 10); // 构造函数
seqList(seqList & sl) ; // 拷贝构造函数
~seqList() {delete [] data;} // 析构函数
void clear() {curLength = 0;} // 清空表,只需修改curLength
bool empty() const {return curLength==0;} // 判空
int size() const {return curLength;} // 返回顺序表的当前存储元素的个数
void insert(int i,const elemType &value); // 在位置i上插入一个元素value,表的长度增1
void remove(int i); // 删除位置i上的元素value,若删除位置合法,表的长度减1
int search(const elemType &value) const ; // 查找值为value的元素第一次出现的位序
elemType visit(int i) const; // 访问位序为i的元素值,“位序”0表示第一个元素,类似于数组下标
void traverse() const ; // 遍历顺序表
void inverse(); // 逆置顺序表
};
template <class elemType>
seqList<elemType>::seqList(int initSize)
{
if (initSize <= 0) throw badSize();
maxSize = initSize;
data = new elemType[maxSize]; // 创建一个大小为maxSize的顺序表
curLength = 0;
}
template <class elemType>
seqList<elemType>::seqList(seqList & sl) {
maxSize = sl.maxSize;
curLength = sl. curLength;
data = new elemType[maxSize];
for (int i = 0; i < curLength; ++i)
data[i] = sl.data[i];
}
template <class elemType>
void seqList<elemType>::insert(int i, const elemType &value)
{
if (i < 0 || i > curLength) throw outOfRange(); // 合法的插入位置为[0..n]
if (curLength == maxSize) resize(); // 表满,扩大数组容量
// 请在这里补充代码,完成本关任务
/********** Begin *********/
for (int j = curLength;j > i;j--) {
data[j] = data[j - 1];
}
data[i] = value;
++curLength;
/********** End **********/
}
template <class elemType>
void seqList<elemType>::remove(int i)
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
if (i < 0 || i > curLength - 1) {
throw outOfRange();
}
for (int j = i;j < curLength - 1;j++){
data[j] = data[j+1];
}
--curLength;
/********** End **********/
}
template <class elemType>
void seqList<elemType>::resize()
{
elemType *p = data; // p指向原顺序表空间
maxSize *= 2; // 表空间扩大2倍
data = new elemType[maxSize]; // data指向新的表空间
// 请在这里补充代码,完成本关任务
/********** Begin *********/
for (int i = 0;i < curLength; ++i) {
data[i] = p[i];
}
delete [] p;
/********** End **********/
}
template<class elemType>
int seqList<elemType>::search(const elemType & value) const
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
for (int i = 0;i < curLength;i++) {
if (value == data[i]) {
return i;
}
return -1;
}
/********** End **********/
}
template<class elemType>
elemType seqList<elemType>::visit(int i) const
{
if (i < 0 || i > curLength-1 ) throw outOfRange();// 合法的访问位置为[0..n-1]
// 请在这里补充代码,完成本关任务
/********** Begin *********/
return data[i];
/********** End **********/
}
template<class elemType>
void seqList<elemType>::traverse()const
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
if(empty()) {
cout << endl;
}
else {
for (int i = 0;i < curLength;i++) {
cout << data[i] << " ";
}
cout << endl;
}
/********** End **********/
}
template<class elemType>
void seqList<elemType>::inverse()
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
elemType tmp;
for(int i = 0;i < curLength/2;i++) {
tmp = data[i];
data[i] = data[curLength-i-1];
data[curLength-i-1] = tmp;
}
/********** End **********/
}
#endif
第2关 合并两个顺序表
任务描述
1.按要求生成顺序表1和顺序表2。
接收由键盘输出的两组数据,第1组数据按录入顺序生成顺序表1,第2组数据按录入的逆序生成顺序表2。
例如,若第一组数据依次录入0 1 2,则顺序表1的0-2号位置依次为 0 1 2。若第二组数据依次录入为0 1 2,则顺序表2的0-2号位置依次为 2 1 0。
2.合并顺序表2到顺序表1中,即顺序表2的元素依次插入到顺序表1尾元素后,打印合并后的顺序表1。
相关知识
为了完成本关任务,你需要掌握:1.顺序表的存储;2.顺序表的基本操作。
本关可调用第1关中已实现的所有顺序表基本操作,请注意头文件的调用。
测试说明
平台会对你编写的代码进行测试:
4 //输入第一个表的长度
0 2 4 6//依次输入顺序表1元素
5 //输入第二个表的长度
1 3 5 7 9 //依次输入顺序表2元素
预期输出:
归并表为:0 2 4 6 9 7 5 3 1
代码
/*
合并两个顺序表:
1.按要求生成顺序表1和顺序表2。
接收由键盘输出的两组数据,第1组数据按录入顺序生成顺序表1,第2组数据按录入的逆序生成顺序表2。
例如,若第一组数据依次录入0 1 2,则顺序表1的0-2号位置依次为 0 1 2。若第二组数据依次录入为0 1 2,则顺序表2的0-2号位置依次为 2 1 0。
2.合并顺序表2到顺序表1中,即顺序表2的元素依次插入到顺序表1尾元素后,打印合并后的顺序表1。
提示:本关可调用第1关中已实现的顺序表基本操作,请注意头文件的调用。
*/
#include <iostream>
#include <cstdlib>
using namespace std;
#include "seqList.h"
#include "List.h"
int main()
{
seqList<int>* sl_1;
seqList<int>* sl_2;
sl_1 = new seqList<int>();
sl_2 = new seqList<int>();
int val;
int n;
cin >> n;
for (int i = 0;i < n;i++){
cin >> val;
sl_1 -> insert(i,val);
}
cin >> n;
for (int i = 0;i < n;i++){
cin >> val;
sl_2 -> insert(i,val);
}
sl_2 -> inverse();
n = sl_2 -> size();
int l = sl_1 -> size();
for (int i = 0;i < n;i++){
val = sl_2 -> visit(i);
sl_1 -> insert(l + i,val);
}
sl_1 -> traverse();
}