数据结构分为线性结构和非线性结构,线性结构是简单常用的数据结构,线性表是典型的线性结构。
线性表的定义是由N个(N>=0)节点或者表项构成,他是有限数列,邻接关系是1:1,有两种:有序和无序
线性表可以有不同的数据类型,如广义表,广义表表中元素自身具有某种结构,属于线性表,是线性表的推广
线性表有两种存储方式:顺序存储和链式存储,有基于数组的、基于链表的、散列的表示
顺序表是基于数组的顺序存储,可以那顺序一次访问或者随机访问,每个表项的存储空间相同
注意:表的起始元素是从1开始的,数组是从0开始的,第 m个表项对应的是数组m-1个
存储分为静态存储和动态存储,动态存储可以扩展存储空间提高灵活性
在Search、Locate、getDatas这几个函数定义中是常函数const,因为const成员函数执行时不能调用非const成员函数,表明函数不能改变对象的函数值
线性表的各个常用函数 表示
1.搜索函数,如果有值等于X,返回表型第几个元素
int SeqList::search(T& x)const{
for(int i=0;i<=last;i++)
if(data[i] == x) return i+1;
return 0;
}
bool SeqList::Insert(int i ,T& x){
if(last == maxSize-1) return false; //表满,不能插入
if(i<0 || i>last+1) return false; //i数据不合理,不能插入
for(int j = last;j>=i;j--)
data[j+1] = data[j]; //向后移动,空出i
data[i] = x; //插入
last++;
return true;
}
这里
采用的是从最后一位开始后移来实现,这个方向是不能变的,不能从前面开始,下面这是
错误的例子,注意啊是错误的
bool SeqList::Insert(int i ,T& x){
if(last == maxSize-1) return false; //表满,不能插入
if(i<0 || i>last+1) return false; //i数据不合理,不能插入
for(int j = i;j
这个和上面的区别在于移动的顺序不一样,这是从前向后移动,这样的话,我们来看一下,执行第一步data[ j ]的值赋给data[ j+1],j++之后,原本的data[ j+1]的值被覆盖掉了,不存在了,执行data[ j+2] = data[ j+1]时还是最开始的data[ j ]的值,后面的所有数据都被冲掉了,都变成data[ i ]的值了,所以这样是不对的,要从后开始
3.删除函数, 值等于X的删除
bool SeqList::Remove(int i ,T& x){
if(last == -1) return false; //表空,不能删除
if(i<1 || i>last+1) return false; //i数据不合理,不能删除
for(int j = i;j<=last;j++)
data[j-1] = data[j]; //向前移
last--;
return true;
}
这个是从前面开始,顺序依然不能变,如果从后面向前推的话,数据被冲掉,都是data[last]
3.2删除值为X的所有元素
void deleteValue(SeqList& L,DataType x){
int i,k=0; //记录不等于X的指针位置
for(i=0;i
3.3删除表中重复元素
int deleteSame(SeqList& L){
int i,k=1;
if(L.n == 0) return 0;
for(i=1;i
注意在插入和删除前要判断表是否是空表或者满表,数据 i 是否合理
顺序表搜索算法的时间代价是数据比较次数衡量,插入和删除是循环内数据移动次数决定的
搜索算法最坏情况是比较n+1次(最后一次检测 i > last,没有数据比较),平均次数是n+1/2
插入时平均数据移动次数是n/2,删除时是n-1/2次
顺序表查找时间复杂度是O(1),插入和删除的复杂度是O(n),进行插入和删除的时间代价相对较高
顺序表的应用
可以把两个顺序表看作是集合,实现”交并“
void union(SeqList& LA,SeqList& LB){ //并集
int n = LA.Length(),m = LB.Length(),i,k,x;
for(i=1;i<=m;i++)
LB.getData(i,x); //从B中取出元素
k = LA.Search(x); //在A中查找有没有
if(k == 0) LA.Insert(n,x);n++; //如果没有就将x插入到A中
}
void intersection(SeqList& LA,SeqList& LB){ //交集
int n = LA.Length(),m = LB.Length(),i=1,k,x;
while(i<=n){
LA.getData(i,x); //从A中取出元素
k = LB.Search(x); //在B中查找有没有
if(k == 0) LA.Remove(i,x);n--; //如果没有就将x删除
}
}
在并集的时候采用的是从B中取元素,没有就添加到A中,而在交集的时候是在A中取元素,将B中没有的删除,之所以不在B取元素是因为添加可以在最后进行,删除不可以,删除必须在数据原本的位置上删除,这就需要remove时获取 i 的位置,只能循环遍历A然后在A中删除