顺序表的基本操作实现
线性表
在程序中,经常需要将一组(通常是同为某个类型的)数据元素作为整体管理和使用,需要创建这种元素组,用变量记录它们,传进传出函数等。一组数据中包含的元素个数可能发生变化(可以增加或删除元素)。
对于这种需求,最简单的解决方案便是将这样一组元素看成一个序列,用元素在序列里的位置和顺序,表示实际应用中的某种有意义的信息,或者表示数据之间的某种关系。
这样的一组序列元素的组织形式,我们可以将其抽象为线性表。一个线性表是某类元素的一个集合,还记录着元素之间的一种顺序关系。线性表是最基本的数据结构之一,在实际程序中应用非常广泛,它还经常被用作更复杂的数据结构的实现基础。
根据线性表的实际存储方式,分为两种实现模型:
- 顺序表,将元素顺序地存放在一块连续的存储区里,元素间的顺序关系由它们的存储顺序自然表示。
- 链表,将元素存放在通过链接构造起来的一系列存储块中。
顺序表的基本形式
上图a表示的是顺序表的基本形式,数据元素本身连续存储,每个元素所占的存储单元大小固定相同,元素的下标是其逻辑地址,而元素存储的物理地址(实际内存地址)可以通过存储区的起始地址Loc(e0)加上逻辑地址(第i个元素)与存储单元大小(c)的乘积计算而得,即:
Loc(ei) = Loc(e0) + c*i
故,访问指定元素时无需从头遍历,通过计算便可获得对应地址,其时间复杂度为O(1)。
如果元素的大小不统一,则须采用图b的元素外置的形式,将实际数据元素另行存储,而顺序表中各单元位置保存对应元素的地址信息(即链接)。由于每个链接所需的存储量相同,通过上述公式,可以计算出元素链接的存储位置,而后顺着链接找到实际存储的数据元素。注意图b中的c不再是数据元素的大小,而是存储一个链接地址所需的存储量,这个量通常很小。
图b这样的顺序表也被称为对实际数据的索引,这是最简单的索引结构。
顺序表的实现
#include <iostream>
using namespace std;
#include <iostream>
#include <cassert>
#include <cstdlib>
#include <ctime>
using namespace std;
typedef int T;
const int defaultSize = 100;
class SeqList
{
private:
T* data;//指向动态内存分配数组的指针
int maxSize;//动态内存分配数组的大小
int last;//标识顺序表中最后一个元素的位置
void Resize(int newSize);
public:
SeqList(int sz=defaultSize);//构造函数
SeqList(const SeqList& L);//拷贝构造函数
SeqList& operator=(const SeqList& L)//赋值运算符函数
{
maxSize = L.maxSize;
data = new int[maxSize];
last = L.Length()-1;
int value;
if(data == NULL)
{
cerr<< "存储分配错误!"<< endl;
exit(1);
}
for(int i = 1; i <= last+1; i++)
{
L.GetData(i,value);
data[i-1] = value;
}
return *this;
}//赋值运算符函数
~SeqList()
{
last = -1;
maxSize = 0;
delete []data;
data = NULL;
}//析构函数//析构函数
int Size() const;//返回顺序表的容量
int Length() const;//返回顺序表中元素的个数
int Search(T & x) const;//在顺序表中搜索x
int Locate(int i) const;//检验顺序表中是否存在第i个元素
bool GetData(int i, T& x) const;//获取顺序表中第i个位置的元素
void SetData(int i, T& x);//将顺序表中第i个位置的元素赋值为x
bool IsEmpty() const;//顺序表是否为空
bool IsFull() const;//顺序表是否为满
bool Insert(int i, const T& x) ;//在顺序表的第i个元素的位置插入x
bool Remove(int i, T&x) ;//删除顺序表第i个位置的元素
void Sort() ;//对顺序表中元素进行排序
friend istream& operator>>(istream& in, SeqList & L)//输入运算符重载
{
int i;
while(1)
{
cin >> L.last;
if(L.last >= L.maxSize||L.last <= 0)
{
break;
}
break;
}
for(i=0; i<L.last; i++)
{
in >> L.data[i];
}
return in;
}
friend ostream& operator<<(ostream& out, const SeqList& L)
{
int i;
if(L.last >= L.maxSize||L.last <= 0)
{
exit(0);
}
for(i=0; i<L.last - 1; i++)
{
out << L.data[i] << " ";
}
out<<L.data[i];
return out;
//逆置顺序表中的元素
};
void Reverse ();//逆置顺序表中的元素
};
int main()
{
SeqList sList;
cout << "请输入顺序表的个数和顺序表分别的元素的值:" ;
cin>>sList;
cout<<sList << endl;
int i, val;
cout << "请输入插入元素的位置和值";
cin>>i>>val;
sList.Insert(i,val);
cout<<sList << endl;
cout << "请输入删除元素的位置";
cin>>i;
sList.Remove(i,val);
cout<<sList << endl;
cin>>val;
i=sList.Search(val);
if(i==0)
cout<<"Not found"<<endl;
else
cout<<i<<endl;
// sList.Reverse();
// cout<<sList;
}
SeqList::SeqList(int sz )
{
if (sz > 0){
maxSize = sz;
data = new T[maxSize];
last = -1;
if (data == NULL)
{
exit(1);
}
}
}
SeqList::SeqList(const SeqList &L) {
int value;
maxSize = L.maxSize;
data = new int[maxSize];
last = L.Length()-1;
if(data == NULL)
{
cerr << "存储分配错误!"<< endl;
exit(1);
}//基本判断
for(int i = 1; i <= last+1; i++)
{
L.GetData(i,value);
data[i-1] = value;
}
}//拷贝构造函数
int SeqList::Size() const
{
return maxSize;
}
int SeqList::Length() const {
return last+1;
}
int SeqList::Search(T &x) const {
for (int i = 0; i < last+1; ++i) {
if (x == data[i])
return i+1;
}
return -1;
}
int SeqList::Locate(int i) const {
if (i > last)
return -1;
else if (i < 0){
return -1;
}
else
return i;
}
bool SeqList::GetData(int i, T &x) const {
if (i < 0 && i > last)
return false;
x = data[i];
return true;
}
void SeqList::SetData(int i, int& x)
{
if(i<0&&i>last+1)
return;
data[i-1] = x;
}
bool SeqList::IsEmpty() const
{
if(last == -1)
return true;
return true;
}
bool SeqList::IsFull() const
{
return (last == maxSize - 1);
}
bool SeqList::Insert(int i, const T &x) {
if (last > maxSize - 1)
return false;
if (i > last||i < 0)
return false;
int j = last;
for (int j = last; j >= i ; j--) {
data[j+1] = data[j];
}
data[i] = x;
last++;
return true;
}
bool SeqList::Remove(int i, int&x)
{
if(last == -1)
return false;
if(i<1||i>last+1)
return false;
x = data[i-1];
for(int j = i; j<=last; j++)
data[j-1] = data[j];
last--;
return true;
}
void SeqList::Sort() {
int i,j;
for (int i = 0; i < last+1; ++i) {
int m = i;
for (int j = i+1; j < last+1; ++j) {
if (data[j] > data[m])
m = j;
}
if (i != m)
{
int temp;
temp = data[m];
data[m] = data[i];
data[i] = temp;
}
}
}
void SeqList::Reverse() {
int temp;
for (int i = 0; i < last+1; ++i) {
temp = data[i];
data[i] = data[last - i];
data[last - i] = temp;
}
}