C语言实现各种排序(1)

#include<stdio.h>
//排序分为插入排序,希尔排序,冒泡排序,快速排序,选择排序,堆排序,归并排序,基数排序(桶排序)

//1.1
//直接插入排序,较为简单,思路为从第二个数开始逐个将其插入前面有序的序列中
//平均时间复杂度为O(N2),最快时间复杂度为O(N),最坏时间复杂度为O(N2),空间复杂度为O(1)
void InsertSort(int *a,int n) {
	int i;
	for (i = 2; i <= n; i++)
	{
		if (a[i-1] > a[i]) {
			int j = i - 1;
			a[0] = a[i];
			for (; j > 0 && a[j] > a[0]; j--) a[j + 1] = a[j];
			a[j + 1] = a[0];
		}
	}
}

//1.2
//折半插入排序
//思路相同,查找方法改为折半查找插入位置
void BInsertSort(int *a, int n)
{
	int i;
	for (i = 2; i <= n; i++)
	{
		if (a[i - 1] > a[i])
		{
			a[0] = a[i];
			int low = 1, high = i - 1;
			while (low <= high)
			{
				int mid = (low + high)/2;
				if (a[mid] > a[0]) high = mid - 1;
				else low = mid + 1;
			}
			int j;
			for (j = i - 1; j > high; j--) {
				a[j + 1] = a[j];
			}
			a[j + 1] = a[0];
		}
	}
}

//1.3
//二路插入排序
//具体实现不再写,思路为设置一个头指针为较小的数,设置一个尾指针为较大的数,开始循环查找,若数比头指针小则插入头指针前,若比尾指针大
//则插入尾指针后,若在二者之间则利用二分查找找到合适的插入位置进行位置变换。

//1.4
//希尔排序思路与直接插入排序相似,加入步长概念,原理为排较为有序的序列时时间较短
//平均时间复杂度O(N1.3),空间复杂度为O(1)
void ShellInsert(int *a, int n, int dk)//一趟希尔插入排序,dk为步长
{
	int i;
	for (i = dk + 1; i <= n; i++)
	{
		if (a[i - dk] > a[i])
		{
			a[0] = a[i];
			int j;
			for (j = i - dk; j > 0 && a[j] > a[0]; j -= dk) a[j + dk] = a[j];
			a[j + dk] = a[0];
		}
	}
}

void ShellSort(int *a, int n, int *dlt,int k)//按照增量为dlt[0...k-1]做一次希尔排序
{
	int i = 0;
	for (i = 0; i < k; i++)
	{
		ShellInsert(a, n, dlt[i]);
	}
}

//2.1
//基于交换的排序,冒泡排序法
//平均时间复杂度为O(N2),最坏时间复杂度为O(N2),最好时间复杂度为O(N)
void BubbleSort(int *a, int length)//相当于每次将最大或最小的排到最后一个
{
	for (int i = 0; i < length - 1; i++)
	{
		for (int j = 0; j < length - i - 1; j++)
		{
			if (a[j] > a[j + 1])
			{
				int temp;
				temp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = temp;
			}
		}
	}
}

//2.2
//快速排序,设置low和high两个指针,每次排完后找到一个枢轴,使其左边为比它小的元素,右边为比它大的元素;
//再继续对其左边和右边执行这个过程
//平均时间复杂度和最好时间复杂度都为O(N*logN),最坏时间复杂度为O(N2)
int Partition(int *a, int left,int right)
{
	int low = left, high = right;
	int base=a[low];
	while (low < high) {
		while (low<high&&a[high]>=base) high--;
		if (low < high) a[low] = a[high];  
		while (low < high&&a[low] <= base) low++;
		if (low < high) a[high] = a[low];
	}
	a[low] = base;
	return low;
}
void QSort(int *a, int left, int right) {
	if (left < right) {
		int pivotloc = Partition(a, left, right);
		QSort(a, left, pivotloc - 1);
		QSort(a, pivotloc + 1, right);
	}
}

//3.1
//基于选择的排序
//选择排序,思路为每次循环找到最小的并将其放在数组头处
//平均复杂度O(N2),最坏情况O(N2),最好情况O(N)
void SelectSort(int *a, int n)
{
	int i, j;
	int min, temp;
	for (i = 0; i < n-1; i++)
	{
		min = i;
		for (j = i; j < n; j++)
		{
			if (a[j] < a[min]) min = j;
		}
		temp = a[min];
		a[min] = a[i];
		a[i] = temp;
	}
}

//3.2
//堆排序 思路:建立堆,初始化堆,每次输出堆顶后将最后一个节点与堆顶互换,重新调整堆
//该排序为从小到大排序
//平均最坏最好时间复杂度都为O(N*logN)
typedef struct Heap {
	int length;
	int *elem;
}Heap;

void HeapAdjust(Heap H,int s,int m)//调整使其成为一个大顶堆
{
	int largest;
	int temp;
	int lc = 2 * s;
	int rc = lc + 1;
	if (H.elem[lc] > H.elem[s] && lc <= m) largest = lc;
	else largest = s;
	if (H.elem[rc] > H.elem[largest] && rc <= m) largest = rc;
	if (largest != s)
	{
		temp = H.elem[largest];
		H.elem[largest] = H.elem[s];
		H.elem[s] = temp;
		HeapAdjust(H, largest, m);
	}
}

void HeapSort(Heap H)
{
	int i, temp;
	for (i = H.length / 2; i > 0; i--)
	{
		HeapAdjust(H, i, H.length);
	}//初始化堆
	for (i = H.length; i > 1; i--)
	{
		temp = H.elem[1];
		H.elem[1] = H.elem[i];
		H.elem[i] = temp;
		HeapAdjust(H, 1, i-1);
	}//将堆顶和最后一个互换位置,然后对前i-1个元素重新调整
}

//4.1
//归并排序,平均最好最坏时间复杂度都为O(N*logN)
//思路对每一部分进行排序,使用的思想是归并思想,利用分治的策略解决问题
//重复比较加填入的方法



int main()
{
	int a[11] = { 0,3,1,3,2,4,5,6,1,7,13 };
	/*InsertSort(a, 10);*/				//插入排序测试
	/*BInsertSort(a, 10);*/				//二分插入排序测试
	/*int dlt[4] = { 4,3,2,1 };			//希尔排序测试
	ShellSort(a, 10, dlt, 4);*/			
	/*BubbleSort(a + 1, 10);*/			//冒泡排序测试
	/*QSort(a, 1, 10);*/				//快排测试
	/*SelectSort(a+1, 10);*/			//选择排序测试
	/*Heap H;							//堆排序测试
	H.elem = a;
	H.length = 10;
	HeapSort(H);*/
	for (int i = 1; i < 11; i++)
		printf("%d  ", a[i]);


}

猜你喜欢

转载自blog.csdn.net/weixin_43889775/article/details/85037519