Go语言展现快速排序算法全过程的思路及代码示例

 更新时间:2016年04月13日 10:55:53   作者:荆榆  
这篇文章主要介绍了Go语言展现快速排序算法全过程的思路及代码示例,文章最后作者还提到了对Quick Sort算法优化的一些想法,需要的朋友可以参考下

快速排序算法
快速排序是一个递归的思想,首先选择一个数作为基数,把数组中小于它的数放在它的左边,把大于它的数放在它的右边,然后对左右两边的数递归进行排序。

算法的关键部分是实现数组的划分,即怎么把数组的元素划分成两部分,使得左边的数比基数小,右边的数比基数大。划分有许多不同的实现方法,这里主要使用单向扫描的方法,后面再稍微介绍双向扫描的方法。

选择最右边的数字作为基数。使用一个变量j记录当前左边数字(比基数小的数)的最右的下标值。然后使用变量i从左到右遍历数组,如果a[i]比基数小,说明a[i]属于左边的数,就把j自增,然后交换a[j]和当前的a[i]。因为自增前的j是左边数字最右的下标,自增后的a[j]肯定不属于左边了,把其跟a[i]交换后,新的a[j]是属于左边的,而且此时j也重新变为左边数字最右的下标了。

扫描结束后,把j自增(因为a[j]将会被交换到最右边,因此要选属于右边的数字)后与最右边的基数交换,此时的j即为划分的结果。

Golang版的实现例子:

复制代码 代码如下:

package main
import "fmt"
 
type ElemType int;
 
func main() {
    data := make([]ElemType, 600000) // ALL ZERO
    var i int = 0;
    var dlen int = len(data);
    for i = 0 ; i < dlen ; i++{
        data[i] = (ElemType)(dlen - i -1);
    }
    fmt.Println("Start ...",len(data));
    for i = 0 ; i < 100 ; i++{
        fmt.Printf("%d ", data[i]);
    }
    fmt.Println();
    QuickSort(data,0,dlen-1);
    
    fmt.Println("End ...");
    for i = 0 ; i < 100 ; i++{
        fmt.Printf("%d ", data[i]);
    }
    fmt.Println();
}
 
func QuickSort(A []ElemType,low, high int){
    if low < high {
        // Partition() is the operation of divide A[low ... high]
        // one to two arrays which can be used as QuickSort Again
        pivotpos := Partition(A,low,high);
        QuickSort(A,low,pivotpos-1);
        QuickSort(A,pivotpos+1,high);
    }
}
 
func Partition(A []ElemType,low ,high int)  int {
    var pivot ElemType = A[low];
    var tmp ElemType;
    //Method I:
    //for low < high {
    //  for low < high && A[high] >= pivot { high-- ; }
    //  A[low] = A[high];
    //  for low < high && A[low] < pivot { low++; }
    //  A[high] = A[low];
    //}
    //end of MI
    
    //Method II:
    for (low < high) && (A[high] > pivot) { high --; }
    for (low < high) && (A[low] < pivot) {low++; }
    for low < high {
        // swap A[low] & A[high]
        tmp = A[low];
        A[low] = A[high];
        A[high] = tmp;
        low ++;
        high --;
    }
    //end of MII
 
    A[low] = pivot ;
    return low ;
}


执行输出如下:

[yu@argcandargv-com quicksort]$ go build quicksort.go 
[yu@argcandargv-com quicksort]$ ls

quicksort quicksort.go
[yu@argcandargv-com quicksort]$ time ./quicksort
Start ... 600000
599999 599998 599997 599996 599995 599994 599993 599992 599991 599990 599989 599988 599987 599986 599985 599984 599983 599982 599981 599980 599979 599978 599977 599976 599975 599974 599973 599972 599971 599970 599969 599968 599967 599966 599965 599964 599963 599962 599961 599960 599959 599958 599957 599956 599955 599954 599953 599952 599951 599950 599949 599948 599947 599946 599945 599944 599943 599942 599941 599940 599939 599938 599937 599936 599935 599934 599933 599932 599931 599930 599929 599928 599927 599926 599925 599924 599923 599922 599921 599920 599919 599918 599917 599916 599915 599914 599913 599912 599911 599910 599909 599908 599907 599906 599905 599904 599903 599902 599901 599900 
End ...
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 

 

real  1m55.564s
user  1m55.215s
sys 0m0.052s

PS:其实应用中有一个优化,因为快速排序在数组本来有序的情况下复杂度会退化为O(n^2)。为了避免这点,在选取基数的时候可以随机地进行选择。具体做法是把最右边的数字跟一个随机的数字交换位置。另外还有一种三数取中的方法,即选择首尾跟中间某个数共三个数的中值作为基数。

相关文章

  • 自己动手用Golang实现约瑟夫环算法的示例

    自己动手用Golang实现约瑟夫环算法的示例

    这篇文章主要介绍了自己动手用Golang实现约瑟夫环算法的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • go语言题解LeetCode1299将每个元素替换为右侧最大元素

    go语言题解LeetCode1299将每个元素替换为右侧最大元素

    这篇文章主要为大家介绍了go语言LeetCode刷题1299将每个元素替换为右侧最大元素示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Golang WaitGroup 底层原理及源码解析

    Golang WaitGroup 底层原理及源码解析

    WaitGroup 是 Golang 中最常见的并发控制技术之一,它的作用我们可以简单类比为其他语言中多线程并发控制中的 join(),这篇文章主要介绍了Golang WaitGroup 底层原理及源码详解,需要的朋友可以参考下
    2023-04-04
  • 深入了解Go语言中sync.Pool的使用

    深入了解Go语言中sync.Pool的使用

    本文将介绍 Go 语言中的 sync.Pool并发原语,包括sync.Pool的基本使用方法、使用注意事项等的内容,对我们了解Go语言有一定的帮助,需要的可以参考一下
    2023-04-04
  • 详解golang中发送http请求的几种常见情况

    详解golang中发送http请求的几种常见情况

    这篇文章主要介绍了详解golang中发送http请求的几种常见情况,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • golang如何实现抓取IP地址的蜘蛛程序详解

    golang如何实现抓取IP地址的蜘蛛程序详解

    这篇文章主要给大家介绍了关于利用golang如何实现抓取IP地址的蜘蛛程序的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-07-07
  • Golang开发中如何解决共享变量问题

    Golang开发中如何解决共享变量问题

    Go提供了传统通过共享变量,也就是共享内存的方式来实现并发。这篇文章会介绍 Go提供的相关机制,对Golang共享变量相关知识感兴趣的朋友一起看看吧
    2021-09-09
  • 手把手带你走进Go语言之语法基础解析

    手把手带你走进Go语言之语法基础解析

    这篇文章主要介绍了手把手带你走进Go语言之语法基础,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • 使用Go中的Web3库进行区块链开发的案例

    使用Go中的Web3库进行区块链开发的案例

    区块链作为一种分布式账本技术,在近年来取得了巨大的发展,而Golang作为一种高效、并发性强的编程语言,被广泛用于区块链开发中,本文将介绍如何使用Golang中的Web3库进行区块链开发,并提供一些实际案例,需要的朋友可以参考下
    2023-10-10
  • golang高并发的深入理解

    golang高并发的深入理解

    golang从语言级别上对并发提供了支持,而且在启动并发的方式上直接添加了语言级的关键字。下面这篇文章主要给大家介绍了关于golang高并发的相关资料,需要的朋友可以参考下
    2019-03-03

最新评论