数据结构与算法之三 深入学习排序

在本章中,你将学习:

通过使用快速排序来排序数据

通过使用归并排序来排序数据

快速排序算法:

快速排序是最有效率的排序算法之一,此算法基于分治法

连续将问题细分为更小的问题直到问题成为可以直接解决的小问题

在快速排序算法中,你:

从名为枢轴的列表处选择元素。

将列表划分为两部分:

列表左端的所有元素小于等于枢轴。

列表右端的所有元素大于枢轴。

在此列表两部分的正确位置存储枢轴

划分之后为创建的两个子列表重复此过程(找枢轴的过程)。

直到每个子列表中只剩一个元素。

思想:就是不断找出符合条件的枢轴位置

编写一个算法以实现快速排序:

QuickSort(low,high)

1. 如果 (low > high):

a.  返回

2. 设置 pivot = arr[low]

3. 设置 i = low + 1

4. 设置 j = high

5. 重复第 6步直到 i > high
或 arr[i] > pivot
// 搜索大于枢轴的元素

6. 按1递增 i

7. 重复第 8步直到 j < low
或 arr[j] < pivot
// 搜索小于枢轴的元素

8. 按1递减 j

9. 如果 i < j:
//如果较大的元素位于较小元素的左侧

a.  交换 arr[i]
与 arr[j]

10. 如果 i <= j:

a.  转到第 5步//
继续搜索

11. 如果low < j:

a.  交换 arr[low]
与 arr[j]//交换枢轴与列表第一部分的最后一个元素

12. QuickSort(low,J – 1)
//对枢轴左侧的列表应用快速排序

13. QuickSort(J + 1, high) //对枢轴右侧的列表应用快速排序

此排序算法的总时间取决于枢轴值的位置。

最糟的情形出现在列表已经排序时。

通常,选择第一个元素作为枢轴,但是其会导致O(n2)的最糟用例效率。

如果您选择所有值的中间值作为枢轴,则效率将是O(n log n)。

什么是快速排序算法的平均用例的比较总次数。

答案:

O(n log n)

归并排序算法:

其使用分治法来排序列表

要排序的列表将分为两个几乎相等的两个子列表

这两个子列表将通过使用归并排序单独排序

这两个排序的子列表归并为单个排序的列表

编写一个算法以实现归并排序:

MergeSort(low,high)

1. 如果 (low >= high):

  a. 
返回调用本函数的地方.

2. 设置 mid = (low + high)/2

3. 将列表划分为几乎完全相等的两个子列表,并通过使用归并排序来排序每个子列表。执行的步骤如下::

a. MergeSort (low, mid)

b. MergeSort(mid + 1, high)

4. 归并两个排序的子列表:通过一merge()方法实现.

a. 设置 i = low

b. 设置 j = mid + 1

c. 设置k = low

d. 重复直到 i > mid
或 j > high:
//  此循环将终止,前提是达到两个子列表的其中一个结束处。 

  i.如果 (arr[I] <= arr[J])

将arr[I]
存储到数组B中的索引k处

按1递增i

Else

将arr[j]
存储到数组B中的索引k处

按1递增j

ii. 按1递增k

e. 重复直到j > high:
//如果第二个中仍然有某些元素                                 
                                    //
追加到新列表的子列表

  i.
将arr[j] 存储到数组B中的索引k处

ii. 按1递增j

iii. 按1递增k

f. 重复直到i > mid: 
//如果在第一个子列表中仍然有一些元素

                                            //
将它们追加到新类别中

i. 将arr[i]
存储到数组B中的索引k处

ii.按1递增i

iii. 按1递增k

5. 将排序的数组B中的所有元素复制到原始数组arr中

若要排序此列表,您需要按递归方式将列表划分为两个几乎完全相等的子列表,直到每个子列表仅包含一个元素。

将列表划分为大小为1的子列表需要log n
次通行。

在每个通行中,最多执行n次比较。

因此,比较总数将是最多n
× log n次。

归并排序的效率等于O(n log n)。

归并列表的最佳、平均和最糟用例效率之间没有差异,因为所有这些效率均需要相同的时间量。

哪个算法使用以下步骤来排序给出的元素列表?

1.    选择名为枢轴的列表中的元素。

2. 将列表分为两个部分,以便一部分包含小于枢轴的元素,另一部分包含大于枢轴的元素。

3. 然后将枢轴放到两个列表之间的正确位置。

4. 使用相同的算法排序列表的两个部分。

答案:

快速排序

小结

在本章中,你已经学到:

快速排序和归并排序算法基于分治技巧。

若要通过使用快速排序算法来排序项目列表,您需要:

选择枢轴值。

将列表分为两个子列表,以便一个子列表包含了所有小于枢轴的项,另一个子列表包含了大于枢轴的所有项。

然后将枢轴放到两个子列表之间的正确位置。

通过使用快速排序来排序两个子列表。

快速排序算法采用的总时间取决于枢轴值的位置和最初的元素分阶。

快速排序算法的最差效率是O(n2)阶的。

快速排序算法的最佳效率是O(n log n)阶的。

若要通过使用归并排序来排序项目列表,您需要:

将列表分为两个子列表。

通过使用归并排序来排序每个子列表。

归并两个排序的子列表。

归并排序算法具有O(n log n)的效率。

/*
问题描述:编写在数组中存储10个数字的程序,并通过使用快速排序算法来排序。
*/
using System;
using System.Text;

class Merge_Sort
{
	private int[]arr=new int[20];	//定义数组,你输入数字,接受存储的数组
	private int[]dest=new int[20];	//在归并排序中用来存储已经排序的数组,就是咱说的新数组.
	private int cmp_count;	//比较总次数
	private int mov_count;	//移动总次数
	//数组元素个数
	public int n;
	//****************构造方法
	public Merge_Sort()
	{
		cmp_count=0;
		mov_count=0;
	}
	//用户输入数据方法
	void read()
	{
		while(true)
		{
			Console.WriteLine("请输入数组的元素个数:");
			string s=Console.ReadLine();
			n=Int32.Parse(s);
			if(n<=20)
				break;
			else
				Console.WriteLine("\n数组的最大元素个数为20.\n");
		}
		Console.WriteLine("\n---------------------------------");
		Console.WriteLine("-----------请输入数组元素---------");
		Console.WriteLine("---------------------------------");
		//获得数组元素
		for(int i=0;i<n;i++)
		{
			Console.Write("<"+(i+1)+">");
			string s=Console.ReadLine();
			arr[i]=Int32.Parse(s);
		}
	}
	//交换两个数组索引的方法
	void swap(int x,int y)
	{
		int temp;

		temp=arr[x];
		arr[x]=arr[y];
		arr[y]=temp;
	}
	/**************归并排序算法****************/
	public void m_sort(int low,int high)
	{
		if(low>=high)
			return;
		else
		{
			int mid=(low+high)/2;
			m_sort(low,mid);
			m_sort(mid+1,high);
			merge(low,mid,high);
		}
	}
	public void merge(int low,int mid,int high)
	{
			int i=low;
			int j=mid+1;
			int k=low;
			while((i<=mid)&&(j<=high))
			{
				if(arr[i]<=arr[j])
					{
						dest[k]=arr[i];
						k++;
						i++;
					}
				else
				{
					dest[k]=arr[j];
					k++;
					j++;
				}
			}
			while(j<=high)
			{
					dest[k]=arr[j];
					k++;
					j++;
			}
			while(i<=mid)
			{
				dest[k]=arr[i];
				k++;
				i++;

			}
			//Array.Copy(dest,arr,arr.Length);
			for(i=low;i<=high;i++)
			{
				arr[i]=dest[i];
			}
	}
	//显示方法
	void display()
	{
		Console.WriteLine("\n------------------------------------");
		Console.WriteLine("---------已经排序后的数组元素为------");
		Console.WriteLine("------------------------------------");	

		for(int j=0;j<=n;j++)
		{
			Console.Write(arr[j]+" ");
			//Console.Write(dest[j]+" ");
		}
		//Console.WriteLine("\n比较的总次数为:"+cmp_count);
		//Console.WriteLine("\n移动的总次数为:"+mov_count);
	}
	int getSize()
	{
		return (n);
	}
	public static void Main(string[]args)
	{
		Merge_Sort mySort=new Merge_Sort();
		mySort.read();
		mySort.m_sort(0,mySort.n-1);
		mySort.display();

		Console.WriteLine("\n\n按任意键退出.");
		Console.Read();
	}
}

时间: 2024-12-28 13:51:51

数据结构与算法之三 深入学习排序的相关文章

数据结构和算法17 之拓扑排序

本文为博主原创文章,转载请注明出处:http://blog.csdn.net/eson_15/article/details/51194219 这一节我们学习一个新的排序算法,准确的来说,应该叫"有向图的拓扑排序".所谓有向图,就是A->B,但是B不能到A.与无向图的区别是,它的边在邻接矩阵里只有一项(友情提示:如果对图这种数据结构部不太了解的话,可以先看一下这篇博文:数据结构和算法之 无向图.因为拓扑排序是基于图这种数据结构的). 有向图的邻接矩阵如下表所示: A B C A

数据结构与算法系列十(排序算法概述)

1.引子 1.1.为什么要学习数据结构与算法? 有人说,数据结构与算法,计算机网络,与操作系统都一样,脱离日常开发,除了面试这辈子可能都用不到呀! 有人说,我是做业务开发的,只要熟练API,熟练框架,熟练各种中间件,写的代码不也能“飞”起来吗? 于是问题来了:为什么还要学习数据结构与算法呢? #理由一: 面试的时候,千万不要被数据结构与算法拖了后腿 #理由二: 你真的愿意做一辈子CRUD Boy吗 #理由三: 不想写出开源框架,中间件的工程师,不是好厨子 1.2.如何系统化学习数据结构与算法?

数据结构与算法C++描述学习笔记1、辗转相除——欧几里得算法

前面学了一个星期的C++,以前阅读C++代码有些困难,现在好一些了.做了一些NOI的题目,这也是一个长期的目标中的一环.做到动态规划的相关题目时发现很多问题思考不通透,所以开始系统学习.学习的第一本是<数据结构与算法C++描述>第三版,边学边做一些笔记.所以这些笔记中的代码有很多将会非常简单,甚至可能只有一个记录或者结论. 辗转相除法用来求两个整数的最大公约数,即能同时整除两个数的最大整数.程序如下: int gdc(int m,int n){ int rem; while(n!=0){ //

数据结构与算法系列研究九——排序算法的一些探讨

四种排序 一.实验内容     输入20个整数,分别用希尔排序.快速排序.堆排序和归并排序实现由小到大排序并输出排序结果.二.关键数据结构与核心算法   关键数据结构:由于是排序为了简单起见,选用线性表中的数组作为存储结构.   核心算法:   1.希尔排序    希尔排序的核心还是直接插入法,但是插入的位置有所讲究.要把数组分为许多段,每一段的长度除了最后的有可能不同之外,其他的都相同.该段的长度即为增量,在最后一次必须为一,此时程序变成了直接插入.每次进行隔段插入,不断地调整是的数组变得隔段

python数据结构与算法第八天【排序算法】

1.排序算法的稳定性 稳定排序算法会让原本有相同键值的记录维持相对次序 例如:对以下元组按照元组的第一个元素升序排列,元组如下: (4,1) (3,1) (3,7) (5,6) 若要满足条件,则可能的排序有: 情况一: (3,1) (3,7) (4,1) (5,6) 情况二: (3,7) (3,1) (4,1) (5,6) 虽然情况一和情况二都是满足条件的,但是情况二在满足条件下打破了原本无需改变的顺序 原文地址:https://www.cnblogs.com/liuzhiqaingxyz/p/

Hark的数据结构与算法练习之图书馆排序

算法说明 图书馆排序是插入排序的变种,典型的以空间换时间的一种方法.我个人感觉这种思路可以学习借鉴,但直接使用的场景应该不大. 我们知道,真正的插入排序通常往前边插入元素后,我们要把后边所有的元素后移.而图书馆排序的思路就是将每个元素后边都预留N个空间(例如预留10个元素空间),这样往某个元素前插入时,在预留空间足够的前题下,只会移动少少几个的元素. 代码 因为4月要考试,所以代码暂不写,以后有时间时补上 参考 http://www.cnblogs.com/kkun/archive/2011/1

Hark的数据结构与算法练习之煎饼排序

算法说明 假设煎锅里边有N个煎饼摞在了一起,它们大小不一并且顺序不一致,我们需要通过拿铲子将它们不停的翻个,进行排序,最终得到一个底下是大的煎饼,上边是小的煎饼的序列.这个排序的过程就是煎饼排序. 这个算法有两种解,一种是普通解,一种是最优解. 普通论证: 例如你的初始煎饼顺序是[2,4,3,1] 然后2与4交换位置,然后4与1交换位置,得出[1,3,2,4]. 然后3与1交换位置,接着3与2交换位置,得出[2,1,3,4]. 最后2与1交换位置,得出结果[1,2,3,4] 通过普通解的过程,我

Hark的数据结构与算法练习之希尔排序

算法说明 希尔排序是插入排序的优化版. 插入排序的最坏时间复杂度是O(n2),但如果要排序的数组是一个几乎有序的数列,那么会降低有效的减低时间复杂度. 希尔排序的目的就是通过一个increment(增量)来对数列分组进行交换排序,最终使数列几乎有序,最后再执行插入排序,统计出结果. 通过increment=n/2, 也就是如果9个数的话,增量为4,2,1.   如果是20个数的话,增量就是10,5,2,1.  当increment为1时,其实对几乎有序的数列进行插入排序啦啦. 时间复杂度 O(n

Hark的数据结构与算法练习之桶排序

算法说明 桶排序的逻辑其实特别好理解,它是一种纯粹的分而治之的排序方法. 举个例子简单说一下大家就知道精髓了. 假如对11,4,2,13,22,24,20 进行排序. 那么,我们将4和2放在一起,将11,13放在一起,将22,24,20放在一起.  然后将这三部分分别排序(可以根据实现情况任意选择排序方式,我的代码中使用的是快排),将子数组排序后,再顺序输出就是最终排序结果了(大概应该明白了,我们是根据数字大小进行分组的,故而顺序输出即可) 怎么样,很简单吧. 具体实现大家看代码就行,我实现的其