栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

数据结构——排序

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

数据结构——排序

目录

常见的排序算法:

快速排序:

思想:

实现过程:

1、hoare版本

代码:

2、挖坑法

代码:

3、前后指针法

代码:

4.非递归版

代码:

选择排序:

思想:

代码:

堆排序:

思想:

代码:

插入排序:

思想:

代码:

希尔排序:

思想:

代码:


常见的排序算法:

快速排序:

思想:

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

实现过程:

1、hoare版本

首先实现单趟排序过程,选数组最左边的数作为keyi,设left,right,让右边right先走找小然后停下,再左边left找大然后停下,交换left,right的数值。循环知道left与right相遇,让后keyi与相遇位置交换,此时相遇位置为keyi正确位置。

单趟循环完后,进行递归,左区间递归,右区间递归。当区间只有一个或不存在递归结束。

初始状态:

 单趟排序:

 

int PartSort1(int* a, int left, int right)
//第一次循环结束后
//区间分为[left,keyi-1][keyi+1,right]进行递归

代码:
int PartSort1(int* a, int left, int right)
{
	int keyi = left;
	while (left < right)
	{

		while (left < right && a[right] >= a[keyi])
			--right;
		while (left < right && a[left] <= a[keyi])
			++left;

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

	Swap(&a[keyi], &a[left]);
	return left;
}

void QuickSort(int* a, int left, int right)
{
	if (left >= right)
		return;

	int keyi = PartSort1(a, left, right);

	QuickSort(a, left, keyi-1);
	QuickSort(a, keyi+1, right);
}

2、挖坑法

挖坑法的思想是将数组最左边的数作为第一个坑位,用key来记录第一个坑位的值,然后right从右找小,找到将right在数组中的值放在坑位中,自身形成坑位,然后left从左找,找到将left在数组中的值放到坑位中,自身形成坑位。循环知道相遇,将key放到相遇位置的坑位中,此时单趟循环结束。

初始状态:

 单趟循环:

 

 

代码:
int PartSort2(int* a, int left, int right)
{
	int key = a[left];
	int hole = left;

	while (left < right)
	{
		while (left < right && a[right] >= a[left])
			--right;
		a[hole] = a[right];
		hole = right;

		while (left < right && a[left] <= a[right])
			++left;
		a[hole] = a[left];
		hole = left;
	}
	a[hole] = key;
	return left;
}

void QuickSort(int* a, int left, int right)
{
	if (left >= right)
		return;

	int keyi = PartSort2(a, left, right);

	QuickSort(a, left, keyi-1);
	QuickSort(a, keyi+1, right);
}

3、前后指针法

前后指针法的思想是以数组最左边的值作为keyi来进行比较,设置前后指针prev与cur,prev为left,cur为left+1,当cur所指向的值小于prev所指向的值时,++prev并进行交换。知道cur>right停止循环,此时prev所指向的位置为keyi正确位置进行交换。

初始状态:

单趟循环:

代码:
int PartSort3(int* a, int left, int right)
{
	int keyi = left;
	int prev = left, cur = left + 1;

	while (cur <= right)
	{
		if (a[cur] < a[keyi] && a[++prev] != a[cur])
			Swap(&a[prev], &a[cur]);

		++cur;
	}

	Swap(&a[prev], &a[keyi]);
	return prev;
}


void QuickSort(int* a, int left, int right)
{
	if (left >= right)
		return;

	int keyi = PartSort3(a, left, right);

	QuickSort(a, left, keyi-1);
	QuickSort(a, keyi+1, right);
}

4.非递归版 代码:
void QuickSortR(int* a, int left, int right)
{
	Stack st;
	StackInit(&st, 10);

	if (left < right)
	{
		StackPush(&st, right);
		StackPush(&st, left);
	}

	while (StackEmpty(&st) != 0)
	{
		left = StackTop(&st);
		StackPop(&st);
		right = StackTop(&st);
		StackPop(&st);

		int div = PartSort1(a, left, right);

		// [left div-1]
		if (left < div - 1)
		{
			StackPush(&st, div - 1);
			StackPush(&st, left);
		}

		// [div+1, right]
		if (div + 1 < right)
		{
			StackPush(&st, right);
			StackPush(&st, div + 1);
		}
	}
}

选择排序: 思想:

每次从要排序的数组从中选择一个最小的数和一个最大的数,分别放在最前面和最后面。

代码:
void SelectSort(int* a, int n)
{
	int begin = 0, end = n - 1;
	while (begin < end)
	{
		int min = begin, max = begin;
		for (int i = begin; i <= end; i++)
		{
			if (a[i] <= a[min])
				min = i;

			else
				max = i;
		}

		Swap(&a[begin], &a[min]);

		//这里要考虑有可能最大的数位置是begin,begin与min交换位置后max的位置变了
		//所以这里判断是够max被换,要更新max位置

		if (begin == max)
			max = min;

		Swap(&a[end], &a[max]);

		++begin;
		--max;
	}
}

堆排序: 思想:

要升序建大根堆,降序建小跟堆。在已有的数组上直接建堆,使用向下调整建堆。建顿完成后每次取根,再进行调整。

假设建小根堆,向下调整的思想是选出孩子结点中小的,再跟根父亲结点进行比较,如果父亲结点小进行交换,更新父亲结点和孩子结点。当出现父亲结点大于孩子结点或者孩子结点出范围结束循环。

建堆的思想运用向下调整方法进行建堆,但是向下建堆的前提是左右结点必须是堆,所以从叶子结点的父亲结点进行调整。然后每次把根节点放在数组最后,进行循环。

代码:
void AdjustDwon(int* a, int n, int root)
{
	int father = root;
	int child = father * 2 + 1;
	while (child a[child + 1])
			++child;

		if (a[father] > a[child])
		{
			Swap(&a[father], &a[child]);
			father = child;
			child = father * 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;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);

		AdjustDwon(a, end, 0);
		--end;
	}
}

插入排序: 思想:

插入排序的思想类似于平时打牌,假设进行升序排序,每次把要插入的数跟前面最后一个进行比较,如何比它大不动,如果比他小,数组最后一个向后移动一位,在跟前一个进行比较,直到比它大停止。

代码:
void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; ++i)
	{
		int end = i;
		int tmp = a[end + 1];

		while (end >= 0 && a[end] > tmp)
		{
			a[end + 1] = a[end];
			--end;
		}
		a[end + 1] = tmp;
	}
}

希尔排序: 思想:

希尔排序的思想是在插入排序上进行优化的。

希尔排序是先进行预排序让较大的数先到后面,让较小的数先到前面。所以设置gap进行预排序。让数组以每gap为一组进行插入排序。然后gap=gap/3+1变化,预排序的gap逐渐变小直到最后gap为1是插入排序。

代码:
void ShellSort(int* a, int n)
{
	int gap = n;

	while (gap > 1)
	{
		gap = gap / 3 + 1;

		for (int 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;
		}
	}
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/843314.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号