线性表由于物理存储方式的不同有两种:顺序表和链表。这个是顺序表的c++代码实现。顺序表有两种存储方式,一种是静态存储(利用数组),二是动态存储。
这里我用的是动态存储实现,并且利用的是函数类的构造,代码如下:
seqlist2.h
//动态存储的情况
//这块全部用的是对象和对象的函数来实现的
//之前书本上用的是普通函数+结构体,并且每次结构体需要改变的时候,结构体做参数是引用的,用对象就不需要了
//对于动态数组来说,当存储元素超过了要存的空间时,需要重新存放在其他的地方,函数IncreaseSize
template<typename keytype>
class SeqList2 {
private:
static const int defaultsize2 = 10;//默认值
keytype* L;
int maxlength;//最大容量
int length;//当前长度,长度从0~n 还是位序的那种,最开始没有数据就是0
public:
//构造函数
SeqList2(int size = defaultsize2) {
if (size > 0) {
maxlength = size;
L = new keytype[maxlength];
Initlist();//初始化
}
else;//这个地方需要考虑下如何处理吗
}
//析构函数
~SeqList2() {
delete[]L;
}
//基本操作,所有的输入输出参数都是位序,只有在函数内处理的时候是用函数下标哈
void Initlist();//初始化顺序表
int Getlength();//返回顺序表的当前长度
int Getmaxlength();//返回顺序表的最大长度
keytype rankGetvalue(int rank);//顺序表rank位序的查找
int valueGetrank(keytype e);//顺序表按照值的查找,返回第一个该值的rank位序(小心)
bool listInsert(int rank, keytype e);//顺序表rank位序的插入
bool listDelete(int rank, keytype& e);//顺序表rank位序的删除
bool listChange(int rank, keytype e);//循序表rank位序的修改
//动态数组特别的,增加动态数组长度,就是重新申请一片更大的空间
void IncreaseSize();
};
具体的方法实现:
//***************顺序表的基础操作的具体实现****************
//初始化顺序表
template<typename keytype>
void SeqList2<keytype>:: Initlist() {
length = 0;
for (int i = 0; i < length; ++i) L[i] = NULL;//这步其实不需要的哈
}
//返回顺序表的当前长度
template<typename keytype>
int SeqList2<keytype>::Getlength() {
return length;
}
//返回顺序表的最大长度
template<typename keytype>
int SeqList2<keytype>::Getmaxlength() {
return maxlength;
}
//顺序表rank位序的查找
template<typename keytype>
keytype SeqList2<keytype>::rankGetvalue(int rank) {//rank是位序
if (rank<1 || rank>length) {
std::cout << "参数无效" << std::endl;
return 0;//此处可以返回这个值吗
}
else {
return L[rank - 1];
}
}
//顺序表按照值的查找,返回第一个该值的rank位序(小心)
template<typename keytype>
int SeqList2<keytype>::valueGetrank(keytype e) {//返回为位序
for (int i = 0; i < length; ++i) {
if (L[i] == e) return i+1;
}
return 0;//返回位序为0,说明查找失败
}
//顺序表rank位序的插入
template<typename keytype>
bool SeqList2<keytype>::listInsert(int rank, keytype e) {
if (rank < 1 || rank>length + 1) return false;//小心哦length+1,因为可以在length之后直接插入
//注意哦这个地方是强制不能让他从0~10 突然加一个第100位,只能加在101
if (length >= maxlength)
IncreaseSize();//要是加了就超了
for (int i = length; i >= rank; --i)//i是下一位
L[i] = L[i - 1];
L[rank - 1] = e;
length++;//这步之前又忘了!
return true;
}
//顺序表rank位序的删除
template<typename keytype>
bool SeqList2<keytype>::listDelete(int rank, keytype& e) {//单纯想把删除的数据最后放在e里面,万一还需要用一下
if (rank<1 || rank>length) return false;
e = L[rank - 1];
/*for (int i = rank - 1; i < length - 1; ++i)
L[i] = L[i + 1]; 没写好*/
for (int i = rank; i < length; ++i)
L[i - 1] = L[i];
length--;
return true;
}
//循序表rank位序的修改
template<typename keytype>
bool SeqList2<keytype>::listChange(int rank, keytype e) {
if (rank<1 || rank>length) return false;
L[rank - 1] = e;
return true;
}
//增加动态数组长度,就是重新申请一片更大的空间
template<typename keytype>
void SeqList2<keytype>::IncreaseSize() {
keytype* p = L;
L = new keytype[maxlength + maxlength];
for (int i = 0; i < length; ++i) {
L[i] = p[i];
}
maxlength += maxlength;
free(p);
}
2.1seqlist.cpp
// 2.1seqlist.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//顺序表 seqlist 链表 linearlist
//顺序表要注意 数组下标和位序 之间的区别,函数参数和返回值一般都是位序,而只有函数内部操作的时候是用的数组下标
#include <iostream>
#include "seqlist2.h"
using namespace std;
int main()
{
const int defaultsize = 10;//默认值
int p = 0;
//创建
SeqList2<int> a;
SeqList2<int> b(defaultsize + 1);
//位序插入
for (int i = 1; i <= defaultsize; ++i) {
a.listInsert(i, i);
b.listInsert(i, i * i);
}
//查询长度
cout << a.Getlength() << a.Getmaxlength() << endl;
cout << b.Getlength() << b.Getmaxlength() << endl;
//位序插入,特别的
cout << a.listInsert(defaultsize + 1, defaultsize + 1) << endl;
cout << b.listInsert(defaultsize + 1, (defaultsize + 1)*(defaultsize + 1)) << endl;
//查询长度
cout << a.Getlength() << " " << a.Getmaxlength() << endl;
cout << b.Getlength() << " " << b.Getmaxlength() << endl;
//输出一下,位序查询
for (int i = 1; i <= a.Getlength(); ++i) {
cout << a.rankGetvalue(i) << " ";
}
cout << a.rankGetvalue(defaultsize + 1) << endl;
//值查询
cout << a.valueGetrank(defaultsize) << endl;
cout << b.valueGetrank(defaultsize) << endl;
//位序删除
cout << b.listDelete(defaultsize/2, p) << " " << p << endl;
//位序修改
a.listChange(defaultsize/2, defaultsize);
//输出一下,位序查询
for (int i = 1; i <= a.Getlength(); ++i) {
cout << a.rankGetvalue(i) << " ";
}
cout << endl;
for (int i = 1; i <= b.Getlength(); ++i) {
cout << b.rankGetvalue(i) << " ";
}
return 0;
}
特别的:
我的这个数组是要是超过了其当前的最大存储量,就自动扩大容量,但是我初始化的时候又专门设置了一个最大容量,很奇怪总觉得逻辑有点冲突。
值得注意的地方就是:
1、位序和数组下标
位序=数组下标+1(e.g. L[i]在意义上就是数组的第i+1个数)。在我们的函数实现上参数,全部是位序,在别人使用函数的时候全是使用的是该数组的实际第几位,而类里面的length, maxlength当前长度和最大长度也是位序,而到了L[]数组上的时候就全是位序-1了
2、线性表就是线性的连续的,所以不存在有 数组第1~10位的数据,要插入一个第100位的数据,只能最大插入到到11位