赞
踩
也就是线性表的顺序存储,即用一组地址连续的存储单元一次存储线性表中的数据元素,从而使得逻辑上相邻的元素在物理位置上也是相邻的,有两种空间分配方式:
根据顺序表中元素的特点可以分为:
通常一个线性表是这样的:
class List{
private:
ElementType data[MAXSIZE];
int length;
public:
bool insert(int pos, ElementType e);
bool delet(int pos);
bool locate(ElementType e);
}
将元素插入到0
到 length - 1
(也可以是1
到 length
,说明清楚,保持一致即可)的位置 i
,我们需要先将包括插入位置的元素在内的后面的所有元素后移一位,平均移动次数为
n
/
2
n/2
n/2(考虑最坏的情况和最好的情况,相加除以二即可得到),函数实现:
bool insert(int pos, ElementType e){
if(pos > this->length || pos < 0){
return false;
}
if(this->length >= MAXSIZE){
return false;
}
for(int j = this->length - 1;j >= pos;j--){
this->data[j + 1] = this->data[j]
}
this->data[pos] = e;
this->length++;
return true;
}
删除所给位置 i
的元素,删除之后,我们需要将删除元素后面的 length - 1 - i
个元素全部前移一位,平均移动次数为
(
n
−
1
)
/
2
(n-1)/2
(n−1)/2。(同理)
bool delet(int pos){
if(pos > this->length - 1 || pos < 0){
return false;
}
if(this->length == 0){
return false;
}
for(int j = pos;j < this->length;j++){
this->data[j] = this->data[j + 1];
}
this->length--;
return true;
}
查找某个特定值的元素在顺序表中的位置,返回其位置索引(index),平均访问次数为 ( n + 1 ) / 2 (n+1)/2 (n+1)/2。(同理)
int locate(ElementType e){
if(this->length == 0){
return -1;
}
for(int i = 0;i < this->length;i++){
if(this->data[i] == e){
return i;
}
}
return -1;
}
交换第i
个元素和length - 1 - i
个元素:
void reverse(){
for(int i = 0;i < this->length / 2;i++{
int temp = this->data[i];
this->data[i] = this->data[length - 1 - i];
this->data[length - 1 - i] = temp;
}
return;
}
合并两个有序的顺序表,只需要遍历到其中一个顺序表末尾即可,复杂度为 O ( N ) = O ( m a x { m , n } ) O(N)=O(max\{m,n\}) O(N)=O(max{m,n}),假定序列都是升序序列:
List merge(List l1, List l2){ List l3; int i = 0, j = 0, k = 0; while(i < l1.length && j < l2.length){ if(l1.data[i] > l2.data[j]){ l3.data[k] = l2.data[j]; j++; } else{ l3.data[k] = l1.data[i]; i++; } k++; } // either while(i < l1.length){ l3.data[k++] = l1.data[i++]; } // or while(j < l2.length){ l3.data[k++] = l1.data[j++]; } l3.length = k; return l3; }
如果是一个有序顺序表,那么给定值的所有元素是在相邻的位置上的,我们只需要统计该位置的元素的个数 k
,然后后面的元素前移 k
位即可:
void deleteByValue(ElementType value){ int start = 0, end = 0; for(int i = 0;i < this->length;i++){ if(this->data[i] == value]){ start = i; break; } } for(int i = start;i < this->length;i++){ if(this->data[i] != value){ end = i - 1; } } int k = end - start; if(k <= 0){ return; } for(int i = end + 1;i < this->length;i++){ this->data[i - k] = this->data[i]; } return; }
如果不是一个有序顺序表,可以有两种方法:
value
的元素,保留value
的元素的个数 k
,其他元素前移 k
位void deleteByValue1(ElementType value){ // count element whose value not equal to given value int k = 0; for(int i = 0;i < this->length;i++){ if(this->data[i] != value){ this->data[k] = this->data[i]; k++; } } } void deleteByValue2(ElementType value){ // count element with given value int k = 0; for(int i = 0;i < this->length;i++){ if(this->data[i] == value){ k++; } else{ this->data[i - k] = this->data[i]; } } return; }
同理,如果是一个顺序表那么给定范围的元素是连续的,我们依然只需要统计给定范围内元素的个数,然后将后续的元素前移相应的步长即可,只需要修改一下判断条件:
void deleteByValue(ElementType floor, ElementType ceiling){ int start = 0, end = 0; for(int i = 0;i < this->length;i++){ if(this->data[i] >= floor]){ start = i; break; } } for(int i = start;i < this->length;i++){ if(this->data[i] >= ceiling){ end = i - 1; } } int k = end - start; if(k <= 0){ return; } for(int i = end + 1;i < this->length;i++){ this->data[i - k] = this->data[i]; } return; }
同样如果是有序顺序表,则同样只需要修改一下判断条件即可:
void deleteByValue1(ElementType floor, ElementType ceiling){ // count element whose value not equal to given value int k = 0; for(int i = 0;i < this->length;i++){ if(this->data[i] < floor || this->data[i] > ceiling){ this->data[k] = this->data[i]; k++; } } } void deleteByValue2(ElementType floor, ElementType ceiling){ // count element with given value int k = 0; for(int i = 0;i < this->length;i++){ if(this->data[i] >= floor && this->data[i] <= ceiling){ k++; } else{ this->data[i - k] = this->data[i]; } } return; }
如果是一个有序顺序表的话,那么重复的元素将是连续的,那么我们只需要判断下一个元素是否跟前一个元素的值相同,是的话,就增加计数,不是的话就前移相应的步长即可:
void removeDuplicate(){
if(this->length <= 1){
return;
}
int k = 0;
for(int i = 1;i < this->length;i++){
if(this->data[i] == this->data[i - 1]){
k++;
}
else{
this->data[i - k] = this->data[i];
}
}
return;
}
如果是一个无序的顺序表,要在时间上尽可能高效的话,我们可以考虑用空间换取时间的方法,也就是用一个散列表记录每一个元素对应的值是否出现过,则增加计数,否则前移相应的步长,可以去了解散列表的用法,实现不难。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。