快速排序(数组和链表)

来源:互联网 发布:知之阅读 pdf 编辑:程序博客网 时间:2024/06/04 01:05

本文介绍的是数组和单链表的快速排序。

首先介绍一下快速排序:

快速排序的思想是基于分治的。在待排序表L[ 1,2...N ] 中任取一个元素作为基准 pivot ,通过一趟排序将待排序表划分为独立的两个部分 L[ 1,2...K-1 ] 和 L[ K+1...N ],

使得 L[ 1,2...K-1 ]  中所有元素的值都小于 pivot ,L[ K+1...N ] 中的所有元素都大于等于 pivot 的值,则 pivot 放在中间的 L[K] 的位置上,这个过程完成了一次快速排序。

然后分别对两个字表进行递归 ,重复上面两个动作,直到每个部分都只有一个元素或者为空为止,这就会使每个元素都放在了最终的位置。

效率分析:

空间:因为是递归完成的,所以需要借助一个递归栈来完成。当已经有序时,会进行 N-1 次递归,此时的递归层次最多,栈的深度为O(N)。但平均情况下,还是比较好的,

为O(LogN)。

时间:运行时间与划分是否对称有关系,所以中枢值得选择就是比较重要的了。可以参照STL中对于中枢值得选取。一般情况下,时间复杂度是O(NLogN)。

以下给出对于 数组 的快速排序算法:

 首先,声明了一个容器 Vector:

//  以下是对容器的声明vector<int> v{10,4,9,12,7,6,18,1,25};

容器声明完成以后,就可以对其进行快速排序:

void QuickSort( vector<int> &v, int low, int high ){    //  满足递归的条件    if ( low < high )    {        //  这里是对容器的划分的方法        int key = Partition( v,low,high );        //  依次对其左右两个区间进行快速排序操作        QuickSort( v, low, key );        QuickSort( v, key+1, high);    }}


下面给出划分的方法:

int Partition( vector<int> &v, int low, int high ){    //  获取中枢值    int key = v[low];    //  划分的主程序    while( low < high )    {        while( v[high] > key && high > low )            high--;        v[low] = v[high];        while( v[low] < key && low < high)            low++;        v[high] = v[low];    }    v[low] = key;    return low;}

对以上声明的容器调用快速排序和排序后的结果输出:

// 调用快速排序QuickSort( v,0,v.size()-1 );// 输出,通过调用仿函数实现for_each( v.begin(),v.end(), print<span style="font-family: Arial, Helvetica, sans-serif;">() );</span>
以下给出仿函数的定义:

具体仿函数的使用,参照其他博客

class print{public:    void operator()( const int i )    {        cout << i << " ";    }};
以上就是对数组的快速排序。

下面给出相对于链表的快速排序的算法:

先给出链表节点的定义:

struct Link{    int value;    struct Link *next;    Link():value(0),next(nullptr){}    Link(int x):value(x),next(nullptr){}};typedef struct Link node;

以下给出快速排序的思想,具体解释见注释:

//  注意这里形参的声明方法,一定要加上 & 符号//  仔细想想为什么void QuickSort( node* &head , node* &end ){    // 声明四个节点,方便保存分开后的左右两个链表    node *head1,*end1,*head2,*end2;    head1 = end1 = head2 = end2 = nullptr;    if ( head == nullptr )        return;    node *p,*pre1,*pre2;    p = pre1 = pre2 = nullptr;    // 取出一个节点作为中枢点    int key = head->value;    // 将头节点孤立出来    p = head->next;    head->next = nullptr;    while( p != nullptr )    {        // 左        if( p->value < key )        {            // 头结点为空的情形            if ( head1 == nullptr )            {                head1 = p;                pre1 = p;            }            else  // 头结点非空的情形            {                pre1->next = p;                pre1 = p;            }            p = p->next;            pre1->next = nullptr;        }        else        {            if ( head2 == nullptr )            {                head2 = p;                pre2 = p;            }            else            {                pre2->next = p;                pre2 = p;            }            p = p->next ;            pre2->next = nullptr;        }    }    // 给出尾节点    end1 = pre1;    end2 = pre2;    // 分别对左右两个区间进行快速排序    QuickSort(head1,end1);    QuickSort(head2,end2);    // 排序之后,链表的融合    if ( head1 != nullptr && head2 != nullptr)    {        end1->next = head;        head->next = head2;        head = head1;        end = end2;    }    else if ( head1 != nullptr )    {        end1->next = head;        end = head;        head = head1;    }    else if ( head2 != nullptr )    {        head->next = head2;        end = end2;    }}


以上是对快速排序基于数组和链表的所有内容。







1 0