6

快速排序 C实现

 1 year ago
source link: http://bean-li.github.io/quicksort/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

快速排序 C实现

首页 分类 标签 留言 关于 订阅 2023-06-05

|

分类 算法 

|

标签 算法 

最近在复习数据结构,参考的是《算法:C语言实现》。 本文实现了quicksort,对于某些特殊序列,quicksort恶化的情况,采用了三者取中的方式,防止快排性能恶化。

对于选择整个输入中第K小的元素,可以不必完成整个排序之后,再来取对应位置的值,可以参考快排的思路,快速获得整个序列中第Kth的元素。同时实现了递归和非递归的版本。

#ifndef _SORT_BASE_H_
#define _SORT_BASE_H_

typedef int Item ;

#define Key(A) (A)
#define less(A,B) (Key(A) < Key(B))
#define exch(A,B) { Item tmp = A; A=B ; B=tmp;}
#define compexch(A, B) if(less(B, A)) exch(A,B)


#endif
#ifndef _QUICKSORT_H_
#define _QUICKSORT_H_

#include "sort_base.h"
#include "insertsort.h"

#define CUTOFF (8)

int partition(Item a[], int l, int r)
{
    int i = l-1;
    int j = r ;
    Item v = a[r];
    for(;;)
    {
        while(less(a[++i],v));
        while(less(v, a[--j]))
        {
            if(j == l)
                break;
        }
        if(i >=j)
            break;
        exch(a[i], a[j]);
    }
    exch(a[i], a[r]);
    return i ;
}

void _quicksort(Item a[], int l, int r)
{
    if(r - l <=CUTOFF)
        return ;

    /* find the middle element of (a[l], a[mid] , a[r])*/
    exch(a[(l+r)/2], a[r-1]);

    compexch(a[l], a[r-1]);
    compexch(a[l], a[r]);
    compexch(a[r-1], a[r]);

    /* a[r-1] is a[mid]
     * a[l] < a[r-1]
     * a[r-1] < a[r]
     * a[l] and a[r] no need to appear in partition function
     */
    int i = partition(a, l+1, r -1);
    _quicksort(a, l , i-1);
    _quicksort(a, i+1 , r);

}


void quicksort(Item a[], int l , int r)
{
    _quicksort(a, l , r);
    insertsort(a, l , r);
}


/* recursive version of find kth element*/
Item find_kth_element(Item a[], int l, int r, int k)
{
    int pivot = partition(a, l , r);
    if (pivot == k)
        return a[pivot];

    if (pivot > k)
        return find_kth_element(a, l, pivot-1, k);
    else
        return find_kth_element(a, pivot+1, r, k);

}

/* non-recursive version of find kth element*/
Item find_kth_element_n(Item a[], int l, int r, int k)
{
    while(l < r)
    {
        int pivot = partition(a, l , r);
        if (pivot == k)
            return a[pivot];
        if (pivot > k)
            r  = pivot - 1;
        else
            l =  pivot + 1 ;
    }
    
    return a[l];
}

#endif

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <vector>
#include "shellsort.h"
#include "quicksort.h"


std::vector<uint32_t> generate_test_vec(size_t n) {
    auto test_vec = std::vector<uint32_t> {};
    while (test_vec.size() < n) {
        test_vec.push_back((uint32_t) std::rand() %100000);
    }
    return test_vec;
}

int cmp_int(const void* a, const void *b)
{
    return ( *(int*)a - *(int*)b );
}

int main() {
    for (int round = 0; round < 3; round++) {
        std::printf("round %d:\n", round);

        auto test_vec1 = generate_test_vec(2000000);
        auto test_vec2 = test_vec1;
        auto test_vec3 = test_vec1;
        auto test_vec4 = test_vec1;

        auto start_time1 = std::clock();
        //std::sort(test_vec1.begin(), test_vec1.end());
        qsort(test_vec1.data(), test_vec1.size(), 4, cmp_int);
        std::printf("qsort(glibc) time: %.3lf sec\n", (std::clock() - start_time1) * 1.0 / CLOCKS_PER_SEC);

        auto start_time2 = std::clock();
        shellsort_2((Item*)test_vec2.data(), 0, test_vec2.size()-1);
        std::printf("shellsort time: %.3lf sec\n", (std::clock() - start_time2) * 1.0 / CLOCKS_PER_SEC);

        auto start_time3 = std::clock();
        quicksort((Item*)test_vec3.data(), 0, test_vec3.size()-1);
        std::printf("quicksort time: %.3lf sec\n", (std::clock() - start_time3) * 1.0 / CLOCKS_PER_SEC);

        auto start_time4 = std::clock();
        std::sort(test_vec4.begin(), test_vec4.end());
        std::printf("std::sort time: %.3lf sec\n", (std::clock() - start_time4) * 1.0 / CLOCKS_PER_SEC);

        assert(test_vec1 == test_vec2);
        assert(test_vec1 == test_vec3);
        assert(test_vec1 == test_vec4);

    }
}


ROG-Manjaro C/sort » ./test
round 0:
qsort(glibc) time: 0.556 sec
shellsort time: 0.898 sec
quicksort time: 0.454 sec
std::sort time: 0.989 sec
round 1:
qsort(glibc) time: 0.555 sec
shellsort time: 0.800 sec
quicksort time: 0.393 sec
std::sort time: 1.064 sec
round 2:
qsort(glibc) time: 0.507 sec
shellsort time: 0.900 sec
quicksort time: 0.498 sec
std::sort time: 1.145 sec


Recommend

  • 96

    数据结构与算法—快速排序(Java实现)

  • 137

    面试官系列(番外): 别再使用阮一峰版的快速排序了 往期 面试官系列(1): 如何实现深克隆 面试官系列(2): Event Bus的实现 面试官系列(3): 前端路由的实现 面试官系列(4): 实现双向绑定Proxy比defineproperty优劣如何

  • 35
    • colobu.com 6 years ago
    • Cache

    使用 Go 实现快速排序

    快速排序(quick sort)号称是二十世纪最伟大的十大算法之一( The Best of the 20th Century: Editors Name Top 10 Algorithms ), 但是快速排序也是最不容易实现的排...

  • 25
    • shockerli.net 5 years ago
    • Cache

    PHP 算法 —— 快速排序

    算法原理 下列动图来自 @五分钟学算法 ,演示了快速排序算法的原理和步骤。 步骤: 从数组中选...

  • 36
    • www.tuicool.com 5 years ago
    • Cache

    快速排序及golang实现

    快速排序 快速排序思路 快速排序通过分支法的思想,从一个数组中选取一个基准元素pivot,把这个数组中小于pivot的移动到左边,把大于pivot的移动到右边。然后再分别对左右两边数组进行快速排序。 双边循环法

  • 36
    • www.tuicool.com 4 years ago
    • Cache

    快速排序

    快速排序 快速排序效率高,空间复杂度底,在工作中一般是用的最多的排序算法,所以需要掌握。 在看快速排序之前,先看一下另一个比快排简单点的问题,就是荷兰国旗问题 给定一个数组arr,和一个数num,请把小于n...

  • 17
    • 微信 mp.weixin.qq.com 4 years ago
    • Cache

    你真的懂快速排序?

    学习不实战 就等于白看 学而后忘 忘而再学 这是个怪圈 思索良久 在一个充满雾霾的下午 本号决定推出 【决战西二旗】系列文章 这个专题名有点土 不文雅 不响亮...

  • 1
    • panda843.github.io 2 years ago
    • Cache

    PHP之快速排序的实现

    PHP之快速排序的实现 发表于 2017-12-28 | 分类于 开发 | | 浏览4 次 | 字数统计: 382 | 阅读时长 ≈ 1快速排序(Quicksort)是对冒泡排序的一种改进。快速排序由C. A....

  • 4

    快速排序(Quicksort)的Javascript实现 浏览:9765次  出处信息     日本程序员norahiko,写了一个...

  • 7

    快速排序算法Java、Python、Go和Rust四种代码实现 快速排序...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK