求教一个快速排序的问题

skyaspnet 2010-11-03 04:23:48
以下是一段快速排序代码:


#include<stdio.h>
int Partition(int a[],int low,int high)
{
int pivotkey = a[low];
while(low<high)
{
if(low<high && a[high]>=pivotkey) --high;
a[low]=a[high];
if(low<high && a[low]<=pivotkey) ++low;
a[high]=a[low];
}
a[low]=pivotkey;
return low;
}

void Quick_Sort(int a[],int low,int high)
{
if(low<high)
{
int position = Partition(a,low,high);
Quick_Sort(a,low,poisition-1);
Quick_Sort(a,poisition+1,high);
}
}

void main()
{
int a[4]={45,56,23,5};
Quick_Sort(a,0,3);
}


哪位大侠能帮忙解释一下:


while(low<high)
{
if(low<high && a[high]>=pivotkey) --high;
a[low]=a[high];
if(low<high && a[low]<=pivotkey) ++low;
a[high]=a[low];
}
a[low]=pivotkey;


这一段?

没有明白为什么要用if而不用while

if(low<high && a[high]>=pivotkey) --high;
a[low]=a[high];

谢谢!
...全文
183 15 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2010-11-04
  • 打赏
  • 举报
回复
//接上帖
/***
*shortsort(hi, lo, width, comp) - insertion sort for sorting short arrays
*
*Purpose:
* sorts the sub-array of elements between lo and hi (inclusive)
* side effects: sorts in place
* assumes that lo < hi
*
*Entry:
* char *lo = pointer to low element to sort
* char *hi = pointer to high element to sort
* size_t width = width in bytes of each array element
* int (*comp)() = pointer to function returning analog of strcmp for
* strings, but supplied by user for comparing the array elements.
* it accepts 2 pointers to elements and returns neg if 1<2, 0 if
* 1=2, pos if 1>2.
*
*Exit:
* returns void
*
*Exceptions:
*
*******************************************************************************/

static void __cdecl shortsort (
char *lo,
char *hi,
size_t width,
int (__cdecl *comp)(const void *, const void *)
)
{
char *p, *max;

/* Note: in assertions below, i and j are alway inside original bound of
array to sort. */

while (hi > lo) {
/* A[i] <= A[j] for i <= j, j > hi */
max = lo;
for (p = lo+width; p <= hi; p += width) {
/* A[i] <= A[max] for lo <= i < p */
if (comp(p, max) > 0) {
max = p;
}
/* A[i] <= A[max] for lo <= i <= p */
}

/* A[i] <= A[max] for lo <= i <= hi */

swap(max, hi, width);

/* A[i] <= A[hi] for i <= hi, so A[i] <= A[j] for i <= j, j >= hi */

hi -= width;

/* A[i] <= A[j] for i <= j, j > hi, loop top condition established */
}
/* A[i] <= A[j] for i <= j, j > lo, which implies A[i] <= A[j] for i < j,
so array is sorted */
}


/***
*swap(a, b, width) - swap two elements
*
*Purpose:
* swaps the two array elements of size width
*
*Entry:
* char *a, *b = pointer to two elements to swap
* size_t width = width in bytes of each array element
*
*Exit:
* returns void
*
*Exceptions:
*
*******************************************************************************/

static void __cdecl swap (
char *a,
char *b,
size_t width
)
{
char tmp;

if ( a != b )
/* Do the swap one character at a time to avoid potential alignment
problems. */
while ( width-- ) {
tmp = *a;
*a++ = *b;
*b++ = tmp;
}
}
赵4老师 2010-11-04
  • 打赏
  • 举报
回复
会用qsort函数就应该可以了吧。要不就参考qsort源代码
c:\Microsoft SDK\src\crt\qsort.c
/***
*qsort.c - quicksort algorithm; qsort() library function for sorting arrays
*
* Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
*
*Purpose:
* To implement the qsort() routine for sorting arrays.
*
*******************************************************************************/

#include <cruntime.h>
#include <stdlib.h>
#include <search.h>
#include <internal.h>

/* Always compile this module for speed, not size */
#pragma optimize("t", on)

/* prototypes for local routines */
static void __cdecl shortsort(char *lo, char *hi, size_t width,
int (__cdecl *comp)(const void *, const void *));
static void __cdecl swap(char *p, char *q, size_t width);

/* this parameter defines the cutoff between using quick sort and
insertion sort for arrays; arrays with lengths shorter or equal to the
below value use insertion sort */

#define CUTOFF 8 /* testing shows that this is good value */

/***
*qsort(base, num, wid, comp) - quicksort function for sorting arrays
*
*Purpose:
* quicksort the array of elements
* side effects: sorts in place
* maximum array size is number of elements times size of elements,
* but is limited by the virtual address space of the processor
*
*Entry:
* char *base = pointer to base of array
* size_t num = number of elements in the array
* size_t width = width in bytes of each array element
* int (*comp)() = pointer to function returning analog of strcmp for
* strings, but supplied by user for comparing the array elements.
* it accepts 2 pointers to elements and returns neg if 1<2, 0 if
* 1=2, pos if 1>2.
*
*Exit:
* returns void
*
*Exceptions:
*
*******************************************************************************/

/* sort the array between lo and hi (inclusive) */

#define STKSIZ (8*sizeof(void*) - 2)

void __cdecl qsort (
void *base,
size_t num,
size_t width,
int (__cdecl *comp)(const void *, const void *)
)
{
/* Note: the number of stack entries required is no more than
1 + log2(num), so 30 is sufficient for any array */
char *lo, *hi; /* ends of sub-array currently sorting */
char *mid; /* points to middle of subarray */
char *loguy, *higuy; /* traveling pointers for partition step */
size_t size; /* size of the sub-array */
char *lostk[STKSIZ], *histk[STKSIZ];
int stkptr; /* stack for saving sub-array to be processed */

if (num < 2 || width == 0)
return; /* nothing to do */

stkptr = 0; /* initialize stack */

lo = base;
hi = (char *)base + width * (num-1); /* initialize limits */

/* this entry point is for pseudo-recursion calling: setting
lo and hi and jumping to here is like recursion, but stkptr is
preserved, locals aren't, so we preserve stuff on the stack */
recurse:

size = (hi - lo) / width + 1; /* number of el's to sort */

/* below a certain size, it is faster to use a O(n^2) sorting method */
if (size <= CUTOFF) {
shortsort(lo, hi, width, comp);
}
else {
/* First we pick a partitioning element. The efficiency of the
algorithm demands that we find one that is approximately the median
of the values, but also that we select one fast. We choose the
median of the first, middle, and last elements, to avoid bad
performance in the face of already sorted data, or data that is made
up of multiple sorted runs appended together. Testing shows that a
median-of-three algorithm provides better performance than simply
picking the middle element for the latter case. */

mid = lo + (size / 2) * width; /* find middle element */

/* Sort the first, middle, last elements into order */
if (comp(lo, mid) > 0) {
swap(lo, mid, width);
}
if (comp(lo, hi) > 0) {
swap(lo, hi, width);
}
if (comp(mid, hi) > 0) {
swap(mid, hi, width);
}

/* We now wish to partition the array into three pieces, one consisting
of elements <= partition element, one of elements equal to the
partition element, and one of elements > than it. This is done
below; comments indicate conditions established at every step. */

loguy = lo;
higuy = hi;

/* Note that higuy decreases and loguy increases on every iteration,
so loop must terminate. */
for (;;) {
/* lo <= loguy < hi, lo < higuy <= hi,
A[i] <= A[mid] for lo <= i <= loguy,
A[i] > A[mid] for higuy <= i < hi,
A[hi] >= A[mid] */

/* The doubled loop is to avoid calling comp(mid,mid), since some
existing comparison funcs don't work when passed the same
value for both pointers. */

if (mid > loguy) {
do {
loguy += width;
} while (loguy < mid && comp(loguy, mid) <= 0);
}
if (mid <= loguy) {
do {
loguy += width;
} while (loguy <= hi && comp(loguy, mid) <= 0);
}

/* lo < loguy <= hi+1, A[i] <= A[mid] for lo <= i < loguy,
either loguy > hi or A[loguy] > A[mid] */

do {
higuy -= width;
} while (higuy > mid && comp(higuy, mid) > 0);

/* lo <= higuy < hi, A[i] > A[mid] for higuy < i < hi,
either higuy == lo or A[higuy] <= A[mid] */

if (higuy < loguy)
break;

/* if loguy > hi or higuy == lo, then we would have exited, so
A[loguy] > A[mid], A[higuy] <= A[mid],
loguy <= hi, higuy > lo */

swap(loguy, higuy, width);

/* If the partition element was moved, follow it. Only need
to check for mid == higuy, since before the swap,
A[loguy] > A[mid] implies loguy != mid. */

if (mid == higuy)
mid = loguy;

/* A[loguy] <= A[mid], A[higuy] > A[mid]; so condition at top
of loop is re-established */
}

/* A[i] <= A[mid] for lo <= i < loguy,
A[i] > A[mid] for higuy < i < hi,
A[hi] >= A[mid]
higuy < loguy
implying:
higuy == loguy-1
or higuy == hi - 1, loguy == hi + 1, A[hi] == A[mid] */

/* Find adjacent elements equal to the partition element. The
doubled loop is to avoid calling comp(mid,mid), since some
existing comparison funcs don't work when passed the same value
for both pointers. */

higuy += width;
if (mid < higuy) {
do {
higuy -= width;
} while (higuy > mid && comp(higuy, mid) == 0);
}
if (mid >= higuy) {
do {
higuy -= width;
} while (higuy > lo && comp(higuy, mid) == 0);
}

/* OK, now we have the following:
higuy < loguy
lo <= higuy <= hi
A[i] <= A[mid] for lo <= i <= higuy
A[i] == A[mid] for higuy < i < loguy
A[i] > A[mid] for loguy <= i < hi
A[hi] >= A[mid] */

/* We've finished the partition, now we want to sort the subarrays
[lo, higuy] and [loguy, hi].
We do the smaller one first to minimize stack usage.
We only sort arrays of length 2 or more.*/

if ( higuy - lo >= hi - loguy ) {
if (lo < higuy) {
lostk[stkptr] = lo;
histk[stkptr] = higuy;
++stkptr;
} /* save big recursion for later */

if (loguy < hi) {
lo = loguy;
goto recurse; /* do small recursion */
}
}
else {
if (loguy < hi) {
lostk[stkptr] = loguy;
histk[stkptr] = hi;
++stkptr; /* save big recursion for later */
}

if (lo < higuy) {
hi = higuy;
goto recurse; /* do small recursion */
}
}
}

/* We have sorted the array, except for any pending sorts on the stack.
Check if there are any, and do them. */

--stkptr;
if (stkptr >= 0) {
lo = lostk[stkptr];
hi = histk[stkptr];
goto recurse; /* pop subarray from stack */
}
else
return; /* all subarrays done */
}

//未完下帖续
skyaspnet 2010-11-04
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 dingshaofengbinbin 的回复:]

代码错了!!就应该用while!!
[/Quote]

代码没错,两段代码都是可以实现快速排序功能的
dingshaofengbinbin 2010-11-04
  • 打赏
  • 举报
回复
代码错了!!就应该用while!!
skyaspnet 2010-11-04
  • 打赏
  • 举报
回复
原因其实也简单,使用WHILE而不使用IF主要减少了递归次数,

也就是说while可以更快地确定low和high的值,从而在将这两个值传递给

下一次递归时减少了判断的次数,最终减少了递归次数
skyaspnet 2010-11-04
  • 打赏
  • 举报
回复
刚才测试了一下运行步骤数,
这种写法

while(low<high) { while((low<high) && (arr[high]>=pivotkey)) { high--; } if(pivotkey>arr[high]) { arr[low]=arr[high]; arr[high]=pivotkey; low++; } while((low<high) && (arr[low]<=pivotkey)) { low++; } if(pivotkey<arr[low]) { arr[high]=arr[low]; arr[low]=pivotkey; high--; } }





while(low<high) { if(low<high && a[high]>=pivotkey) --high; a[low]=a[high]; if(low<high && a[low]<=pivotkey) ++low; a[high]=a[low]; } a[low]=pivotkey;


在输入数据为:49,38,65,97,76,13,27,9,2,1 情况下性能的两倍
do__i 2010-11-03
  • 打赏
  • 举报
回复
是while!
你可以自己上机试一下啊!


while(low<high)
{
while(low<high && pivotkey<=a[high])
--high;
if(low<high)
a[low++]=a[high];

while(low<high && pivotkey>=a[low])
++low;
if(low<high)
a[high--]=a[low];

}
a[low]=pivotkey;
tangxianghenggood 2010-11-03
  • 打赏
  • 举报
回复
这些程序是我自己一个一个写的,现拿出来让和我一样的初学者分享一下,用的是dev C++ 编译,里面包括详细的分析过程和代码注释,有两个文件,一个是c++/c 基础的,另一个是基础提高篇,我相信对初学者是有很大的帮助的! 同时里面有运行的图片,下载的同学可以先看题目,然后在自己去做,在和我比较一下思路,我写的不是很好的地方还望赐教

下载地址:http://tangxianghenggood.download.csdn.net/

上面有,并且我我个人资源里还有dec 写的个系统源代码,希望有帮助,加油
junjun151 2010-11-03
  • 打赏
  • 举报
回复
这个确实只是为了简洁。


skyaspnet 2010-11-03
  • 打赏
  • 举报
回复
难道只为了简洁?
skyaspnet 2010-11-03
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 luciferisnotsatan 的回复:]

while是循环,if是判断。
lz是不理解这个循环的意思?
while(low<high)
{
if(low<high && a[high]>=pivotkey) --high;
a[low]=a[high];
if(low<high && a[low]<=pivotkey) ++low;
a[high]=a……
[/Quote]

不是,这一段可以换一种写法:


while(low<high)
{
while((low<high) && (arr[high]>=pivotkey))
{
high--;
}

if(pivotkey>arr[high])
{
arr[low]=arr[high];
arr[high]=pivotkey;
low++;
}

while((low<high) && (arr[low]<=pivotkey))
{
low++;
}

if(pivotkey<arr[low])
{
arr[high]=arr[low];
arr[low]=pivotkey;
high--;
}
}


主要是没明白为什么要这样写:


while(low<high)
{
if(low<high && a[high]>=pivotkey) --high;
a[low]=a[high];
if(low<high && a[low]<=pivotkey) ++low;
a[high]=a[low];
}
luciferisnotsatan 2010-11-03
  • 打赏
  • 举报
回复
while是循环,if是判断。
lz是不理解这个循环的意思?
while(low<high)
{
if(low<high && a[high]>=pivotkey) --high;
a[low]=a[high];
if(low<high && a[low]<=pivotkey) ++low;
a[high]=a[low];
}
try325 2010-11-03
  • 打赏
  • 举报
回复
注意到--high,用while存在一个遍历的过程

70,022

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧