排序算法总结-插入排序、希尔排序、堆排序、快速排序


今天去面试被问到了自己知道哪些排序算法,虽然答了一堆,但是想想会的真没几个,所以回来后这里将几个(自认为)重要的写在这里。

1、插入排序

//插入排序
//原理:前i项是排过序的,将当前元素插入到前面已经排过序的序列中
//时间界:O(N2)
template <typename Comparable>
void insertionSort(vector<Comparable> &a){
	for( size_t i = 1; i < a.size(); i++){
		Comparable temp = a[i];
		int j;
		for(j = i; j > 0 && temp < a[j - 1]; j--){
			//如果当前待插入的元素小于前面的元素,
			//则依次后移
			a[j] = a[j - 1];
		}
		//将当前带插入元素放到循环退出的位置
		//即前面的元素没有他大,或者j已经到了第一个位置
		a[j] = temp;
	}
}

2、希尔排序

//希尔排序
//原理:所有相隔某个增量的元素都被排序
//时间界与选取的增量序列相关,一般好于插入排序,但大于NlogN
int getGap(int num){
	int power = 0;
	while((num/=2) > 0){
		power++;
	}

	return (int)pow((double)2,(double)power);
}
template<typename Comparable>
void shellSort(vector<Comparable> &v){
	//这里选取增量序列为1,3,7,...,pow(2,k)-1
	int gap = getGap(v.size());
	for(; gap > 0; gap = gap/2 - 1){
		for( size_t i = gap; i < v.size(); i++){
			Comparable temp = v[i];
			int j = i;
			//我感觉这里跟插入排序是一样的,插入排序可以理解为gap是1的情况。
			for(j = i; j >= gap && temp < v[j - gap]; j -= gap)
				v[j] = v[j - gap];
			v[j] = temp;
		}
	}
}

3、堆排序

//堆排序
//根据二叉堆而来,这里用最大堆,即根的键值比其儿子的键值大
//通过deleteMax操作得到排序后的序列
template<typename Comparable>
//下率操作
void percDown(vector<Comparable> &v, int current, int n){
	Comparable temp;
	int child;
	for( temp = v[current]; 2*current < n; current = child){
		child = 2*current;
		//找到最大的孩子
		if( child + 1 < n && v[child] < v[child+1])
			child++;

		//如果最大的孩子比父亲大,则交换,否则找到了正确的位置退出
		if( v[child] > temp)
			v[current] = v[child];
		else
			break;
	}
	//将传进来的位置上的键值放到找到的位置
	v[current] = temp;
}

template<typename Comparable>
void heapSort(vector<Comparable> &v){
	for( int i = v.size()/2; i >= 0; i--){
		percDown(v, i, v.size());
	}

	for(size_t j = v.size() - 1; j > 0; j--){
		//这里将最大的值与最后一个元素互换,即deleteMax操作
		Comparable temp = v[0];
		v[0] = v[j];
		v[j] = temp;
		//然后对根处的元素进行下率
		percDown( v, 0, j);
	}
}



4、快速排序

//快速排序
//主要需要找到枢纽元,然后对其进行分段排序
//找到枢纽元的方法可以自己进行各种改进
template<typename Comparable>
void swap(vector<Comparable> &v, int i, int j){
	Comparable temp = v[i];
	v[i] = v[j];
	v[j] = temp;
}
template<typename Comparable>
int getPivot(vector<Comparable> &v, int low, int high){
	int middle = (low + high)/2;

	if( v[low] > v[middle]){
		swap(v, low, middle);
	}
	if( v[low] > v[high]){
		swap(v, low, high);
	}
	if( v[middle] > v[high]){
		swap(v, middle, high);
	}

	//这里将选出的中间值放在倒数第二个位置,因为最后一个不用再筛选了,他肯定比中间值大
	swap(v, middle, high - 1);

	return v[high - 1];
}
template<typename Comparable>
void quickSort(vector<Comparable> &v, int low, int high){
	if( low >= high)
		return;

	Comparable pivot = getPivot( v, low, high);

	int l = low;
	int r = high - 1;
	while(1){
		//当遇到不满足条件的元素时,l和r分别指向他们
		while(v[++l] < pivot){}
		while(v[--r] > pivot){}

		if( l < r){
			swap( v, l, r);
		}else{
			break;
		}
	}
	//将枢纽元放置到结束的地方
	swap(v, l, high - 1);
	quickSort( v, low, l -1);
	quickSort( v, l + 1, high);
}


今天就写到这里吧,上面的我都试了一下可以正常工作。睡觉了



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值