c++实现对结构体的快速排序

浅谈sort排序

在写这篇文章之前我对于结构体排序都是用STL的std::sort()
现假设有

typedef struct STreeNode* pSTreeNode;
struct STreeNode
{
    int nodeid;
    int namevalue;
    vector<pSTreeNode> pChildList;
}; 

对于pChildList的排序,加上头文件#include,就可以用
std::sort(pChildList.begin(), pChildList.end, cmp);其中cmp是自己定义的内部排序规则。可能很多人跟我一样这样使用,STL提供的sort算法类似快速排序,算法时间复杂度是n*log2(n)
但是在实际的项目中,有经验的人都知道不可以轻易地使用STL里面的算法,虽然方便,但是在头文件里面你引进#include,对于项目编译来说是加了一层压力,特别是大的项目,如果你不注意使用标准库,可能对于某个模块来说没有什么,但是你加一个,他加一个。。。对整个项目的编译无疑是沉重的打击,所以能自己实现的算法何不自己写接口

快速排序的介绍

时间复杂度:

快速排序的平均时间复杂度是nlogn,最坏情况是N方(基本有序,后面我会给大家证明),平均时间复杂度的证明较为繁琐,数学公式啦,感兴趣的可以百度学习一下

核心思想

随机找出一个数(通常就拿数组第一个数据就行),把它插入一个位置,使得它左边的数都比它小,它右边的数据都比它大,这样就将一个数组分成了两个子数组,然后再按照同样的方法把子数组再分成更小的子数组,直到不能分解为止。它也是分治思想的一个经典实验(归并排序也是) 。快速排序将数组排序的方式是当两个子数组都有序时整个数组也就自然有序了

举例说明

假设现在有 6 1 2 7 9 3 4 5 10 8 这十个数,我们对这个十个数进行从小到大排序

方法:

找一个基准数不要被这个名次吓到了,它就是一个可以用来参照的数,我们就用第一个数6作为参照吧,接下来,需要将这个序列中所有比基准数大的数放在6的右边,比基准数小的数放在6的左边。

友情提示。回忆一下冒泡排序,是如何通过“交换”,一步步让每个数归位的。此时可以通过“交换”的方法来达到目的。具体是如何一步步交换呢?怎样交换才既方便又节省时间呢?在纸上画画看。以前第一次学习冒泡排序算法的时(N方)候,觉得冒泡排序很浪费时间,每次都只能对相邻的两个数进行比较,这显然太不合理了。于是我就想能不能。。。,后来才知道原来这就是“快速排序”。

步骤

1>分别从 序列6 1 2 7 9 3 4 5 10 8的两端开始试探,假设left = 0, right = n-1 先从右往左找一个小于6的数,把这个数放到低位,再从左往右找一个大于6的数,然后把这个数放到刚刚那个小于6的数的位置。

我们来模拟一下 从右往左找一个小于6的数,8 不是, 10不是, 5哦对了,记住他的下标,然后把5放到最低位,从左往右找一个大于6的数1 不是, 2不是, 7哦对了,然后把7放到刚刚5的位置
序列变成了 5 1 2 7 9 3 4 5 10 8(想想为什么), 比如 3 2 1这个序列 3 跟 2换, 3再跟1换。1再跟2换 何不 3直接跟1换(以2为参照的话)?

2>沿着刚刚的思想会继续换,这样序列变成了 5 1 2 4 9 3 9 7 10 8(这里为什么总是有两个数是相同的呢,想想这样会不会有什么影响,其实没有,因为每一轮下去两个游走的下标会相遇,即两个相同的数字相临,那么前者会是分界线,也就是基准数的位置 即会变成 5 1 2 4 3 9 9 7 10 8 )

3>下一次从右到左发现了他的前面就是left,然后把基准数移到left位置,至此第一轮交换完毕

4>这样的话 整个序列变成了 三个序列 分别是 5 1 2 4 3 和 6 和 9 7 10 8

然后对5 1 2 4 3 和 9 7 10 8重复上诉1 > 2> 3> 4>步骤

最后会得到 1 2 3 4 5 6 7 8 9 10

细心的朋友可能会发现如果每次能把这个序列均分,n个数 最终分成N/2组,最后再对每组的两个数排序,这样是最优的情况10000个数 一次分成2个5000
1+2次分成 四个 2500,1+2+3次分成8个1250,,那么最终需要1+..x 想想x是不是logn复杂度 就是 nlogn/2,,,
那么最糟糕的情况呢,基本有序的时候,10000个数分成9999 1 然后 9998 1 1以此类推,,然后每次移动都需要n-1次 这种情况是最糟糕的,所以快排是不稳定的排序算法。(每种排序算法都有缺点,局限性)

下面给出结构体的快速排序算法的代码实现,

假设有结构体

typedef struct STreeNode* pSTreeNode;
struct STreeNode
{
    int nodeid;
    int namevalue;
    vector<pSTreeNode> pChildList;
}; 

上诉实现

int 
CTree::Partition(vector<pSTreeNode>&nodeids, int left, int right)
{     
    pSTreeNode Righttmp = nodeids[left];//基准数
    while (left < right) {
        while(left < right && nodeids[right]->namevalue >= Righttmp->namevalue) {
            right--;
        }  
        nodeids[left] = nodeids[right];

        while(left < right && nodeids[left]->namevalue <= Righttmp->namevalue) {
            left++;
        }  
        nodeids[right] = nodeids[left];
    }
    nodeids[left] = Righttmp;
    return left;
}

void 
CTree::quickSort(vector<pSTreeNode>&nodeids, int left, int right)
{
    if (left < right)
    {
        int q = Partition(nodeids, left, right);
        quickSort(nodeids, left, q - 1);
        quickSort(nodeids, q + 1, right);
    }
}

猜你喜欢

转载自blog.csdn.net/breakpoints_/article/details/80113761
今日推荐