快速排序
去年大一下学数据结构的时候,学到了快速排序,记得当时怎么都不理解~!尤其不理解递归的实现。
今天复习算法的时候发现并不是当时想的那么难,于是就代码实现了一下!我们都知道快排的效率高低取决于基准元素(这个可能不同的人叫法不一样,就是交换轴,我想你懂的,O(∩_∩)O~)的选择,一般我们选取第一个元素(或某一个),但是这样选取可能会导致快排的最低效率。还可以随机选取一个元素作为基准元素。
代码:
/* 主题:快速排序
* 作者:chinazhangjie
* 邮箱:chinajiezhang@gmail.com
* 开发语言: C++
* 开发环境: Virsual Studio 2005
* 时间: 2010.12.09
*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <ctime>
#include <windows.h>
using namespace std;
template <class T>
class Sort
{
public:
Sort (const vector<T>& vsortData, bool bsortMode)
: m_vsortData(vsortData), m_bsortMode(bsortMode)
{}
virtual void QSort()
{
__QSort (0, m_vsortData.size() - 1) ;
}
// display all element
void display () const
{
for (size_t i = 0; i < m_vsortData.size() / 10; ++ i)
{
copy (m_vsortData.begin() + 10 * i,
m_vsortData.begin() + 10 * i + 10,
ostream_iterator<int>(cout," "));
cout << endl ;
}
}
protected:
bool __compare (const T& rth, const T& lth)
{
return m_bsortMode ? (rth < lth) : (rth > lth) ;
}
virtual void __QSort (int istart, int iend)
{
if (istart < iend)
{
int isegLocation = __partition (istart, iend) ;
__QSort (istart, isegLocation - 1) ;
__QSort (isegLocation + 1, iend) ;
}
}
virtual int __partition(int istart, int iend)
{
int iinc = istart ;
int idec = iend ;
T midData = m_vsortData[iinc] ;
while (true)
{
while (__compare (m_vsortData[iinc], midData) && iinc <= iend)
{
++ iinc ;
}
while (__compare (midData, m_vsortData[idec]) && idec >= istart)
{
-- idec ;
}
if (iinc >= idec)
break ;
swap (m_vsortData[iinc], m_vsortData[idec]) ;
Sleep (100) ; // 增大交换的代价
}
swap (m_vsortData[iinc], m_vsortData[idec]) ;
return idec ;
}
virtual int __getPivot(int istart, int iend) = 0 ;
protected:
vector<T> m_vsortData ;
// true:从小到大,false: 从大到小
bool m_bsortMode ;
} ;
template <class T>
class QuickSort : public Sort<T>
{
public:
QuickSort (const vector<T>& vsortData, bool bsortMode)
: Sort (vsortData, bsortMode)
{}
protected:
virtual int __getPivot(int istart, int iend)
{
return istart ;
}
} ;
template <class T>
class RandomQuickSort : public Sort<T>
{
public:
RandomQuickSort (const vector<T>& vsortData, bool bsortMode)
: Sort (vsortData, bsortMode)
{}
protected:
virtual int __getPivot(int istart, int iend)
{
srand (time(NULL)) ;
return istart + rand () % (iend - istart) ;
}
} ;
int main ()
{
const int size = 100;
vector<int> sortdata (size) ;
for (int i = 0; i < size; ++ i)
{
sortdata[i] = i ;
}
random_shuffle (sortdata.begin(), sortdata.end()) ;
QuickSort<int> qs (sortdata, false) ;
SYSTEMTIME sys1;
SYSTEMTIME sys2;
GetLocalTime(&sys1) ;
qs.QSort () ;
GetLocalTime(&sys2) ;
printf ("%d, %d\n",
(sys2.wSecond - sys1.wSecond), (sys2.wMilliseconds - sys1.wMilliseconds));
random_shuffle (sortdata.begin(), sortdata.end()) ;
// qs.display () ;
RandomQuickSort<int> rqs (sortdata, true);
GetLocalTime(&sys1) ;
rqs.QSort () ;
GetLocalTime(&sys2) ;
printf ("%d, %d\n",
(sys2.wSecond - sys1.wSecond), (sys2.wMilliseconds - sys1.wMilliseconds));
return 0 ;
}
理论上来说,随机取值回比直接选取效率要高一下,但是一开始测试的结果确实相反的,无论我采用多大的数组,直接选取效率要高于随机取值效率高。
后来我仔细想了一下,在我的程序中交换消耗的时间可能要比获得随机数的时间要短的多,所以才会有这种效果。也就是说有点本末倒置了,事实上交换的时间应该远大于获得随机数的时间。为了验证我的结论我在交换后加了一条语句sleep,也就是增加交换消耗的时间。运行后,果然如此。所以和我们想的一样,随机选取要比直接选取效率要高。我一直觉得会有更好的算法来选择基准元素,比如去中位数之类的,但是局限性有太强,只有具体问题具体分析了。
ok,表述完毕,吃饭去了!