Chinaunix首页 | 论坛 | 博客
  • 博客访问: 407111
  • 博文数量: 128
  • 博客积分: 2247
  • 博客等级: 大尉
  • 技术积分: 767
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-17 09:30
文章分类

全部博文(128)

文章存档

2011年(4)

2010年(124)

我的朋友

分类:

2010-06-28 11:30:45

前天参加一个讨论班,报告者在讲 Quick Sort 时,精力全集中在分割算法上了。他说:“你们一定要多体会一下,这个算法是先跟这边比,再跟那边比,又跟这边比,再跟那边比,如是直到相会。不这样的话, 将无法理解 Quick Sort.

对这个说法我很不同意。当然线性时间的分割算法是 Quick Sort 最出彩,最有技巧的地方,但 Quick Sort 的 big idea 并不在这里。从大方向上看,Quick Sort 都干了什么?

    * 找一个枢纽元 p ,把数组分成两部分,左边的比 p 小,右边的比 p 大。
    * 找一个元素 r, 把数组分成两部分,比 r 小的作为子树接在 r 的左边,比 r 大的最为子树接在树的右边。

不难看出,Quick Sort 其实在建一棵二叉排序树,这是它跟其它排序算法最不同的地方。其它几种常见的排序算法都专注于如何排出一个按序的线性序列,Quick Sort 表面上也如此,但背后却藏了一棵二叉树。这也能说明为什么原始的 Quick Sort 会有一个 O(n^2) 的最坏情形,此时对应的二叉树一定非常不平衡(比如输入是基本有序的,你却用第一个元素作为枢纽元)。

其实我们可以丢掉 Quick Sort 的分割算法,通过建立二叉排序树来得到一个理论上能与 Quick Sort 抗衡的排序算法。

    * 通过插入建立一棵平衡二叉树,时间界 O(nlog n);
    * 先序遍历此树,得到排好序的序列,时间界 O(n);

这样,总的时间界也是 O(nlog n)。这个算法在实践中当然不如 Quick Sort,因为 Quick Sort 的分割算法效率很高,而且最后不用去遍历一棵二叉树,但是它对于理解 Quick Sort 是有帮助的。

---------------------------------------------------------


发表的:

#include
using namespace std;

//quickSort algorithm
template < class T >
int partition(T a[], int p, int r){
T x = a[r];
int i = p-1;
  for(int j=p;j     if(a[j] <= x){
     i++;
     swap(a,a[j]);
    }
  }
  swap(a[i+1], a[r]);
  return i+1;
}


template< class T >
void quickSort(T a[], int p, int r){
if(p < r){
  int q = partition(a, p , r);
  quickSort(a, p , q-1);
  quickSort(a, q+1 , r);
}
}

int main()
{
    int arr[]={23,31,4,9,12,7,59};
    int const n=sizeof(arr)/sizeof(arr[0]);
    for(int i=0;i< quickSort(arr,0,n);
cout<<"after sort: "< for(int i=0;i<
}
阅读(781) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~