一、各算法的时间复杂度
①平均时间复杂度
插入排序 O(n^2),冒泡排序 O(n^2),选择排序 O(n^2)
快速排序 O(n log n),堆排序 O(n log n),归并排序 O(n log n),基数排序 O(n),希尔排序 O(n^1.25)
②算法稳定性
选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法;
冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
##################
经典排序算法 – 插入排序Insertion sort
插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。
插入排序方法分直接插入排序和折半插入排序两种,这里只介绍直接插入排序,折半插入排序留到“查找”内容中进行。
图1演示了对4个元素进行直接插入排序的过程,共需要(a),(b),(c)三次插入。
##################
二、各算法的实现
/***************************************************************************
*
* Copyright (c) 2015 Baidu.com, Inc. All Rights Reserved
*
**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <new>
using namespace std;
template <class T>
void swap(T* a, T* b) {
T temp = *a;
*a = *b;
*b = temp;
}
// 冒泡排序
void bubble_sort(int* v, const int& len) {
if (v == NULL || len <= 0) {
return ;
}
int i;
int j;
for (i = 0; i < len - 1; ++i) {
for (j = 0; j < len - i - 1; ++j) {
if (v[j] > v[j + 1]) {
swap<int>(&v[j], &v[j + 1]);
}
}
}
}
// 选择排序
void select_sort(int* v, const int& len) {
if (v == NULL || len <= 0) {
return ;
}
int i;
int j;
for (i = 0; i < len - 1; ++i) {
for (j = i + 1; j < len; ++j) {
if (v[i] > v[j]) {
swap<int>(&v[i], &v[j]);
}
}
}
}
// 优化选择排序
void select_sort_better(int* v, const int& len) {
if (v == NULL || len <= 0) {
return ;
}
int i;
int j;
int k;
for (i = 0 ; i < len - 1; ++i) {
k = i;
for (j = i + 1; j < len; ++j) {
if (v[i] > v[j]) {
k = j;
}
}
if (k != i) {
swap<int>(&v[i], &v[k]);
}
}
}
// 快速排序
int partition(int*v, const int& low, const int& high) {
int i = low;
int j = high;
const int pivot = v[i];
while (i < j) {
while (i < j && pivot <= v[j]) {
--j;
}
if (i < j) {
v[i++] = v[j];
}
while (i < j && pivot >= v[i]) {
++i;
}
if (i < j) {
v[j--] = v[i];
}
}
v[i] = pivot;
return i;
}
void quick_sort(int* v, const int& low, const int& high) {
if (v == NULL || low < 0 || high <= 0) {
return ;
}
if (low < high) {
int pos = partition(v, low, high);
quick_sort(v, 0, pos - 1);
quick_sort(v, pos + 1, high);
}
}
// 插入排序
void insert_sort(int *v, const int& len) {
if (v == NULL || len <= 0 ) {
return ;
}
int i;
int j;
int temp;
for (i = 1; i < len; ++i) {
temp = v[i];
for (j = i; j > 0 && temp < v[j - 1]; --j) {
v[j] = v[j -1];
}
v[j] = temp;
}
}
// 归并排序
void merge(int* v, const int& low, const int& mid, const int& high) {
int i = low;
int j = mid + 1;
// 小数据测试,不用判断是否分配成功。现实产品线必需判断是否分配成功
int* buff = new (std::nothrow) int[high - low + 1];
if (buff == NULL) {
printf("fail to allocate buff memory");
exit(-1);
}
int index = 0;
while (i <= mid && j <= high) {
if (v[i] <= v[j]) {
buff[index] = v[i++];
} else {
buff[index] = v[j++];
}
++index;
}
while (i <= mid) {
buff[index++] = v[i++];
}
while (j <= high) {
buff[index++] = v[j++];
}
// 写回原数组
for (i = low; i <= high; ++i) {
v[i] = buff[i - low];
}
delete []buff;
buff = NULL;
}
void merge_sort(int* v, const int& low, const int& high) {
if (v == NULL || low < 0 || high <= 0) {
return ;
}
if (low < high) {
// mid = low + (high - low) >> 1
// 错误!栈溢出导致无穷循环
const int mid = low + ((high - low) >> 1);
merge_sort(v, low, mid);
merge_sort(v, mid + 1, high);
merge(v, low, mid, high);
}
}
// 希尔排序
void shell_sort(int* v, const int& len) {
if (v == NULL || len <= 0) {
return ;
}
int i;
int j;
int div;
int temp;
for (div = len / 2; div >= 1; div /= 2) {
for (i = div; i < len; ++i) {
temp = v[i];
for (j = i - div; j >= 0 && temp < v[j]; j -= div) {
v[j + div] = v[j];
}
v[j + div] = temp;
}
}
}
int main() {
int v[] = {1,3,5,7,9,0,8,6,4,2};
const int len = sizeof(v) / sizeof(int);
// bubble_sort(v, len);
// select_sort(v, len);
// quick_sort(v, 0, len - 1);
// insert_sort(v, len);
// merge_sort(v, 0, len - 1);
shell_sort(v, len);
for (int i = 0; i < len; ++i) {
printf("%d ", v[i]);
}
return 0;
}
/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */