排序C语言实现

本文详细介绍了快速排序(QuickSort)、归并排序(MergeSort)的实现原理、 Hoare法与挖坑法的比较,以及非递归版本。涉及插入排序、选择排序、堆排序和计数排序等其他排序算法。适合深入理解排序算法在信息技术中的应用。
摘要由CSDN通过智能技术生成
#define _CRT_SECURE_NO_WARNINGS 1
#include"Sort.h"
void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
void InsertSort(int* a, int n)
{
	assert(a);
	int i = 0;
	int j = 0;
	for (i = 0; i < n - 1; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;
	}
}
void ShellSort(int* a, int n)
{
	int gap = 3;
	int j = 0;
	int i = 0;
	while (gap > 1)
	{
		gap =gap / 3 + 1;//gap不等于1的时候是在预排序
		for (i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp > a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
	
}
void SelectSort(int* a, int n)
{
	int left = 0;
	int right = n;
	while (left < right)
	{
		int max = left;
		int min = left;
		for (int i = left; i < right; i++)
		{
			if (a[i] > a[max])
			{
				max = i;
			}
			else if (a[i] < a[min])
			{
				min = i;
			}
		}
		Swap(&a[left], &a[min]);
		//如果left和max 相等 那么由于之前left位置的数和min位置互换 所以应该把max的值更正为min
		if (left == max)
		{
			max = min;
		}
		Swap(&a[right - 1], &a[max]);
		left++;
		right--;
	}
	
}
void AdjustDown(HPDataType* a, int n, int parent)
{

	int child = 2 * parent + 1;
	while (child < n)
	{
		if (a[child] > a[child + 1] && child + 1 < n)
		{
			child += 1;
		}
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}
void HeapSort(HPDataType* a, int n)//O(N*logN)
{
	//建堆
	//向下建堆O(N*logN)
	/*int i = 0;
	for (i = 0; i < n; i++)
	{
		AdjustUp(a, n, i);
	}*/
	//向上建堆O(N)
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(a, n, i);
	}
	//排升序用大堆,排降序用小堆
	int end = n - 1;
	while (end)
	{
		Swap(&a[0], &a[end]);
		end--;
		AdjustDown(a, end, 0);
	}
}
int GetMid(int* a, int left, int right)
{
	int mid = (left + right) / 2;
	if (a[left] > a[right])
	{
		if (a[right] > a[mid])
		{
			return right;
		}
		else if (a[mid] > a[left])
		{
			return left;
		}
		else
		{
			return mid;
		}
	}
	else//a[left] < a[right]
	{
		if (a[right] < a[mid])
		{
			return right;
		}
		else if (a[left] > a[mid])
		{
			return left;
		}
		else
		{
			return mid;
		}
	}
}
void QuickSort(int a[], int left, int right)//闭区间
{
	1.Hoare法//选取最左或最后作为key值,在从所选的对向开始找小于key数(升序),从key方向开始找大于key的数交换,直到相遇
	//if (left >= right)
	//{
	//	return;
	//}
	//int key = left;
	//int end = right;
	//int begin = left;
	//while (left < right)
	//{
	//	while (left < right && a[right] >= a[key])
	//	{
	//		right--;
	//	}

	//	while (left < right && a[left] <= a[key])
	//	{
	//		left++;
	//	}
	//	Swap(&a[left], &a[right]);
	//}
	//Swap(&a[key], &a[right]);
	//key = right;
	//QuickSort(a, begin, key - 1);
	//QuickSort(a, key + 1,end);
	
	//2.挖坑法//先将第一个数据放到一个临时变量中,形成一个坑位
	/*if (left >= right)
	{
		return;
	}
	int pit = left;
	int key = a[left];
	int begin = left;
	int end = right;
	
	while (left < right)
	{
		while (left < right && a[right] >= key)
		{
			right--;
		}
		a[pit] = a[right];
		pit = right;
		while (left < right && a[left] <= key)
		{
			left++;
		}
		a[pit] = a[left];
		pit = left;
	}
	a[pit] = key;
	QuickSort(a, begin, pit - 1);
	QuickSort(a, pit + 1, end);*/

	//前后指针法 以左边第一个值为key值 prev在第一个位置 cur在第二个位置 
	//cur先走如果遇到比key小的数的时候就和prev前面的数交换 因为prev指的是比key小的数
	//他的前一个数cur走过是大于key的交换后 prev更新位置
	
	if (left >= right)
	{
		return;
	}
	/*Swap(&a[prev], &a[left]);
	QuickSort(a, left, prev);
	QuickSort(a, prev + 1, right);*/
	if (right - left > 15)//如果数据量大于15 那么就采用递归
	{
		
		int prev = left;
		int cur = prev + 1;
		//三数取中优化
		Swap(&a[left], &a[GetMid(a, left, right)]);
		int key = a[left];
		while (cur <= right)
		{
			if (a[cur] < key && prev++ != cur)
			{
				Swap(&a[cur], &a[prev]);
			}
			cur++;
		}
		Swap(&a[prev], &a[left]);
		QuickSort(a, left, prev - 1);
		QuickSort(a, prev + 1, right);
	}
	else// 小于15 就采用插排减少递归次数
	{
		//swap(&a[prev], &a[left]);
		InsertSort(a + left, right - left + 1);
	}
}
void QuickSortNoR(int a[], int left, int right)//非递归快排
{
	Stack* st = (Stack*)malloc(sizeof(Stack));
	StackInit(st);
	StackPush(st, right);
	StackPush(st, left);
	while (!StackEmpty(st))
	{
		int begin = StackTop(st);
		StackPop(st);
		int prev = begin;
		int end = StackTop(st);
		StackPop(st);
		int cur = prev + 1;
		//三数取中优化
		Swap(&a[begin], &a[GetMid(a, begin, end)]);
		int key = a[begin];
		while (cur <= end)
		{
			if (a[cur] < key && prev++ != cur)
			{
				Swap(&a[cur], &a[prev]);
			}
			cur++;
		}
		Swap(&a[prev], &a[begin]);
		if (end > prev + 1)
		{
			StackPush(st, end);
			StackPush(st, prev + 1);
		}
		if (begin < prev - 1)
		{
			StackPush(st, prev);
			StackPush(st, begin);
		}
		
	}
	
}
void _MergeSort(int* a, int begin , int end, int* tmp)
{
	if (begin >= end)//如果空间中只有一个数或者空间不存在就返回
	{
		return;
	}

	int mid = (begin + end) / 2;
	_MergeSort(a, begin, mid, tmp);
	_MergeSort(a, mid + 1, end, tmp);//产生待排序的两段空间

	//归并
	int begin1 = begin;
	int end1 = mid;
	int begin2 = mid + 1;
	int end2 = end;
	int i = begin;
	
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}
	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}
	memcpy(a + begin, tmp + begin, (end - begin + 1)*sizeof(int));
}

void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(n * sizeof(int));
	_MergeSort(a, 0, n - 1,tmp);
	free(tmp);
}
void MergeSortNoR(int* a, int n)// 归并非递归
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	int gap = 1;
	while (gap < n)
	{
		//printf("gap = %d->", gap);
		for (int j = 0; j < n; j += 2 * gap)
		{
			//[begin][begin + gap -1],[begin + gap][begin + 2*gap -1]

			
			int begin1 = j;
			int end1 = begin1 + gap - 1;
			int begin2 = begin1 + gap;
			int end2 = begin2 + gap - 1;
			int i = begin1;
			int left = begin1;
			int right = end2;
			// 判断越界问题
			if (end1 >= n)// end1 越界
			{
				end1 = n - 1;
				begin2 = n;
				end2 = n - 1;
			}
			else if (begin2 >= n)// begin2越界
			{
				begin2 = n;
				end2 = n - 1;
			}
			else if (end2 >= n)// end2越界
			{
				end2 = n - 1;
			}
			//printf("[%d][%d] [%d][%d]--", begin1, end1, begin2, end2);
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] < a[begin2])
				{
					tmp[i++] = a[begin1++];
				}
				else
				{
					tmp[i++] = a[begin2++];
				}
			}
			while (begin1 <= end1)
			{
				tmp[i++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[i++] = a[begin2++];
			}
			memcpy(a + left, tmp + left, (right - left + 1) * sizeof(int));
		}
		//printf("\n");
		gap *= 2;
	}
	
	
}
void BubbleSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int flag = 1;
		for (int j = n - 1; j > i; j--)
		{
			if (a[j] < a[j - 1])
			{
				Swap(&a[j], &a[j - 1]);
				flag = 0;
			}
		}
		if (flag)
		{
			break;
		}
		flag = 1;
	}
}
void CountSort(int* a, int n)
{
	int min = a[0], max = a[0];
	for (int i = 0; i < n; i++)
	{
		if (a[i] < min)
		{
			min = a[i];
		}
		if (a[i] > max)
		{
			max = a[i];
		}
	}
	int range = max - min + 1;

	int* count = (int*)malloc(sizeof(int) * range);
	memset(count, 0, sizeof(int) * range);
	for (int j = 0; j < n; j++)
	{
		count[a[j] - min]++;
	}
	int i = 0;
	for (int j = 0; j < range; j++)
	{
		while (count[j]--)
		{
			a[i++] = j + min;
		}
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值