数据结构-C语言实现各种排序

参考:https://blog.csdn.net/qq_41998576/article/details/81635566
堆排序:https://blog.csdn.net/daiyudong2020/article/details/52529791
归并排序:https://www.cnblogs.com/agui521/p/6918229.html
一、 排序的分类
►插入排序:直接插入排序 希尔排序
►交换排序:冒泡排序 快速排序
►选择排序:简单选择排序 堆排序

二、排序算法比较

排序方法 最好时间 平均时间 最坏时间 辅助存储 稳定性
插入排序 O(n) O(n^2) O(n^2) O(1) 稳定
希尔排序 O(n^1.3) O(nlogn) O(n^2) O(1) 不稳定
冒泡排序 O(n) O(n^2) O(n^2) O(1) 稳定
快速排序 O(nlogn) O(nlogn) O(n^2) O(nlogn) 不稳定
选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定
选择排序 O(nlogn) O(nlogn) O(nlogn) O(1) 不稳定

从平均情况看:堆排序、归并排序、快速排序胜过希尔排序。
从最好情况看:冒泡排序和直接插入排序更胜一筹。
从最差情况看:堆排序和归并排序强过快速排序。

虽然直接插入排序和冒泡排序速度比较慢,但是当初始序列整体或局部有序是,这两种算法的效率比较高。当初始序列整体或局部有序时,快速排序算法效率会下降。当排序序列较小且不要求稳定性是,直接排序效率较好;要求稳定性时,冒泡排序法效率较好。

三、排序代码
// 直接插入排序 – 插入排序
/方法:对于给定的一组记录,初始时假定第一个记录自成一个有序的序列,
其余的记录为无序序列;接着从第二个记录开始,
按照记录的大小依次将当前处理的记录插入到其之前的有序序列中,
直至最后一个记录插入到有序序列为止。
/

void sort_insert(int *nums, int nums_length) {
	int i = 0;
	int j = 0;
	// 小 到 大
	for (i = 1; i < nums_length; i++) {
		int tmp = nums[i];
		for (j = i - 1; j >= 0 ; j--) {
			if (tmp < nums[j]) {
				nums[j + 1] = nums[j];
			}
			else {
				break;
			}
		}
		nums[j + 1] = tmp;
	}
}

// 希尔排序 – 插入排序
/*希尔排序也称为“缩小增量排序”,基本原理是:首先将待排序的元素分为多个子序列,
使得每个子序的元素个数相对较少,对各个子序分别进行直接插入排序,
待整个待排序序列“基本有序后”,再对所有元素进行一次直接插入排序。
具体步骤如下:

     (1)选择一个步长序列t1, t2, ..., tk,满足ti > tj(i <j),tk = 1。
     (2)按步长序列个数k,对待排序序列进行k趟排序。
     (3)每趟排序,根据对应的步长ti,将待排序的序列分割成ti个子序列,
	 分别对各个子序列进行直接插入排序。
void shellsort(int *arr, int arr_len)
{
	int i = 0;
	int j = 0;
	int step = 0;

	for (step = arr_len / 2; step > 0; step = step / 2)
	{
		for (i = step; i <= arr_len - 1; i++)
		{
			int tmp = arr[i];
			for (j = i - step; j >= 0; j -= step)
			{
				if (arr[j] > tmp)  // 小到大(>)   大到小(<)
				{
					arr[j + step] = arr[j];
				}
				else{
					break;
				}
			}
			arr[j + step] = tmp;
		}
	}
}

// 冒泡排序

void maopaosort(int *arr, int arr_len)
{
	int i = 0;
	int j = 0;

	for (i = 1; i <= arr_len - 1; i++)
	{
		for (j = 0; j < arr_len - 1; j++)
		{
			if (arr[j + 1] < arr[j])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

// 快速排序
/采用“分而治之”的思想,把大的拆分为小的,小的在拆分为更小的。
原理:对于一组给定的记录,通过一趟排序后,将原序列分为两部分,
其中前部分的所有记录均比后部分的所有记录小,然后再依次对前后两部分的记录进行快速排序,
递归该过程,直到序列中的所有记录均为有序为止。
/

void quick_sort(int *arr, int start, int end){
	if (start >= end) return;

	int i = start;
	int j = end;
	while (i < j)
	{
		while (arr[j] >= arr[start] && i < j) // 从基准数的对面开始走
			j--;
		while (arr[i] <= arr[start] && i < j)
			i++;

		if (i < j){
			int tmp = arr[i];
			arr[i] = arr[j];
			arr[j] = tmp;
		}
	}
	int tmp = arr[start];
	arr[start] = arr[i];
	arr[i] = tmp;

	quick_sort(arr, start, i -1);
	quick_sort(arr, i + 1, end);
}

// 选择排序
/对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将记录与第一个记录的位置进行交换;
接着对不包括第一个记录以外的其他记录进行第二轮排序,得到最小的记录并与第二个记录进行位置交换;
重复该过程,直到进行比较的记录只有一个为止。
/

void select_sort(int *arr, int arr_len)
{
	int i = 0;
	int j = 0;
	int min = 0;

	for (i = 0; i < arr_len - 1; i++) // time 
	{
		int min = i;
		for (j = i + 1; j <= arr_len - 1; j++)
		{
			if (arr[j] < arr[min])
			{
				min = j;
			}
		}
		if (min != i) {
			int tmp = arr[i];
			arr[i] = arr[min];
			arr[min] = tmp;
		}
	}
}

// 堆排序
/*
将序列构造成一棵完全二叉树 ;
把这棵普通的完全二叉树改造成堆,便可获取最小值 ;
输出最小值 ;
删除根结点,继续改造剩余树成堆,便可获取次小值 ;
输出次小值 ;
重复改造,输出次次小值、次次次小值,直至所有结点均输出,便得到一个排序 。
*/

void swap_heap(int *a, int *b) {
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

void adjust_min_heap(int *arr, int pos, int len) {
	int tmp = arr[pos];
	int child = pos;
	for (tmp = arr[pos]; 2 * pos + 1 < len; pos = child) {
		child = 2 * pos + 1;
		if (child + 1 < len && arr[child] < arr[child + 1]) {
			child++;
		}
		if (tmp < arr[child]) {
			arr[pos] = arr[child];
		}
		else {
			break;
		}
	}
	arr[pos] = tmp;
}

void heap_sort(int *arr, int arr_len) {
	// step 1 
	int i = 0;
	for (i = arr_len / 2 - 1; i >= 0; i--) {
		adjust_min_heap(arr, i, arr_len - 1);
	}
	// step 2 - 3
	for (i = arr_len - 1; i >= 0; i--) {
		swap_heap(&arr[0], &arr[i]);
		adjust_min_heap(arr, 0, i - 1);
	}
}

测试main函数

int main() {
	int nums[] = { 8, 2, 2, 2, 5, 3, 6, 7, 1, 9,0, 0, 0 };
	int nums_length = 13;

	int i = 0;
	printf("before sort_insert : ");
	for (i = 0; i < nums_length; i++) {
		printf(" %d ", nums[i]);
	}
	printf("\n");

	// sort_insert
	heap_sort(nums, nums_length);

	printf("after sort_insert : ");
	for (i = 0; i < nums_length; i++) {
		printf(" %d ", nums[i]);
	}
	printf("\n");
	stop;
	return 0;
}

你可能感兴趣的:(数据结构-C语言实现各种排序)