2.3有序向量

1、有序性及其甄别

有序/无序序列中,任意/总有一对相邻元素顺序/逆序
相邻逆序对的数目,可以度量向量的逆序程度。

template <typename T> 
int Vector<T>::disordered() const{
	int n=0;
	for(int i=1;i<_size;i++){
		n+=(_elem[i-1]>_elem[i]);
	}
	return n;
}

2、唯一化:低效算法

template <typename T>
int Vector<T>::uniquify(){
	int oldSize=_size;
	int i=0;
	while(i<_size-1)
		(_elem[i]==_elem[i+1])?remove(i+1):i++;
	return oldSize-_size;
}

最坏时,累计o(n2
最好时,o(n)

3、唯一化:高效算法

template <typename T> int Vector<T>::uniquify(){
	Rank i=0,j=0;
	while(++j<_size){
		if(_elem[i]!=_elem[j])_elem[++i]=_elem[j];
	}
	_size=++i;shrink();
	return j-i;
}

累计时间o(n);

4、有序向量的查找:二分查找

template <typename T> Rank Vector<T>::search(T const & e,Rank lo,Rank hi) const{
	return (rand()%2)?binsearch(_elem,e,lo,hi):fibsearch(_elem,e,lo,hi);
}

5、语义约定

至少,应该便于有序向量自身的维护:V.insert(1+V.search(e), e)
即便失败,也应给出新元素适当的插入位置,若允许重复元素,则每一组也需按其插入的次序排列。
约定:在有序向量区间[lo,hi)中,确定最后一个不大于e的最后一个元素:
若负无穷<e<V[lo],则返回lo-1(左侧哨兵)
若V[hi-1]<e<正无穷,则返回hi-1(末元素=右侧哨兵左临)

6、二分查找原理

减而治之:以任一元素x=S[mi]为界,都可将待查找区间分为三部分,S[lo,mi)<=S[mi]<=S(mi,hi),只要将目标元素e与x比较,即可确定更小的范围,甚至可直接命中,随即返回。
算法实现:

template <typename T> static Rank binSearch(T* A, T const& e, Rank lo, Rank hi){
	while(lo<hi){
		Rank mi=(lo+hi)>>1;
		if(e<A[mi])hi=mi;
		else if(A[mi]<e)lo=mi+1;
		else return mi;
	}
	return -1;//查找失败
}

复杂度o(logn),再精细一点,约为o(1.50logn)

7、Fibonacci查找

二分查找的版本仍有改进余地,主要原因是左右分支前的关键码比较次数不同,而递归深度却相同。
比如,若设n=fib(k)-1,则可取mi=fib(k-1)-1;于是前后子向量的长度分别为fib(k-1)-1、fib(k-2)-1;

template <typename T> static Rank binSearch(T* A, T const& e, Rank lo, Rank hi){
	Fib fib(hi-lo);
	while(lo<hi){
		while(hi-lo<fib.get())fib.prev();
		Rand mi=lo+fib.get()-1;
		if(e<A[mi])hi=mi;
		else if(A[mi]<e)lo=mi+1;
		else return mi;
	}
	return -1;//查找失败
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值