对于线性表来说,
1:必有一个唯一的一个被称为第一个的数据元素
2:必有一个唯一的一个被称为最后一个的数据元素
3:每个元素都有它的直接前驱和直接后继
4:它是一个最常用且简单的数据结构,它的描述为:n个数据元素的有限序列,记为:L=(a1,a2,...,an)。
按照存储结构它又可以分为顺序存储结构和链式存储结构
这里暂时介绍的就是顺序存储结构:用一段连续的地址依次存储表中的数据元素。看到这里,会自然而然的联想到,
在c++当中数组的概率,也是开辟一段空间,有序的存储数据。
位置相邻<=>逻辑相邻,是一种可随机存取的数据结构。
LOC(a (i+1))=LOC(a i)+l(l为一个数据元素占得存储单元)
其实这里就是类似于数组的一些操作。
我们在数组里,直接定义a[10];并没有考虑缘由,其实数组也类似于指针,在这里就是用指针,指向地址,开辟一段连续的空间。
接下来呢,就是对于线性表的一些简单的操作。这里呢,在增加元素的时候,当超过了开始定义的允许的最大长度就没有增加分配了。
#include<iostream>
using namespace std;#define MAXSIZE 100
class List
{
public:
List();//创建线性表
void InitList();//初始化一个线性表
void ClearList();//将线性表置为空表
void ListEmpty();//判断线性表是否为空
int ListLength();//返回线性表的长度
int GetElem(int a);//得到第i个数据元素的值
void InsertList(int value,int a);//向线性表中第i个元素位置插入元素
void DelList(int a);//将线性表的第i个元素删除
void ShowList();//将线性表元素全部输出
List MergeList(List b);//将两个有序表综合到一起
private:
int *base;
int length;
int listsize;
};
List::List()
{
base = (int *)malloc(MAXSIZE * sizeof(int));//分配内存空间,建立一个数组的感觉,给数组分配大小。
if (!base)//常用这样的判断条件,还有这样判断输入变量的个数的,以后可以继续利用,下次看到可以综合一下。
cout << "error" << endl;
length = 0;
listsize = MAXSIZE;
}
void List::InitList()
{
int i;
cin >> i;
for (int j = 0; j < i; j++)
cin >> base[j];
length = i;
}
void List::ClearList()
{
for (int i = 0; i < length; i++)
base[i] = 0;
length = 0;
}
void List::ListEmpty()
{
if (length == 0)
cout << "empty" << endl;
else
cout << "not empty" << endl;
}
int List::ListLength()
{
return length;
}
int List::GetElem(int a)
{
if (length < a)
cout << "error" << endl;
else
return base[a];
}
void List::InsertList(int value,int a)
{
if (length < a)
{
length++;
if (length < MAXSIZE)
base[length] = value;
else
cout << "error" << endl;
}
else
{
length++;
for (int i = length - 1; i > a; i--)
{
base[i] = base[i - 1];
}
base[a] = value;//没有判断这个时候的是否溢出,没有用之前的把一个数慢慢的移,那样比较慢,直接从后面的数开始移动
}
}
void List::DelList(int a)
{
if (a > length || a<0 || a>MAXSIZE)
{
cout << "error" << endl;
}
else
{
for (int i = a; i < length-1; i++)
{
base[i] = base[i + 1];
}
length--;//与插入的时候相反,从前开始。
}
}
void List::ShowList()
{
for (int i = 0; i < length; i++)
{
cout << base[i]<<" ";
}
}
List List::MergeList(List b)
{
List c;
int i = 0;
while (i < this->ListLength() && i < b.ListLength())
{
if (this->GetElem(i) > b.GetElem(i))
c.InsertList(this->GetElem(i), i);
else
c.InsertList(b.GetElem(i), i);
i++;
}
while (i < this->ListLength())
{
for (i = b.ListLength(); i < this->ListLength(); i++)
c.InsertList(this->GetElem(i), i);
i++;
}
while (i < b.ListLength())
{
for (i = this->ListLength(); i < b.ListLength(); i++)
c.InsertList(b.GetElem(i), i);
i++;
}
return c;
}
int main()
{
List b;
b.InitList();
b.ListEmpty();
b.ShowList();
b.ListLength();
b.InsertList(5, 2);
b.DelList(4);
b.DelList(9);
b.ShowList();
List c;
c.InitList();
List d;
d=b.MergeList(c);
d.ShowList();
return 0;
}
我们可以看到,在顺序表中某个位置上插入和删除一个数据元素的时候,主要的时间都耗费在了移动数据元素上了。
插入和删除的E=n/2与E=(n-1)/2,故其时间复杂度为O(n),
在两个顺序表进行两个数据元素的比较而言时间复杂度为O(a.length*b.length),
对于两个顺序表的合并,若只是在原来的基础上进行,时间复杂度为O(a.length+b.length)
若为新建一个c表,分出元素进行计较的话,算法基本相同,但第一句循环改成用开关代替条件语句。
时间复杂度为O(nlogn)。