问题描述:
标题:三部排序
一般的排序有许多经典算法,如快速排序、希尔排序等。 但实际应用时,经常会或多或少有一些特殊的要求。我们没必要套用那些经典算法,可以根据实际情况建立更好的解法。 比如,对一个整型数组中的数字进行分类排序: 使得负数都靠左端,正数都靠右端,0在中部。注意问题的特点是:负数区域和正数区域内并不要求有序。可以利用这个特点通过1次线性扫描就结束战斗!! 以下的程序实现了该目标。 其中x指向待排序的整型数组,len是数组的长度。
void sort3p(int* x, int len) { int p = 0; int left = 0; int right = len-1; while(p<=right){ if(x[p]<0){ int t = x[left]; x[left] = x[p]; x[p] = t; left++; p++; } else if(x[p]>0){ int t = x[right]; x[right] = x[p]; x[p] = t; right--; } else{ ______________________________//填空部分 } } }
来分析一下这道题,相信会写快速排序的同学应该可以秒写这个填空部分。程序一开始定义了三个变量,p,left和right,结合下面的代码,我们可以分析出,left指向的就是数组的最左端,而right指向的是数组的最右端,p就起到一个哨兵的作用。
当p指向的内容是小于0的数时,就把它和left指向的元素交换位置,并且p再往前探路,然后left右移一位,表示左边的就不用管了。当p指向的内容是大于0的数时,就把它和right指向的元素交换位置,再将right左移一位,表示后面的就不用管了。
既然对大于0和小于0的数都已经进行移位操作了,等于0的时候其实时不需要操作的(这个地方得好好体会),就只用移动指针就行了,那么要移动哪个呢,现在有left,p和right,right肯定是不可能动的,因为如果此时right指向的是一个小于0的数,左移就错了。 (显然,,别打我) 而left同理,如果此时left指向的是一个大于0的数,将left右移的话,那肯定也错了。所以就只用将哪个探路的指针向后移动就可以了。程序如下:
#include <iostream> using namespace std; void sort3p(int* x, int len) { int p = 0; int left = 0; int right = len-1; while(p<=right){ if(x[p]<0){ int t = x[left]; x[left] = x[p]; x[p] = t; left++; p++; } else if(x[p]>0){ int t = x[right]; x[right] = x[p]; x[p] = t; right--; } else{ p++; } } } int main() { int x[14] = {25,18,-2,0,16,-5,33,21,0,19,-16,25,-3,0}; sort3p(x , 14); for(int i = 0 ; i < 14 ; ++i) cout << x[i] << " "; return 0; }
完,读到这里的同学可以去复习或者学习一下快速排序。
Comments NOTHING