//快速排序<C++版>
typedef unsigned char usc;
typedef unsigned long usl;
#include<iostream.h>
#include<stdlib.h>
static void swap(usc*p,usc*q)/*仅供Qsort()调用*/
{usc c=*p;*p=*q;*q=c;}/*故swap()不是public函数*/
void Qsort( /*快速排序函数*/
usc*LL, /*LL为待排序字符串的起始地址*/
usc*RR) /*RR为末字符(并非'\0')的地址*/
{ static usc*rr,cc;
auto usc*ll; /*因参与递归调用故ll为auto型*/
ll=LL;rr=RR;
if(ll>=rr) /*如果是空字符串或者只含一个*/
return; /*元素则可以认为排序业已完成*/
cc=*ll++; /*否则取首字符作区间划分基准*/
check1:if(ll==rr)/*若ll==rr则表示分区即将完成*/
goto equal; /*只剩(*ll)亦即(*rr)归属待定*/
renew:if(*ll<cc) /*若(*ll)<cc则归属"小数区间"*/
{ ll++; goto check1; }
check2:if(ll==rr)/*若ll==rr则表示分区即将完成*/
goto equal; /*只剩(*ll)亦即(*rr)归属待定*/
if(*rr>cc) /*若(*rr)>cc则归属"大数区间"*/
{ rr--; goto check2; }
swap(ll++,rr--); /*有点像一对一战俘交换*/
/*至此[LL,ll-01]为小数区,[rr+01,RR]为大数区*/
if(ll<rr)goto renew;
/*若ll<rr则至少有两个元素的归属待定,转renew*/
else if(ll>rr)goto digui;/*实际是ll-rr==1*/
/*若ll-rr==1则表示所有元素的归属都已确定,故转
递归调用.注意因swap()前恒有LL<ll<rr<=RR所以
swap(ll++,rr--)后,LL<rr<ll<=RR,即"小数区间"
[LL+1,rr]与"大数区间"[ll,RR]都至少有1个元素
(如果基准元素*LL既不算大数也不算小数的话)*/
equal: /*以下确定(*ll)即(*rr)的归属
此时的情况是LL<rr==ll<=RR.在"最坏"的情况下
①如果(*rr)>cc,那么"小数区间"有可能是空集!
②如果(*ll)<cc,那么"大数区间"有可能是空集!
为避免无限递归,针对情况①②的解决方案如下:
①将基准元素(*LL)划入"小数区间"即[LL,ll-1]
②对调(*LL)与(*ll),令"大数区间"为[ll,RR].*/
if(*ll<cc)swap(LL,ll);////本语句顶以下五行
//// if(*ll<cc)ll++;else rr--;
//// if(rr==LL)//若"小数区间"为空集
//// { Qsort(LL+1,RR);return; }
//// if(ll>RR) //若"大数区间"为空集
//// { swap(LL,RR);Qsort(LL,RR-1);return; }
digui: /*以下递归调用先后顺序不限*/
Qsort(ll,RR); /*因参与递归ll应为auto属性*/
Qsort(LL,ll-1);/*原则上ll-1也可用rr替换之*/
/*但那样做要求rr为auto属性*/
}
int main()
{
usl NUM,i;
usc *s,*p;
cout<<"NUM=";
cin >> NUM;
p=s=new usc[NUM+1];
for(i=0; i<NUM; i++)
s[i]=rand()%96+32;
s[NUM]='\0';
Qsort(s,&s[NUM-1]);
while(*p)cout<<*p++;
cout<<endl;
delete[]s;
return 0;
}
落霞与孤鹜齐飞,秋水共长天一色! 心有多大,路有多宽。三教九流,鸡鸣狗盗。兼收并蓄,海纳百川。