相信算法对于许多开发人员来说都是一大难点,之所以难,就像设计模式一样,许多人在阅读之后,没有很好地理解,也不愿意动手上机操作,只停留在理论的学习上面,随着时间推移就慢慢淡忘。

有些东西,你可以发明创造,但是有些东西呢,你要么死记硬背,要么好好理解并动手进行练习来巩固。搞开发的话,死记硬背没用,好好理解火候还是差一点。最好的方式,还要在理解的基础上多敲敲代码,使自己即知其然,又知其所以然。

本篇只是简单介绍快速排序算法,大牛可以从旁帮忙指点,但是请嘴下留情哦:)

快速排序算法定义

快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。

它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

快速排序算法视频舞蹈

这里可以看看老外的一个非常棒的创意视频来认识快速排序的算法是怎么样的(http://v.youku.com/v_show/id_XMzMyODk4NTQ4.html),它以舞蹈的方式形象而生动地再现快速排序算法的方式。

快速排序算法讲解

假设现有一组整型数据需要你用快速排序的算法来进行排序(如int[] unsort = { , , , , , },假设以第一个数据3作为左右数据的分隔数)

那么运行完int midPosition = QuickSort(unsort, left, right);这一句的时候,得出的数组结果是:
{, , 3, , , },并且midPosition返回数据3的索引位置(即为索引2)。

这样之后,就可以根据3为分隔数(3的位置已经排好序),把数据分为{, },{ , , }两部分,然后通过递归的方式进行排序。

下面的代码我觉得很好理解,虽然在网上看到有很多可以改进的地方,但是这都不是本文的重点。本文只是入门的内容,能简单理解,尽量简单。毕竟要复杂些,我也写不出来。

唯一不好理解的地方,就是怎么去理解分隔数的位置。就我本人来说吧,以前在大学时也没学好,以至于后面来学习的时候,总会先入为主,觉得好难好难。人有抵触的心结在的话,做事情往往是事倍功半。

所以在我花大部分时间去理解好分隔数的位置之后,下面这种快速排序算法就能自己手动敲打出来了。理解了之后,再动手实践能巩固学习到的知识。

下面谈谈我对求分隔数位置的理解,不好的地方,欢迎大家讨论。

(1)预先定好一个分隔数,默认为第一个数(如我们讲到的实例3,我们假设是按照从小到大的顺序排序)

(2)按照先从右端和左端向中间的方式来进行排序(一趟排序只是排好分隔数的位置,并且分隔数左部分的数据都比右部分的数据要小)。

右端先开始排序,如果右端的数据比分隔数要大时,则位置不用改变。一旦出现右端的数据比分隔数要小时,则需要把右端的这个小数据挪到左边去,具体看下面步骤说明。

并且排序方向改为从左端开始,如果左端的数据比分隔数要小时,则位置不用改变。一旦出现左端的数据比分隔数要大时,则需要把左端的这个大数挪到右边去。

并且排序方向又改为从刚才已到达的右边位置再进行排序。

其实说白了,就是开始时,我们从左边拿出了一个数存给一个变量(分隔数),相当于左边留出了一个空位,让分隔数右边的数(这个数小于分隔数)来存放,一旦存放了,则右边就空出一个空位,等待分隔数左边的数(这个数比分隔数要大)来存放,反正就这么一直调来调去,调到没得调了,剩下的空位就是分隔数的位置。

步骤:{ , , , , , }

第一小步:把3赋值给一个存储的变量,假设是 int splitNum = 3 (而数组3的这个位置到时将会给比3小的数占用)。我们可以理解为数组3这个数暂时是一个空位

即:{ X, , , , , },X代表空位

第二小步:拿splitNum跟右端的5来进行比较(跟右端比较的目的是什么,当然是想把比3大的数保留在3的右边,比3小的数放在3的左边),5大,所以5右边不变

即:{ X, , , , , }

第三小步:拿splitNum跟右端的7来进行比较,7大,所以7右边不变

即:{ X, , , , , }

第四小步:拿splitNum跟右端的1来进行比较,splitNum大,所以X赋值为1(那么原先数组1的索引位置就是一个空位)

即:{ , , , X, , }

第五小步:拿splitNum跟左端的1来进行比较,(跟左端比较的目的是什么,当然是想把比3大的数放到3的右边,比3小的数保留在3的左边),splitNum大,所以1不变

即:{ , , , X, , }

第六小步:拿splitNum跟左端的2来进行比较,splitNum大,所以2不变

即:{ , , , X, , }

第七小步:拿splitNum跟左端的4来进行比较,4大,所以X赋值为4,(那么原先数组4的索引位置就空出来了)

即:{  , , X, , , }

第八小步:由于两天都比较完了,那X赋值为splitNum的值

即:{  , , , , , }

从而实现以3为分隔数,3左边的数都比3右边的数要小(按照从小到大的顺序排序)

快速排序算法代码
namespace Sort
{
class Program
{
static void Main(string[] args)
{
string result = string.Empty;
int[] unsort = { , , , , , }; result = GetPrint(unsort);
Console.Write("排序前结果: ");
Console.WriteLine(result); //快速排序
QuickSort(unsort, , unsort.Length - ); result = GetPrint(unsort);
Console.Write("排序后结果: ");
Console.WriteLine(result); Console.ReadLine();
} /// <summary>
/// 调用快速排序算法
/// </summary>
/// <param name="unsort">待排序的整形数组</param>
/// <param name="left">左边起始点</param>
/// <param name="right">右边结束点</param>
public static void QuickSort(int[] unsort, int left, int right)
{
if (left < right)
{
//获取一次排序的中间索引位置
int midPosition = GetSplitNum(unsort, left, right); //递归实现
QuickSort(unsort, left, midPosition - );
QuickSort(unsort, midPosition + , right);
}
} /// <summary>
/// 获取一次排序的中间索引位置
/// </summary>
/// <param name="unsort">待排序的整形数组</param>
/// <param name="left">左边起始点</param>
/// <param name="right">右边结束点</param>
public static int GetSplitNum(int[] unsort, int left, int right)
{
int splitNum = unsort[left];
while (left < right)
{
/**
* 从右端开始比较
* (1)假如从右端过来的数比分隔数要大,则不用处理
* (2)假如从右端过来的数比分隔数要小,则需要挪到分隔线左边
* */
while (left < right && splitNum <= unsort[right])
{
right--;
}
unsort[left] = unsort[right]; /**
* 从从端开始比较
* (1)假如从左端过来的数比分隔数要小,则不用处理
* (2)假如从左端过来的数比分隔数要大,则需要挪到分隔线右边
* */
while (left < right && splitNum >= unsort[left])
{
left++;
}
unsort[right] = unsort[left];
}
//一趟比较之后,分隔数的位置就可以确认起来
unsort[left] = splitNum; return left;
} /// <summary>
/// 打印输出结果
/// </summary>
/// <param name="unsort">数据</param>
public static string GetPrint(int[] unsort)
{
string result = string.Empty;
foreach (int n in unsort)
{
if (!string.IsNullOrEmpty(result))
{
result += string.Format("->{0}", n);
}
else
{
result = string.Format("{0}", n);
}
}
return result;
}
}
}

C#快速排序算法基础入门篇的更多相关文章

  1. SQLAlchemy 教程 —— 基础入门篇

    SQLAlchemy 教程 -- 基础入门篇 一.课程简介 1.1 实验内容 本课程带领大家使用 SQLAlchemy 连接 MySQL 数据库,创建一个博客应用所需要的数据表,并介绍了使用 SQLA ...

  2. Linux及Arm-Linux程序开发笔记(零基础入门篇)

    Linux及Arm-Linux程序开发笔记(零基础入门篇)  作者:一点一滴的Beer http://beer.cnblogs.com/ 本文地址:http://www.cnblogs.com/bee ...

  3. FPGA基础入门篇(四) 边沿检测电路

    FPGA基础入门篇(四)--边沿检测电路 一.边沿检测 边沿检测,就是检测输入信号,或者FPGA内部逻辑信号的跳变,即上升沿或者下降沿的检测.在检测到所需要的边沿后产生一个高电平的脉冲.这在FPGA电 ...

  4. 【Linux开发】Linux及Arm-Linux程序开发笔记(零基础入门篇)

    Linux及Arm-Linux程序开发笔记(零基础入门篇) 作者:一点一滴的Beer http://beer.cnblogs.com/ 本文地址:http://www.cnblogs.com/beer ...

  5. JS基础入门篇(三十五)—面向对象(二)

    如果没有面向对象这种抽象概念的小伙伴,建议先看一下我写的JS基础入门篇(三十四)-面向对象(一)

  6. 云小课|DGC数据开发之基础入门篇

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要:欢迎来到DGC数据 ...

  7. .NET ORM 的 “SOD蜜”--零基础入门篇

    PDF.NET SOD框架不仅仅是一个ORM,但是它的ORM功能是独具特色的,我在博客中已经多次介绍,但都是原理性的,可能不少初学的朋友还是觉得复杂,其实,SOD的ORM是很简单的.下面我们就采用流行 ...

  8. Elasticsearch 7.x 之文档、索引和 REST API 【基础入门篇】

    前几天写过一篇<Elasticsearch 7.x 最详细安装及配置>,今天继续最新版基础入门内容.这一篇简单总结了 Elasticsearch 7.x 之文档.索引和 REST API. ...

  9. 1-ESP8266 SDK开发基础入门篇--开发环境搭建

    因为今天终于做好了自己的另一块工控板,所以我就开始写基础公开篇的内容,希望自己小小的努力能够帮到大家 自己做的另一块板子 https://www.cnblogs.com/yangfengwu/cate ...

随机推荐

  1. XML DOM 循环(foreach)读取PHP数据 和 PHP 编写 XML DOM 【转载】

    用 PHP 读取和编写可扩展标记语言(XML)看起来可能有点恐怖.实际上,XML 和它的所有相关技术可能是恐怖的,但是用 PHP 读取和编写 XML 不一定是项恐怖的任务.首先,需要学习一点关于 XM ...

  2. rac安装oem

    [oracle@node1 ~]$ emca -config dbcontrol db -repos recreate -cluster STARTED EMCA at May 31, 2016 3: ...

  3. Objective-C设计模式——原型Prototype(对象创建)

    1.原型 原型设计模式所谓原型设计模式,其实就是对象复制,这个特性在所有语言基本上都是存在的. 我们知道在OC中,对象赋值其实是对对象的引用复制,其实就是相当于C语言中的指针.创建了一个新的变量,但是 ...

  4. iOS-Andriod百度地图仿百度外卖-饿了么-选择我的地址-POI检索/

    http://zanderzhang.gitcafe.io/2015/09/19/iOS-Andriod百度地图仿百度外卖-饿了么-选择我的地址-POI检索/ 百度外卖选择送货地址: 饿了么选择送货地 ...

  5. C# 中 datagridview 绑定BindingList类型和更新

    C# 中的datagridview是一个非常有用且强大的控件,可以用来绑定数据库.绑定LIST类型的变量等等. 这里我们说一说绑定List类型并实时更新datagridview的情况.实时更新,指的是 ...

  6. 理解C#系列 / 核心C# / 名称空间

    名称空间namespace 名称空间 名称空间用来逻辑分类,而不是物理上的,名称空间与程序集无关[程序集:经由编译器编译得到的文件],同一个程序集中可以有2不同的名称空间,也可以在不同的程序集中定义同 ...

  7. UI1_Calayer

    // // ViewController.m // UI1_Calayer // // Created by zhangxueming on 15/7/2. // Copyright (c) 2015 ...

  8. python基础:自定义函数

    一.背景 在学习函数之前,一直遵循:面向过程编程,即:根据业务逻辑从上到下实现功能,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,也就是将之前实现的代码块复制到现需功能处,如下 ...

  9. HyperMesh生成Flac3D的剖分网格

    本帖的目的是探索煤矿沉积岩层采煤过程中的力学分析模拟的前处理方法,计算软件采用公认的Flac3D差分方法. 目前,Flac3D官方提供的剖分网格的生成方法有三种.一是直接使用命令和Fish语句生成,这 ...

  10. go开发环境配置