# 常用排序算法总结与分析

## 一：冒泡排序

template <typename T>
void bubble_sort(T* arr, const int size)
{
assert(arr != NULL && size > 0);
for(int i=0; i<size-1; ++i){
for(int j=0; j<size-1-i; ++j){
if(arr[j] > arr[j+1]){
std::swap(arr[j], arr[j+1]);
}
}
}
}


template <typename T>
void bubble_sort(T* arr, const int size)
{
assert(arr != NULL && size > 0);
bool flag = true;
for(int i=0; i<size-1; ++i){
for(int j=0; j<size-1-i; ++j){
if(arr[j] > arr[j+1]){
std::swap(arr[j], arr[j+1]);
flag = false;
}
}
if(flag)
break;
}
}


## 二：选择排序

template <typename T>
void select_sort(T* arr, const int size)
{
assert(arr != NULL && size > 0);
for(int i=0; i<size-1; ++i){
int min_index = i;
for(int j=i+1; j<size; ++j){
if(arr[j] < arr[min_index])
min_index = j;
}
if(min_index != i)
std::swap(arr[i], arr[min_index]);
}
}

swap(arr[i], min)，这么做完全是错误的。

## 三：插入排序

template <typename T>
void insert_sort(T* arr, const int size)
{
assert(arr != NULL && size > 0);
int j;
for(int i=1; i<size; ++i){
int temp = arr[i];
for(j=i-1; j>=0 && arr[j]>temp ; --j)  //j>=0防越界，记住用while循环是不要忘了break
arr[j+1] = arr[j];
arr[j+1] = temp;
}
}

## 四：希尔排序

template <typename T>
void shell_sort(T* arr, const int size, int increment)
{
assert(arr != NULL && size > 0 && increment > 0);
int j;
while(increment > 0){
for(int i=increment; i<size; i+=increment){
T temp = arr[i];
for(j=i-increment; j>=0 && arr[j]>temp; j-=increment){  //记住用while循环时不要忘了break
arr[j+increment] = arr[j];
}
arr[j+increment] = temp;
}
increment >>= 1;
}
}


## 五：归并排序

template <typename T>
void merge(T* arr, int low, int middle, int high)
{
T* tmp = new int[high-low+1];

int left = low;
int right = middle + 1;
int k = 0;

while(left <= middle && right <= high){
if(arr[left] < arr[right])
tmp[k++] = arr[left++];
else
tmp[k++] = arr[right++];
}

while(left <= middle)
tmp[k++] = arr[left++];
while(right <= high)
tmp[k++] = arr[right++];

for(int i=0; i<k; ++i)  //注意从arr从low开始
arr[low+i] = tmp[i];

delete []tmp;
}

template <typename T>
void merge_sort(T* arr, int low, int high)
{
if(low < high){
int middle = (int)((low + high) >> 1);
merge_sort(arr, low, middle);
merge_sort(arr, middle+1, high);
merge(arr, low, middle, high);
}
}


template <typename T>
void merge(T* arr, T* tmp, int low, int middle, int high)
{
int left = low;
int right = middle + 1;
int k = 0;

while(left <= middle && right <= high){
if(arr[left] < arr[right])
tmp[k++] = arr[left++];
else
tmp[k++] = arr[right++];
}

while(left <= middle)
tmp[k++] = arr[left++];
while(right <= high)
tmp[k++] = arr[right++];

for(int i=0; i<k; ++i)
arr[low+i] = tmp[i];
}

template <typename T>
void merge_sort(T* arr, T* tmp, int low, int high)
{
if(low < high){
int middle = (int)((low + high) >> 1);
merge_sort(arr, tmp, low, middle);
merge_sort(arr, tmp, middle+1, high);
merge(arr, tmp, low, middle, high);
}
}

template <typename T>
void merge_sort(T* arr, const int size)
{
assert(arr != NULL && size > 0);
T* tmp = NULL;
try{
tmp = new T[size];
}
std::cerr<<e.what()<<std::endl;
exit(1);
}
merge_sort(arr, tmp, 0, size-1);
delete []tmp;
}

## 六：快速排序

template <typename T>
int partition(T* arr, int low, int high)
{
int i = low;
int j = high + 1;
while(i < j){
while(arr[++i] < arr[low] && i < high);  //防止越界
while(arr[--j] > arr[low]);
if(i < j)
std::swap(arr[i], arr[j]);
}
std::swap(arr[low], arr[j]);
return j;
}

template <typename T>
void quick_sort(T* arr, int low, int high)
{
if(low < high){
int middle = partition(arr, low, high);
quick_sort(arr, low, middle-1);
quick_sort(arr, middle+1, high);
}
}



inline int random_range(int begin, int end)
{
return random()%(end-begin+1) + begin;    //注意+begin，因为begin不总是0
}

template <typename T>
int partition(T* arr, int low, int high)
{
int index = random_range(low, high);
std::swap(arr[index], arr[high]);

int small = low -1;
for(index=low; index<high; ++index){   //注意<high，因为最后一个元素是关键值
if(arr[index] < arr[high]){
++small;
if(small != index)   //不等于才交换
std::swap(arr[small], arr[index]);
}
}
++small;
std::swap(arr[small], arr[high]);
return small;
}

template <typename T>
void quick_sort_detail(T* arr, int low, int high)
{
if(low < high){
int middle = partition(arr, low, high);
quick_sort_detail(arr, low, middle-1);
quick_sort_detail(arr, middle+1, high);
}
}

template <typename T>
void quick_sort(T* arr, int low, int high)
{
assert(arr != NULL && low >= 0 && high > 0 && low < high);   //注意low>=0而不是>0
quick_sort_detail(arr, low, high);
}

## 七：堆排序

inline int left_child(int i) { return (i << 1) + 1; }

template <typename T>
void sift_down(T* arr, int i, const int size)
{
T tmp = arr[i];
int child = 0;
for(; left_child(i)<size; i=child){
child = left_child(i);
if(child != size-1 && arr[child] < arr[child+1])
++child;
if(tmp < arr[child])
arr[i] = arr[child];
else
break;
}
arr[i] = tmp;   //注意这里是i，不是child，不要写错。  //注意这句话，不能写进break处，因为有叶子结点情况，不会进循环
}

template <typename T>
void heap_sort(T* arr, const int size)
{
assert(arr != NULL && size > 0);
for(int i=(size>>1)-1; i>=0; --i)
sift_down(arr, i, size);  //bulidheap
for(int i=size-1; i>0; --i){
std::swap(arr[0], arr[i]);
sift_down(arr, 0, i);   //heapify
}
}