排序八卦炉之总复习【改良版】

1.总结

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.总代码

点击 排序(C) 跳转码云获取完整代码

2.1Stack.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>

//静态栈
/*
#define N 10
typedef int STDataType;
typedef struct Stack
{
	STDataType a[N];
	int top;
}ST;
*/

typedef int STDataType;
typedef struct Stack
{
	int top;      //栈顶位置
	int capacity;
	STDataType* a;
}ST;

//初始化
void StackInit(ST* ps);

//销毁
void StackDestroy(ST* ps);

//压栈
void StackPush(ST* ps, STDataType x);

//出栈
void StackPop(ST* ps);

//栈顶数据
STDataType StackTop(ST* ps);

//判空
bool StackEmpty(ST* ps);

//栈大小
int StackSize(ST* ps);



2.2Stack.c

#include "Stack.h"

//初始化
void StackInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

//销毁
void StackDestroy(ST* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;
}

//压栈
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}

		ps->a = tmp;
		ps->capacity = newCapacity;
	}

	ps->a[ps->top] = x;
	ps->top++;
}

//出栈
void StackPop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));
	ps->top--;
}

//取栈顶
STDataType StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	return ps->a[ps->top - 1];
}

//判空
bool StackEmpty(ST* ps)
{
	assert(ps);

	return ps->top == 0;
}

//栈大小
int StackSize(ST* ps)
{
	assert(ps);

	return ps->top;
}

2.3Sort.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

//打印函数
void PrintArray(int* a, int n);

//插入排序
void InsertSort(int* a, int n);

//希尔排序
void ShellSort(int* a, int n);

//选择排序
void SelectSort(int* a, int n);

//堆排序
void HeapSort(int* a, int n);

//冒泡排序
void BubbleSort(int* a, int n);

//快速排序
extern int count;        //测试快排递归次数
void QuickSort(int* a, int begin, int end);
void QuickSort_NonRecursion(int* a, int begin, int end);

//归并排序
void MergeSort(int* a, int n);
void MergeSort_NonRecursion1(int* a, int n);
void MergeSort_NonRecursion2(int* a, int n);

//计数排序
void CountSort(int* a, int n);


2.4Sort.c

#include"sort.h"
#include"Stack.h"


//打印函数
void PrintArray(int* a, int n)
{
	for (int i = 0; i < n; ++i)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}

//插入排序1.0
/*
void InsertSort(int* a, int n)
{
	//i: 0 -- 倒数第2个元素
	for (int k = 0; k < n - 1; ++k)
	{
		//end记录i
		int end = k;
		//tmp记录end后一个值
		int tmp = a[end + 1];
		//把tmp与tmp前的每一个数比较 若小于则前面数据后移
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + 1] = a[end];
				--end;
			}
			else
			{
				break;
			}
		}
		//遇到<=tmp的数 或 tmp前数据遍历完毕 循环终止 把tmp放到目的地
		a[end + 1] = tmp;
	}
}
*/

//插入排序2.0--在这个版本中默认第一个已排好序 在内层for中会与i前的比较 
//直接插入排序没什么问题 但是在下面的希尔排序 第一个元素不能被默认为已经有序
//所以插入排序3.0更好一些 对下面的代码复用起到很好的作用
/*
void InsertSort(int* a, int n)
{
	int k, k, t;
	for (k = 1; k < n; k++)  //i:1 ~ n-1 a[0]默认已排好序
	{
		//临时变量t记录a[k]的值  下面程序a[k]会被修改
		t = a[k];
		//遍历i前所有数据 把比a[k]大的都向后移
		for (k = k - 1; k >= 0 && t < a[k]; k--)
			a[k + 1] = a[k];
		//j的初值为i-1  k!=k-1:i前有比a[k]大的 a[k]移到a[k+1]
		//此时内层for循环已终止 表明i前数据已有序 需要把原a[k]插到合适位置
		if (k != k - 1)
			a[k + 1] = t;
	}
}
*/

//插入排序3.0
void InsertSort(int* a, int n)
{
	int i, j, t;
	for (i = 0; i < n - 1; i++)
	{
		t = a[i + 1];
		for (j = i; j >= 0 && t < a[j]; j--)
			a[j + 1] = a[j];
		if (j != i)
			a[j + 1] = t;
	}
}

//希尔排序1.0
/*
void ShellSort(int* a, int n)
{
	int x = 3;

	for (int k = 0; k < x; ++k)
	{
		for (int k = k; k < n - x; k += x)
		{
			int end = k;
			int tmp = a[end + x];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + x] = a[end];
					end -= x;
				}
				else
				{
					break;
				}
			}
			a[end + x] = tmp;
		}
	}
    PrintArray(a, n);
}
*/
//希尔排序2.0
/*
void ShellSort(int* a, int n)
{
	int x = n;
	while (x > 1)
	{
		x = x / 3 + 1;

		for (int k = 0; k < n - x; ++k)
		{
			int end = k;
			int tmp = a[end + x];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + x] = a[end];
					end -= x;
				}
				else
				{
					break;
				}
			}
			a[end + x] = tmp;
		}

		printf("x:%d->", x);
		PrintArray(a, n);
	}
}
*/

//希尔排序3.0
void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		int i, j, t;
		//printf("x:%d->", x);
		//PrintArray(a, n);
		for (i = 0; i < n - gap ; ++i)
		{
			t = a[i + gap];
			for (j = i ; j >= 0 && t < a[j]; j-=gap)
			{
				a[j + gap] = a[j];
			}
			if (j != i)
				a[j + gap] = t;
		}
		//printf("x:%d->", x);
		//PrintArray(a, n);
		//printf("\n");
	}
}

void Swap(int* a, int* b)
{
	if (*a == *b)
		return;
	else
	{
		int t = *a;
		*a = *b;
		*b = t;
	}
}

//插入排序: O(num)~O(num^2)
//选择排序:O(num^2)~O(num^2)
//当数据趋于有序或随机(可能部分有序) 插排更优
void SelectSort(int* a, int n)
{
	assert(a);
	//i:数据头 j:数据尾
	for (int i = 0, j = n - 1; i < j; ++i, --j)
	{
		//假设最大值/最小值下标为i
		int m = i, M = i;
		//遍历i后到j的所有数据 确定real_m/M
		for (int k = i + 1; k <= j; ++k)
		{
			if (a[k] < a[m])
				m = k;

			if (a[k] > a[M])
				M = k;
		}
		//小值换到数据头
		Swap(&a[i], &a[m]);
		//特殊情况需重新匹配
		if (i == M)
		{
			M = m;
		}
		//大值换到数据尾
		Swap(&a[j], &a[M]);
	}
}

//堆排序 -- 升序建大堆 降序建小堆
void AdjustDwon(int* a, int size, int parent)
{
	//设左孩子较小
	int child = parent * 2 + 1;
	//当未达到堆末 进入循环
	while (child < size)
	{
		//确定real小孩子
		//if (child + 1 < size && a[child + 1] < a[child])  //小堆
		
		//确定real大孩子
		if (child + 1 < size && a[child + 1] > a[child])    //大堆
		{
			++child;
		}
		
		//if (a[parent] > a[child])    //小堆
		if (a[parent] < a[child])      //大堆
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
void HeapSort(int* a, int n)
{
	//下调建大堆
	for (int i = (n - 1 - 1) / 2; i >= 0; --i)
	{
		AdjustDwon(a, n, i);
	}
	//排序
	int end = n - 1;           //此时end表示堆尾数据的下标
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDwon(a, end, 0); //此时end表示传过去数据个数(n-1)
		--end;
	}
}

//插入排序  O(num)~O(num^2)
//冒泡排序  O(num)~O(num^2)
//当数据有序 二者均为O(num)
//当数据接近有序或局部有序 插排更优
void BubbleSort(int* a, int n)
{
	assert(a);
	int flag = 1;
	for (int i = 0; flag && i < n - 1; ++i)
	{
		flag = 0;
		for (int j = 0; j < n - 1 - i; ++j)
		{
			if (a[j] > a[j + 1])
			{
				Swap(&a[j + 1], &a[j]);
				flag = 1;
			}
		}
	}
}

//快速排序   O(num * logN)
int count = 0;  //测试递归次数
//对任意区间三值取中位数
int GetMid_X(int* a, int begin, int end)
{
	int mid = (begin + end) / 2;

	if (a[begin] < a[mid])
	{
		if (a[mid] < a[end])
			return mid;
		else if (a[begin] < a[end])
			return end;
		else
			return begin;
	}
	else //a[begin] >= a[mid]
	{
		if (a[mid] > a[end])
			return mid;
		else if (a[begin] < a[end])
			return begin;
		else
			return end;
	}
}
//霍尔版本
int PartQuickSort1(int* a, int begin, int end)
{
	int left = begin, right = end, x = left;

	//确定更合适的key
	int mid_x = GetMid_X(a, begin, end);
	Swap(&a[x], &a[mid_x]);

	while (left < right)
	{
		//右找小
		while (left < right && a[right] >= a[x])
			--right;

		//左找大
		while (left < right && a[left] <= a[x])
			++left;

		Swap(&a[left], &a[right]);
	}

	Swap(&a[x], &a[left]);
	x = left;

	return x;
}
//挖坑版本
int PartQuickSort2(int* a, int begin, int end)
{
	int x = begin;
	
	//确定更合适的key
	int mid_x = GetMid_X(a, begin, end);
	Swap(&a[x], &a[mid_x]); 
	int key = a[x];
    
	while (begin < end)
	{
		while (begin < end && a[end] >= key)
			--end;
		a[x] = a[end];
		x = end;


		while (begin < end && a[begin] <= key)
			++begin;
		a[x] = a[begin];
		x = begin;
	}

	a[x] = key;
	return x;
}  
//指针版本
int PartQuickSort3(int* a, int begin, int end)
{   //prv:previous  cp:current pointer
	int prv = begin, cp = begin + 1, x = begin;
	//确定更合适的key
	int mid_x = GetMid_X(a, begin, end);
	Swap(&a[x], &a[mid_x]);
	while (cp <= end)
	{
		if (a[cp] < a[x] && ++prv != cp)
			Swap(&a[prv], &a[cp]);
		++cp;
	}
	Swap(&a[prv], &a[x]);
	x = prv;
	return x;
}

void QuickSort(int* a, int begin, int end)
{
	count++;
	//begin:左区间左边界下标 
	//end  :右区间右边界下标
	//begin==end:数据量=1 无需排序 直接返回
	//begin>end :无效区间 无需排序 直接返回
	if (begin >= end)
		return;

	int x = PartQuickSort3(a, begin, end);

	// [begin, x - 1] x [x + 1, end]
	QuickSort(a, begin, x - 1);
	QuickSort(a, x+1, end);
}

/*
void QuickSort(int* a, int begin, int end)
{
	arr++;
	if (begin >= end)
		return;
	
	if (end - begin > 10)
	{
		int x = PartQuickSort3(a, begin, end);
		
		// [begin, x-1] x [x+1, end]
		QuickSort(a, begin, x - 1);
		QuickSort(a, x + 1, end);
	}
	else 
		InsertSort(a + begin, end - begin + 1);
}
*/
//非递归版本
void QuickSort_NonRecursion(int* a, int begin, int end)
{
	ST st;
	StackInit(&st);

	StackPush(&st, begin);
	StackPush(&st, end);

	while (!StackEmpty(&st))
	{
		int end = StackTop(&st);
		StackPop(&st);
		int begin = StackTop(&st);
		StackPop(&st);

		int x = PartQuickSort3(a, begin, end);
		 
		if (x + 1 < end)
		{
			StackPush(&st, x + 1);
			StackPush(&st, end);
		}
		// [begin, x-1] x [x+1, end]
		if (begin < x - 1)
		{
			StackPush(&st, begin);
			StackPush(&st, x - 1);
		}
	}
	StackDestroy(&st);
}

//归并排序 时间复杂度:O(num*logN)   空间复杂度:O(num)
void PartMergeSort(int* a, int begin, int end, int* tmp)
{
	if (begin >= end)
		return;

	int mid = (begin + end) / 2;

	//[begin, mid] [mid+1, end] 
	PartMergeSort(a, begin, mid, tmp);
	PartMergeSort(a, mid + 1, end, tmp);

	//[begin, mid] [mid+1, end]
	//  [index, mid]     [k, end]
	int i = begin, j = mid + 1, k = i;
	while (i <= mid && j <= end)
	{
		if (a[i] <= a[j])
			tmp[k++] = a[i++];
		else
			tmp[k++] = a[j++];
	}

	while (i <= mid)
		tmp[k++] = a[i++];
	while (j <= end)
		tmp[k++] = a[j++]; 
	
	memcpy(a + begin, tmp + begin, (end - begin + 1) * sizeof(int));
}
void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	//void PartMergeSort(int* a, int begin, int end, int* tmp);
	PartMergeSort(a, 0, n - 1, tmp);
	free(tmp);
}
void MergeSort_NonRecursion1(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}

	int range = 1;
	while (range < n)
	{
		printf("num = %d ->", range);
		for (int index = 0; index < n; index += 2 * range)
		{
			int i = index, k = i,  end = index + range - 1;
			int j = index + range, End = index + 2 * range - 1;
			
			//修正边界
			if (end >= n)
			{
				end = n - 1;
				j = n;
				End = n - 1;
			}
			else if (j >= n)
			{
				j = n;
				End = n - 1;
			}
			else if (End >= n)
				End = n - 1;
			printf("[%d,%d]--[%d, %d]  ", i, end, j, End);
			//数据排序
			while (i <= end && j <= End)
			{
				if (a[i] <= a[j])
					tmp[k++] = a[i++];
				else
					tmp[k++] = a[j++];
			}
			while (i <= end)
				tmp[k++] = a[i++];
			while (j <= End)
				tmp[k++] = a[j++];
		}
		printf("\n");
		memcpy(a, tmp, sizeof(int) * n);
		range *= 2;
	}

	free(tmp);
}
void MergeSort_NonRecursion2(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}

	int range = 1;
	while (range < n)
	{
		printf("num=%d->", range);
		for (int index = 0; index < n; index += 2 * range)
		{
			int i = index, k = i, end = index + range - 1;
			int j = index + range, End = index + 2 * range - 1;
            if (end >= n || j >= n)
				break;
			else if (End >= n)
				End = n - 1;
			printf("[%d,%d]--[%d,%d]  ", i, end, j, End);
			int m = End - i + 1;
			while (i <= end && j <= End)
			{
				if (a[i] <= a[j])
					tmp[k++] = a[i++];
				else
					tmp[k++] = a[j++];
			}
            while (i <= end)
				tmp[k++] = a[i++];
			while (j <= End)
				tmp[k++] = a[j++];
			memcpy(a + index, tmp + index, sizeof(int) * m);
		}
		printf("\n");
		range *= 2;
	}
	free(tmp);
}

//计数排序  时间复杂度:O(max(num, N)) 空间复杂度:O(num)
void CountSort(int* a, int n)
{
	//确定最值
	int min = a[0], max = a[0];
	for (int i = 1; i < n; ++i)
	{
		if (a[i] < min)
			min = a[i];
		if (a[i] > max)
			max = a[i];
	}
	int num = max - min + 1;  //最多有N个"连续"的数据
	//开空间
	int* arr = (int*)malloc(sizeof(int) * num);
	if (arr == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	memset(arr, 0, sizeof(int) * num);

	//a的数据映射到arr的下标 arr的值存储对应数据出现次数
	for (int i = 0; i < n; ++i)
		arr[a[i] - min]++;
	for (int i = 0, j = 0; i < num; ++i)
	{
		while (arr[i]--)
			a[j++] = i + min;
	}
}

2.5Test.c

#include "Sort.h"

//插入排序
void TestInsertSort()
{ 
	int a[] = { 4, 9,5, 2, 6, 3, 8, 5, 1, 7, 10 };
	InsertSort(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

//希尔排序
void TestShellSort()
{
	int a[] = { 4, 9, 2, 6, 3, 8, 5, 1, 7, 10 };
	ShellSort(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

//选择排序
void TestSelectSort()
{
	int a[] = { 4, 9, 2, 6, 3, 8, 5, 1, 7 };
	SelectSort(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

//冒泡排序
void TestBubbleSort()
{
	int a[] = { 4, 9, 2, 6, 3, 8, 5, 1, 7 };
	BubbleSort(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

//快速排序
void TestQuickSort()
{
	int a[] = { 4, 9, 2, 6, 3, 8, 5, 1, 7, 10 };
	//QuickSort(a, 0, sizeof(a) / sizeof(int)-1);
	QuickSort_NonRecursion(a, 0, sizeof(a) / sizeof(int) - 1);

	PrintArray(a, sizeof(a) / sizeof(int));
}

//归并排序
void TestMergeSort()
{
	int a[] = { 4, 2, 6, 3, 8, 5, 1, 7, 9 };
	printf("%u个数据\n", sizeof(a) / sizeof(int));
	//MergeSort(a, sizeof(a) / sizeof(int));
	//MergeSort_NonRecursion1(a, sizeof(a) / sizeof(int));
	MergeSort_NonRecursion2(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

//计数排序
void TestCountSort()
{
	int a[] = { -2,-4,-2,4,6,1,3,8,6,9,3 };
	CountSort(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

//性能测试
void TestOP()
{
	srand(time(0));
	const int N = 1000000;
	int* a1 = (int*)malloc(sizeof(int) * N);
	int* a2 = (int*)malloc(sizeof(int) * N);
	int* a3 = (int*)malloc(sizeof(int) * N);
	int* a4 = (int*)malloc(sizeof(int) * N);
	int* a5 = (int*)malloc(sizeof(int) * N);
	int* a6 = (int*)malloc(sizeof(int) * N);
	int* a7 = (int*)malloc(sizeof(int) * N);


	for (int i = 0; i < N; ++i)
	{
		a1[i] = rand();
		a2[i] = a1[i];
		a3[i] = a1[i];
		a4[i] = a1[i];
		a5[i] = a1[i];
		a6[i] = a1[i];
		a7[i] = a1[i];
	}

	//ShellSort(a1, N);

	int begin1 = clock();
	//InsertSort(a1, N);
	int end1 = clock();

	int begin2 = clock();
	//ShellSort(a3, N);
	int end2 = clock();

	int begin3 = clock();
	//SelectSort(a3, N);
	int end3 = clock();

	int begin4 = clock();
	//HeapSort(a4, N);
	int end4 = clock();

	int begin5 = clock();
	QuickSort(a5, 0, N - 1);
	int end5 = clock();

	int begin6 = clock();
	//MergeSort(a6, N);
	int end6 = clock();

	int begin7 = clock();
	//BubbleSort(a7, N);
	int end7 = clock();

	printf("InsertSort:%d\n", end1 - begin1);
	printf("ShellSort:%d\n", end2 - begin2);
	printf("SelectSort:%d\n", end3 - begin3);
	printf("HeapSort:%d\n", end4 - begin4);
	printf("QuickSort:%d\n", end5 - begin5);  printf("count:%d\n", count);
	printf("MergeSort:%d\n", end6 - begin6);
	printf("BubbleSort:%d\n", end7 - begin7);

	

	free(a1);
	free(a2);
	free(a3);
	free(a4);
	free(a5);
	free(a6);
	free(a7);
}

int main()
{
	//插入排序
	TestInsertSort();
	
	//希尔排序
	//TestShellSort();
	
	//选择排序
	//TestSelectSort();
	
	//堆排序
	//TestHeapSort();
	
	//冒泡排序
	//TestBubbleSort();
	
	//快速排序
	//TestQuickSort();
	
	//归并排序
	//TestMergeSort();
	
	//计数排序
	//TestCountSort();

	//性能测试
	//TestOP();

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿猿收手吧!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值