排序|常见7种排序

常见的各种排序有哪些?
  1. 直接插入排序
  2. 希尔排序
  3. 冒泡排序
  4. 选择排序
  5. 堆排序
  6. 快速排序
  7. 归并排序

以上七种排序都是我们在学习中经常会遇到的常见的排序

插入排序

什么是插入排序?

当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移

假定有一个数组arr[] = { 3,5,8,4,7,9,1,2,6}
我们对其进行插入排序
在这里插入图片描述
简而言之就是我们将一个数据插入到前面已经排好序的数据中合适的位置

代码实现

void InsertSort(int *arr, int len)
{
	int i = 0;
	int end;
	int tmp;
	for (i; i < len - 1; i++)
	{
		end = i;
		tmp = arr[end + 1];
		while (end >= 0 && tmp < arr[end])
		{
			arr[end + 1] = arr[end];
			end--;
		}
		arr[end + 1] = tmp;
	}
}
希尔排序

什么是希尔排序?

希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个
组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。

在这里插入图片描述
希尔排序大大降低了插入排序的时间复杂度

代码实现

void ShellSort(int *arr, int len)
{
	int tap = len / 2;
	int i = 0;
	int end = 0;
	int tmp = 0;
	while (tap)
	{
		
		for (i = 0; i < len - tap; i++)
		{
			end = i;
			tmp = arr[end + tap];
			while (end >= 0 && arr[end]>tmp)
			{
				arr[end + tap] = arr[end];
				end = end - tap;
			}
			arr[end + tap] = tmp;
		}
		tap = tap / 2;
	}	
}
冒泡排序

什么是冒泡排序?

重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。

代码实现

void BubSort(int *arr, int len)
{
	int i = 0;
	int j = 0;
	int tmp;
	int folg = 0;
	for (i; i < len - 1; i++)
	{
		folg = 0;
		for (j = 0; j < len - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				folg = 1;
			}
		}
		if (folg == 0)
		{
			break;
		}
	}
}
选择排序

什么是选择排序?

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。

代码实现

void SelectSort(int *arr, int len)
{
	int max = 0;
	int min = 0;
	int begin = 0;
	int end = len - 1;
	int i = 0;
	while (begin < end)
	{
		for (i = begin; i <= end; i++)
		{
			if (arr[i] < arr[min])
				min = i;
			if (arr[i]>arr[max])
				max = i;
		}
		Swap(&arr[begin], &arr[min]);
		if (max == begin)
			max = min;
		Swap(&arr[end], &arr[max]);
		begin++;
		end--;
	}
}
堆排序

什么是堆排序?

堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。

堆排序的大致分成两个阶段:①建堆。②排序。

建堆
假设有一数组内容为 arr[] = {4,2,1,6,5}
我们根据这组数据先建立一刻树。
在这里插入图片描述
将其转化为大根堆。
根据大堆的性质,父亲节点的值要大于孩子节点的值,经过自低向上的调整,我们可以得到大根堆。
在这里插入图片描述
代码实现建堆

void MaxHeap(int *arr, int len, int n)
{
	int parent = n;
	int child = parent * 2 + 1;
	int tmp = 0;
	while (child < len)
	{
		if (child + 1 < len && arr[child] < arr[child + 1])
			child++;
		if (arr[parent] < arr[child])
		{
			tmp = arr[parent];
			arr[parent] = arr[child];
			arr[child] = tmp;
			parent = child;
			child = parent * 2 + 1;
		}
		else
			break;
		
	}
}

void BuildHeap(int *arr, int len)
{
	int i = len - 1;
	for (i; i >= 0; i--)
	{
		MaxHeap(arr, len, i);
	}
}

接下来我们进行第二阶段,排序
因为大根堆的性质可知,我们很容易的到当前数据中最大的元素,因此我们可以利用这一特性对其进行排序。
首先我们将根节点元素与最后一个节点元素进行交互,然后将除去最后一个元素的其他元素进行建堆的操作,这样我们就能得到第二大的数字,再将其与最后一个元素进行交换(这里的最后一个元素,不包括之前移动到末尾的那些元素)。
在这里插入图片描述
代码实现

void HaepSort(int *arr, int len)
{
	BuildHeap(arr, len); //建堆
	int tmp = 0;
	int n = len - 1;
	for (int i = len; i > 0; i--)
	{
		tmp = arr[0];    // 交换
		arr[0] = arr[i - 1];
		arr[i - 1] = tmp;
		MaxHeap(arr, --len, 0);  //再次建堆
	}
}
快速排序

什么是快速排序?

基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置为止。

假设数组内容为arr[] = {3 ,5,8,7,9,1}
我们以3为基准点,开始找三相对应的位置。

在这里插入图片描述
进过一次查找,我们把比3小的数字移动到了3的左边,比3三大的移动到了三的右边,同是我们将数值划分成了三部分,3,3的左半部分,三的右半部分。
接下来我们对于3的左半部分和右半部分分别进行排序。
代码实现

int PartSort(int *arr, int left, int right)
{
	int key = arr[left];
	int start = left;
	int tmp = 0;
	while(left < right)
	{
		while (left<right && arr[right] >= key)
		{
			right--;
		}
		while (left < right && arr[left] <= key)
		{
			left++;
		}
		Swap(&arr[left], &arr[right]);
	}
	Swap(&arr[start], &arr[left]);
	return left;
}

void QSort(int *arr, int left, int right)
{
	int mid = PartSort(arr, left, right);
	if (left<mid - 1)
		QSort(arr, left, mid - 1);
	if (mid + 1<right)
		QSort(arr, mid + 1, right);
}
归并排序

什么是归并排序?

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序。

在这里插入图片描述

代码实现

void _MergeSort(int *arr, int* NewArr, int left, int right, int mid)
{
	int begin1 = left;
	int begin2 = mid+1;
	int tmp = left;
	while (begin1 <= mid && begin2 <= right)
	{
		if (arr[begin1] < arr[begin2])
			NewArr[tmp++] = arr[begin1++];
		else
			NewArr[tmp++] = arr[begin2++];
	}
	while (begin1<=mid)
	{
		NewArr[tmp++] = arr[begin1++];
	}
	while (begin2 <= right)
	{
		NewArr[tmp++] = arr[begin2++];
	}
	for(tmp = left; tmp <= right; tmp++)
	{
		arr[tmp] = NewArr[tmp];
	}
}

void MergeSort(int *arr, int* NewArr, int left, int right)
{
	int mid = left + (right - left)/2;
	if (left < right)
	{
		MergeSort(arr, NewArr,left, mid);
		MergeSort(arr, NewArr, mid + 1, right);
	}
	_MergeSort(arr, NewArr, left, right, mid);
}
  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值