数据结构从青铜到王者第九篇:数据结构之排序

Posted 森明帮大于黑虎帮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构从青铜到王者第九篇:数据结构之排序相关的知识,希望对你有一定的参考价值。

在这里插入图片描述

系列文章目录



前言

在这里插入图片描述


一、排序的概念

1.排序的概念

  1. 排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
  2. 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。
  3. 内部排序:数据元素全部放在内存中的排序。
  4. 外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

二、常见排序算法的实现

1.插入排序

1.基本思想

直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。实际中我们玩扑克牌时,就用了插入排序的思想
在这里插入图片描述

2.代码实现

在这里插入图片描述
代码如下:

void InsertSort(int* arr, int sz)
{
	int i = 0;
	int j = 0;
	//多躺排序
	for (i = 0; i < sz - 1; i++)
	{
		int end = i;
		int tmp = arr[end + 1];
		//单趟排序
		while (end >= 0)
		{
			if (arr[end]>tmp)
			{
				arr[end + 1] = arr[end];
				end--;
			}
			else
			{
				break;
			}
		}
		arr[end + 1] = tmp;
	}
}

2.希尔排序

1.基本思想

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达1时,所有记录在统一组是直接排好序。
在这里插入图片描述

2.代码实现

在这里插入图片描述
代码如下:

void ShellSort(int* arr, int sz)
{
	//gap>1的时候,预排序
	//gap=1的时候,直接插入排序
	int gap = sz;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		for (int i = 0; i < sz - gap; i++)
		{
			int end = i;
			int tmp = arr[end + gap];
			while (end >= 0)
			{
				if (arr[end]>tmp)
				{
					arr[end + gap] = arr[end];
					end = end - gap;
				}
				else
				{
					break;
				}
			}
			arr[end + gap] = tmp;
		}
		printf("gap=%d ", gap);
		for (int i = 0; i < sz; i++)
		{
			printf("%d-->", arr[i]);
		}
		printf("NULL\\n");
	}

}

3.选择排序

1.基本思想

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

2.代码实现

在这里插入图片描述
代码如下:

void Swap(int *a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
void SelectSort(int* arr, int sz)
{
	int left = 0;
	int right = sz - 1;
	while (left < right)
	{
		int minIndex = left;
		int maxIndex = left;
		for (int i = left; i <= right; i++)
		{
			if (arr[i] < arr[minIndex])
			{
				minIndex = i;
			}
			if (arr[i]>arr[maxIndex])
			{
				maxIndex = i;
			}
		}
		Swap(&arr[left], &arr[minIndex]);
		if (left == maxIndex)
		{
			maxIndex = minIndex;
		}
		Swap(&arr[right], &arr[maxIndex]);
		left++;
		right--;
	}
}

4.堆排序

1.基本思想

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

2.代码实现

在这里插入图片描述
代码如下:

void swap(int* left, int* right)
{
	int tmp = 0;
	tmp = *left;
	*left = *right;
	*right = tmp;
}
void AdjustDown(int* arr, int sz, int parent)
{
	int child = 2 * parent + 1;
	while (child < sz)
	{
		if (child + 1 < sz&&arr[child + 1] > arr[child])
		{
			child++;
		}
		if (arr[child]>arr[parent])
		{
			swap(&arr[child], &arr[parent]);
			parent = child;
			child = 2 * parent + 1;
		}
		else
		{
			break;
		}
	}
}
//排升序,建大堆
void HeapSort(int *arr, int sz)
{
	//建堆
	int i = (sz - 1 - 1) / 2;
	for (i = (sz - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(arr, sz, i);
	}
	int end = sz - 1;	
	while (end > 0)
	{
		//选出次大的
		swap(&arr[0], &arr[end]);
		//最后一个不用交换,所以为n-1个数为end
		AdjustDown(arr, end, 0);
		end--;
	}
}

5.冒泡排序

1.基本思想

基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。
在这里插入图片描述

2.代码实现

在这里插入图片描述
代码如下:

void BubbleSort(int* arr, int sz)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int exchange = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j]>arr[j + 1])
			{
				int tmp = arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = tmp;
				exchange = 1;
			}
			if (exchange = 0)
			{
				break;
			}
		}
	}
}

6.快速排序递归思想

在这里插入图片描述

1.左右指针法
1.基本思想

在这里插入图片描述

2.代码实现

代码如下:

void Swap(int*a, int*b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
void QuickSort1(int* arr, int begin, int end)
{
	if (begin >= end)
	{
		return;
	}
	int midIndex = getMid(arr, begin, end);
	int left = begin;
	int right = end;
	Swap(&arr[left], &arr[midIndex]);
	int key = left;
	while (left<right)
	{
		while (left<right && arr[right] >= arr[key])
		{
			right--;
		}
		while (left<right && arr[left] <= arr[key])
		{
			left++;
		}
		Swap(&arr[left], &arr[right]);
	}
	int meet = left;
	Swap(&arr[key], &arr[meet]);
	QuickSort1(arr, begin, meet - 1);
	QuickSort1(arr, meet + 1, end);
}
2.挖坑法
1.基本思想

在这里插入图片描述

2.代码实现

代码如下:

//挖坑法
void QuickSort2(int* arr, int begin, int end)
{
	if (begin >= end)
	{
		return;
	}
	int left = begin;
	int right = end;
	int key = arr[begin];
	while (left < right)
	{
		while (left<right && arr[right] >= key)
		{
			right--;
		}
		//把值放到左边的坑位
		arr[left] = arr[right];
		while (left<right && arr[left] <= key)
		{
			left++;
		}
		//把值放到右边的坑位
		arr[right] = arr[left];
	}
	int meet = left;
	//最后相遇的位置就是坑位
	arr[meet] = key;
	QuickSort2(arr, begin, key - 1);
	QuickSort2(arr, key + 1, end);
}
3.前后指针法
1.基本思想

在这里插入图片描述

2.代码实现

代码如下:

void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
int partSort3(int* arr, int left, int right)
{
	int prev = left;
	int cur = left + 1;
	int key = left;
	while (cur <= right)
	{
		if (arr[cur] < arr[key] )
		{
			Swap(&arr[++prev], &arr[cur]);
		}
		cur++;
	}
	int meet = prev;
	Swap(&arr[key], &arr[prev]);
	return meet;
}
void QuickSort(int* a, int begin, int end)
{
	if (begin >= end)
		return;
	if (end - begin > 10)
	{
		int keyi = partSort3(a, begin, end);
		QuickSort(a, begin, keyi - 1);
		QuickSort(a, keyi + 1, end);
	}
	else
	{
		InsertSort(a + begin, end - begin + 1);
	}

}
4.快速排序优化方法
1.三数取中法

在这里插入图片描述
代码如下:

//三数取中
int getMid(int *arr, int left, int right)
{
	int mid = left + (right - left) / 2;
	if (arr[mid] > arr[left])
	{
		if (arr[mid] < arr[right])
		{
			return mid;
		}
		else if (arr[left]>arr[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
	else
	{
		if (arr[mid] > arr[right])
		{
			return mid;
		}
		else if (arr[left] < arr[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
}
2.小区间排序优化

在这里插入图片描述
代码如下:

void QuickSort(int* a, int begin, int end)
{
	if (begin >= end)
		return;
	if (end - begin > 10)
	{
		int keyi = partSort3(a, begin, end);
		QuickSort(a, begin, keyi - 1);
		QuickSort(a, keyi + 1, end);
	}
	else
	{
		InsertSort(a + begin, end - begin + 1);
	}
}

7.快速排序非递归思想

1.基本思想

在这里插入图片描述

2.代码实现

代码如下:

void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
int QuickSort(int* arr, int left, int right)
{
	int prev = left;
	int cur = left + 1;
	int key = left;
	while (cur <= right)
	{
		if (arr[cur] < arr[key])
		{
			Swap(&arr[++prev], &arr[cur]);
		}
		cur++;
	}
	int meet = prev;
	Swap(&arr[key], &arr[prev]);
	return meet;
}
void QuickSortNonR(int* arr, in

以上是关于数据结构从青铜到王者第九篇:数据结构之排序的主要内容,如果未能解决你的问题,请参考以下文章

Lua从青铜到王者基础篇第九篇:Lua元表

Linux从青铜到王者第九篇:Linux进程间通信第一篇

Love2d从青铜到王者第九篇:Love2d之库(library)

C++从青铜到王者第十九篇:C++二叉树进化之二叉搜索树

Linux从青铜到王者第十九篇:Linux网络基础第二篇之滑动窗口流量控制拥塞控制延迟应答捎带应答

数据结构从青铜到王者第七篇:数据结构之堆