希尔排序
又称缩小增量排序
先给数组设定一个增量,一般数组长度为len,同常将增量设为increment = len/2,increment每次缩小为原来的1/2。
1、通过这个增量给数组里的数分组:例如 0,0+increment, 0+2*increment,... 为一组 1,1+increment, 1+2*increment,...为另外一组。
2、对于每一个组通过插入算法进行排序。(前面已经写了折半插入排序,这里写的是普通插入排序)
3、increment = increment/2,然后继续循环
代码:shell_sort.cc
#include<iostream>
#include<vector>
using namespace std;
template< class T >
void shell_sort(vector<T> &a){
int len = a.size();
int i,j;
T tmp;
int increment;
for ( increment = len/2; increment >0; increment /= 2){
for ( i = increment; i < len; i++){
tmp = a[i];
for ( j = i; j >=increment; j -= increment){
if ( tmp < a[j - increment] )
a[j] = a[ j - increment];
else{
break;
}
}
a[j] = tmp;
}
}
}
int main(int argc, char **argv){
vector<int> a = {10, 8, 9, 1, 7, 4, 11, 23, 3, 2, 5};
vector<int>::iterator iter;
shell_sort<int>( a );
for( iter = a.begin(); iter != a.end(); iter++){
cout<< *iter <<" ";
}
cout << endl;
return 0;
}
运行结果:
jdh@jdh-virtual-machine:~/program/datastruct/c_plus/sort$ ./a.out
1 2 3 4 5 7 8 9 10 11 23
快速排序
#include<iostream>
#include<vector>
using namespace std;
template<class T>
int partition(vector<T> &a, int left, int right){
int i = left;
int j = right;
T key = a[right];
for( j = left; j < right; j++){
if ( a[j] < key ){
swap(a[j], a[i]);
++i;
}
}
swap(a[i] , a[right]);
return i;
}
template<class T>
void quick_sort(vector<T> &a, int left, int right){
if ( left < right){
int q = partition(a, left, right);
quick_sort(a, left, q-1);
quick_sort(a, q+1, right);
}
}
int main(int argc, char **argv){
vector<int> a = {10, 8, 9, 1, 7, 4, 11, 23, 3, 2, 5};
int len = a.size();
vector<int>::iterator iter;
quick_sort<int>(a, 0, len-1);
for( iter = a.begin(); iter != a.end(); iter++){
cout<< *iter <<" ";
}
cout << endl;
return 0;
}
运行结果:
jdh@jdh-virtual-machine:~/program/datastruct/c_plus/sort$ g++ -std=c++11 quik_sort.cc
jdh@jdh-virtual-machine:~/program/datastruct/c_plus/sort$ ./a.out
1 2 3 4 5 7 8 9 10 11 23
堆排序
性质:
1、二叉堆在逻辑上是一个完全二叉树,但是我们可以采用数组的方式存储。
如果二叉堆数组从1开始存储,那么父亲i的左孩子下标为2i,右孩子下标为2i+1;同理结点i的父亲下标为i/2。
如果二叉堆数组从0开始,则父结点i左孩子的下标为2i+1,右孩子的下标2i+2.
2、小根堆,一个结点的权值小于其所在在子树其它结点的权值。
大根堆,一个结点的权值大于其所在子树其它结点的权值。
堆排序步骤;
1、将普通数组转换成大根堆数组
2、 a.将大根堆的第一个数和数组的最后一个数交换,修正除了最后一个数以外其余数的大根堆性质
b.重复a的步骤
#include<iostream>
#include<vector>
using namespace std;
inline int left(int i){
return 2*i+1;
}
inline int right(int i){
return 2*i+2;
}
template<class T>
void build_child_max_heap(vector<T> &a, int i, int len){
int max = i;
if ( left(i) < len ){
if ( a[i] < a[left(i)])
max = left(i);
}
if ( right(i) < len){
if ( a[right(i)] > a[max] )
max = right(i);
}
if ( max != i){
swap(a[max], a[i]);
build_child_max_heap(a, max, len);
}
}
template<class T>
void build_max_heap(vector<T> &a){
int len = a.size();
for ( int i = (len-1)/2; i >= 0; --i)
build_child_max_heap(a, i, len);
}
template<class T>
void heap_sort(vector<T> &a, int len){
build_max_heap(a);
for ( int i = len - 1; i > 0; --i){
swap(a[0], a[i]);
build_child_max_heap(a, 0, i);
}
}
int main(int argc, char **argv){
vector<int> a = {6, 8, 9, 1, 7, 4, 11, 23, 3, 2, 5};
int len = a.size();
vector<int>::iterator iter;
heap_sort(a, len);
for( iter = a.begin(); iter != a.end(); iter++){
cout<< *iter <<" ";
}
cout << endl;
return 0;
}
运行结果:
jdh@jdh-virtual-machine:~/program/datastruct/c_plus/sort$ g++ -g -std=c++11 heap_sort.cc
jdh@jdh-virtual-machine:~/program/datastruct/c_plus/sort$ ./a.out
1 2 3 4 5 6 7 8 9 11 23