假期训练专题及模板——排序

推荐一个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");
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值