常用排序算法之快速排序c及lua实现

本文详细介绍了快速排序算法,这是一种采用分治法的排序策略。首先选取基准元素,然后将数组分为两部分,小于基准的元素在前,大于基准的在后。通过递归方式对这两部分继续进行排序,最终实现整个序列的有序。文中提供了C语言和Lua语言的实现代码,展示了快速排序的具体步骤,并分析了其平均时间复杂度为O(n log n)。
摘要由CSDN通过智能技术生成

快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。

步骤为:

  1. 从数列中挑出一个元素,称为 "基准"(pivot),
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

在简单的伪代码中,此算法可以被表示为:

 procedure quicksort(a, left, right)
     if right > left
         select a pivot value a[pivotIndex]
         pivotNewIndex := partition(a, left, right, pivotIndex)
         quicksort(a, left, pivotNewIndex-1)
         quicksort(a, pivotNewIndex+1, right)

对于待排序的输入顺序之所有排列情形的平均比较次数,可以借由解出以下递归关系式可以精确地算出来。

C(n) = n - 1 + \frac{1}{n} \sum_{i=0}^{n-1} (C(i)+C(n-i-1)) = 2n \ln n = 1.39n \log_2 n.

在这里,n-1 是分区所使用的比较次数。因为基准值是相当均匀地落在排列好的数列次序之任何地方,总和就是所有可能分区的平均。故,快速排序的平均时间复杂度为

C版本算法实现:

#include "stdio.h"

int partition(int data[], int left, int right)
{
#if 0
//双向扫描-这种做法当有相同数据时,会有死循环的情况(不建议使用)
    int key = data[left];
    int i = left+1;
    int j = right;

    while(i <= j)
    {
        //gcc编译器可能不支持这种写法,编译不会报错,但是运行会有问题
        //while(data[i++] < key);
        //while(data[j--] > key);
        while(data[i] < key) ++i;
        while(data[j] > key) --j;

        if(i < j)
        {
            int temp = data[i];
            data[i] = data[j];
            data[j] = temp;
        }
    }

    data[left] = data[j];
    data[j] = key;

    return j;
#endif
#if 0
//单向扫描
    int key = data[left];

    int temp = data[left];
    data[left] = data[right];
    data[right] = temp;

    int i = left, j = left;
    while(i < right)
    {
        if(data[i] <= key)
        {
            int _temp = data[i];
            data[i] = data[j];
            data[j] = _temp;
            ++j;
        }
        ++i;
    }

    int __temp = data[right];
    data[right] = data[j];
    data[j] = __temp;

    return j;
#endif
#if 1
//双向扫描(有相同元素不影响排序)
    int key = data[left];
    int i = left;
    int j = right;

    while(i < j)
    {
        while(i < j && data[j] >= key) --j;
        if(i < j)
            data[i++] = data[j];

        while(i < j && data[i] <= key) ++i;
        if(i < j)
            data[j--] = data[i];
    }

    data[i] = key;
    return i;
#endif
}

void quick_sort(int data[], int low, int high)
{
    if(low < high)
    {
        int index = partition(data, low, high);
        quick_sort(data, low, index-1);
        quick_sort(data, index+1, high);
    }
}

void print_data(int data[], int len)
{
    int i = 0;
    for(i = 0; i < len; ++i)
    {
        printf("%d ", data[i]);
    }
    printf("\n");
}

void main()
{
    int data[] = {3,6,2,1,7,4,8,5};
    int size = sizeof(data)/sizeof(int);

    printf("before quick sort:\n");
    print_data(data, size);
#if 1
    printf("after quick sort:\n");
    quick_sort(data, 0, size-1);
    print_data(data, size);
#endif
}

lua版本算法实现:

local t = {5,1,3,6,3,4,2,3}
function partition(t, left, right)
------------
--  单向扫描
    local key = t[left] 
    local index = left
    t[index],t[right] = t[right],t[index] 
    local i = left
    while i < right do
        if key >= t[i] then
            t[index],t[i] = t[i],t[index]
            index = index + 1
        end
        i = i + 1
    end
    t[right],t[index] = t[index],t[right] 
    return index;
------------
--
-- 双向扫描
    local key = t[left]
    local i = left
    local j = right
    while i < j do
        while i < j and t[j] >= key do
            j = j - 1
        end
        if i < j then
            t[i] = t[j]
            i = i + 1
        end

        while i < j and t[i] <= key do
            i = i + 1
        end
        if i < j then
            t[j] = t[i]
            j = j - 1
        end
    end

    --最后i,j相等
    t[i] = key
    return i
end

function quick_sort(t, low, high)
    if low < high then
        local index = partition(t, low, high)
        quick_sort(t, low, index-1)
        quick_sort(t, index+1, high)
    end
end

print("---before quick sort---")
print(table.concat(t,' '))
print("---after quick sort---")
quick_sort(t, 1, #t)
print(table.concat(t,' '))


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值