推荐一个Youtube视频专辑,这个人说的非常清楚,每个算法10分钟内就说的非常明白,很赞。
基础排序算法:https://youtu.be/MrUMzthTXOs?list=PLJse9iV6Reqg-IffRqjxebaPg0zaPxWlt
进阶排序算法:https://www.youtube.com/playlist?list=PLJse9iV6ReqhrZyq301AtJuC6butyhmLY
代码是自己根据视频的解说实现的,如下:
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <climits>
#include <cstring>
#define NUM 100
#define MAX_NUM 9999999
void swap(int *a, int *b){
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
// O(n^2), 不稳定
void select_sorting(int* arr, int num){
int min_num, min_id;
int i, j;
for (i = 0; i < num; i++){
min_num = INT_MAX;
min_id = -1;
for (j = i; j < num; j++){
if (min_num > arr[j]){
min_num = arr[j];
min_id = j;
}
}
if (i != min_id){
swap(&arr[i], &arr[min_id]);
}
}
}
// O(n^2), 稳定
void bubble_sorting(int *arr, int num){
int i, j;
for (i = 0; i < num - 1; i ++){
for (j = 0; j < num - i - 1; j++){
if (arr[j] > arr[j + 1]){
swap(&arr[j], &arr[j + 1]);
}
}
}
}
//O((n^2) / 2),稳定
void cocktail_sorting(int *arr, int num){
int i, j;
for (i = 0; i < num / 2; i++){
for (j = i; j < num - i; j++){
if (arr[j] > arr[j + 1]){
swap(&arr[j], &arr[j + 1]);
}
}
for (j = num - i - 3; j >= i; j --){
if (arr[j] > arr[j + 1]){
swap(&arr[j], &arr[j + 1]);
}
}
}
}
//O(n^2), 稳定
void insertion_sorting(int *arr, int num){
int i, j;
int tmp;
for (i = 1; i < num; i++){
tmp = arr[i];
for (j = i - 1; arr[j] > tmp; j--){
arr[j + 1] = arr[j];
}
arr[j + 1] = tmp;
}
}
//O(n), 稳定
//消耗空间很大 O(max_num - min_num)
void bucket_sorting(int *arr, int num){
int min_num, max_num;
int i, j;
int *tmp_arr;
min_num = INT_MAX;
max_num = -1;
for (i = 0; i < num; i++){
if (min_num > arr[i]){
min_num = arr[i];
}
if (max_num < arr[i]){
max_num = arr[i];
}
}
tmp_arr = (int*)malloc((max_num - min_num) * sizeof(int));
memset(tmp_arr, 0, sizeof(int) * (max_num - min_num));
for (i = 0; i < num; i++){
++tmp_arr[arr[i] - min_num];
}
for (i = j = 0; i < max_num - min_num + 1; i++){
while (tmp_arr[i] > 0){
arr[j++] = i;
--tmp_arr[i];
}
}
free(tmp_arr);
}
// O(nlogn), 不稳定
// 使用递归,导致消耗内存较大
// 适用于大数量的时候
void quick_sorting(int *arr, int left, int right){
if (left > right){
return;
}
int i, j;
int tmp = arr[left];
for (i = left, j = right; i < j; ){
while (arr[j] >= tmp && i < j){
--j;
}
while (arr[i] <= tmp && i < j){
++i;
}
if (i < j){
swap(&arr[i], &arr[j]);
}
}
swap(&arr[left], &arr[i]);
quick_sorting(arr, left, i - 1);
quick_sorting(arr, i + 1, right);
}
// MergeSort O(nlogn), 稳定
// 比堆排序更快一些
// 消耗堆排序一倍的内存。
void merge(int *arr, int left, int mid, int right){
int i, j, k;
int tmp_arr[NUM];
for (i = mid + 1; i > left; i--){
tmp_arr[i - 1] = arr[i - 1];
}
for (j = mid ; j < right; j++){
tmp_arr[right + mid - j] = arr[j + 1];
}
for (k = left; k <= right; k++){
if (tmp_arr[j] < tmp_arr[i]){
arr[k] = tmp_arr[j--];
}
else{
arr[k] = tmp_arr[i++];
}
}
}
void merge_sorting (int *arr, int left, int right){
if (left >= right){
return;
}
int mid = (left + right) / 2;
merge_sorting(arr, left, mid);
merge_sorting(arr, mid + 1, right);
merge(arr, left, mid, right);
}
void merge_sorting2(int *arr, int left, int right){
int mid, i;
for (mid = 1; mid <= right - left; mid = mid + mid){
for (i = left; i <= right - mid; i += mid + mid){
merge(arr, i, i + mid - 1, (i + mid + mid - 1) <= right ? (i + mid + mid - 1) : right);
}
}
}
// Binary Search Tree Sort,O(nlogn) 不稳定
// 需要较多内存空间,可能出现不平衡的BST, 所以最好使用AVL Tree优化。
struct binary_tree{
int value;
struct binary_tree *left;
struct binary_tree *right;
};
void binary_tree_insert(struct binary_tree **top, int val){
if (*top == NULL){
*top = (struct binary_tree * )malloc(sizeof (struct binary_tree));
(*top) -> value = val;
(*top) -> left = NULL;
(*top) -> right = NULL;
return ;
}
if (val < (*top) -> value){
binary_tree_insert(&(*top) -> left, val);
}
else{
binary_tree_insert(&(*top) -> right, val);
}
}
void traverse_binary_tree(struct binary_tree *top, int *arr, int *index){
if (top == NULL){
return;
}
if (top -> left != NULL){
traverse_binary_tree(top -> left, arr, index);
}
arr[(*index)++] = top -> value;
if (top -> right != NULL){
traverse_binary_tree(top -> right, arr, index);
}
}
void free_tree(struct binary_tree *top){
if (top -> left != NULL){
free_tree(top -> left);
}
if (top -> right != NULL){
free_tree(top -> right);
}
if (top -> left == NULL && top -> right == NULL){
free(top);
}
}
void binary_sorting(int *arr, int num){
struct binary_tree *top;
int i;
int index = 0;
for (i = 0 ; i < num; i++){
binary_tree_insert(&top, arr[i]);
}
traverse_binary_tree(top, arr, &index);
free_tree(top);
}
// Shell Sorting O (nlogn)
// 比冒泡快5倍,比插入排序快2倍,比Quicksort, MergeSort, HeapSort慢很多
// 适用于5000以下的数据量。
void shell_sorting(int *arr, int num){
int gap, i, j, temp;
for (gap = num / 2; gap > 0; gap /= 2){
for (i = gap; i < num; i++){
for (j = i - gap; j >= 0 && arr[j] > arr[j + gap]; j -= gap){
swap(&arr[j], &arr[j + gap]);
}
}
}
}
// Heap Sorting O(nlogn), 不稳定
// 适用于大数据量,百万级别
// In-Place的方法
void heap_siftdown(int *heap, int i){
int flag = 0;
int tmp;
int num = heap[0];
while (i * 2 <= num && flag == 0){
tmp = i * 2;
if (i * 2 + 1 <= num){
tmp = heap[tmp] < heap[i * 2 + 1] ? tmp : i * 2 + 1;
}
if (heap[tmp] < heap[i]){
swap(&heap[tmp], &heap[i]);
i = tmp;
}
else{
flag = 1;
}
}
}
int* heap_create(int *arr, int num){
int i;
int *heap = (int *)malloc(sizeof(int) * (num + 1));
for (i = 0; i < num; i++){
heap[i + 1] = arr[i];
}
heap[0] = num;
for (i = num / 2; i >= 1; i--){
heap_siftdown(heap, i);
}
return heap;
}
void heap_delete(int *heap){
int tmp;
swap(&heap[1], &heap[heap[0]]);
--heap[0];
heap_siftdown(heap, 1);
}
void heap_sorting(int *arr, int num){
int *heap;
int i;
heap = heap_create(arr, num);
for (i = 0; i < num; i++){
heap_delete(heap);
arr[i] = heap[num - i];
}
free(heap);
}
//Count Sorting O(n + k), 稳定
// 消耗过多内存。
void count_sorting(int *arr, int num){
int i, j;
int range = 1024;
int *count = (int *)malloc(sizeof(int) * range);
int *result = (int *)malloc(sizeof(int) * num);
memset(count, 0, sizeof(sizeof(int) * num));
for (i = 0; i < num; i++){
count[arr[i]]++;
}
for (i = 1; i < range; ++i){
count[i] += count[i - 1];
}
for (i = num - 1; i >= 0; --i){
result[--count[arr[i]]] = arr[i];
}
for (i = 0; i < num; i++){
arr[i] = result[i];
}
free(count);
free(result);
}
//Radix Sorting O(logRB), R是基数,B是10. 稳定
// 需要至少(NUM)的内存空间
int radix_maxbit(int *arr, int num){
int d, i, maxd;
int p;
for (i = 0, maxd = -1; i < num; i++){
d = 1;
p = 10;
while (arr[i] >= p){
p *= 10;
++d;
}
if (maxd < d){
maxd = d;
}
}
return maxd;
}
void radix_sorting(int *arr, int num){
int d = radix_maxbit(arr, num);
int *tmp = (int *)malloc(sizeof(int) * num);
int count[10];
int i, j, k;
int radix = 1;
for (i = 1; i <= d; i++){
memset(count, 0, sizeof(int) * 10);
for (j = 0; j < num; j++){
k = (arr[j] / radix) % 10;
++ count[k];
}
for (j = 1; j < 10; j++){
count[j] += count[j - 1];
}
for (j = num - 1; j >= 0; j--){
k = (arr[j] / radix) % 10;
tmp[count[k] - 1] = arr[j];
--count[k];
}
for (j = 0; j < num; j++){
arr[j] = tmp[j];
}
radix *= 10;
}
free(tmp);
}
int main(void){
int arr[NUM];
int i;
int select = 13;
srand(0);
for (i = 0; i < NUM; i++){
arr[i] = rand() % 1000;
}
for (i = 0; i < NUM; i++){
printf("%d\t", arr[i]);
}
printf("\n");
switch(select){
case 1:
select_sorting(arr, NUM);
break;
case 2:
bubble_sorting(arr, NUM);
break;
case 3:
cocktail_sorting(arr, NUM);
break;
case 4:
insertion_sorting(arr, NUM);
break;
case 5:
bucket_sorting(arr, NUM);
break;
case 6:
quick_sorting(arr, 0, NUM - 1);
break;
case 7:
merge_sorting(arr, 0, NUM - 1);
break;
case 8:
merge_sorting2(arr, 0, NUM - 1);
break;
case 9:
binary_sorting(arr, NUM);
break;
case 10:
shell_sorting(arr, NUM);
break;
case 11:
heap_sorting(arr, NUM);
break;
case 12:
count_sorting(arr, NUM);
break;
case 13:
radix_sorting(arr, NUM);
break;
default:
printf("NO SORTING METHOD\n");
}
for (i = 0; i < NUM; i++){
printf("%d\t", arr[i]);
}
printf("\n");
}