Begin
记录一下自己的学习过程啦~~
上题目
三部排序
一般的排序有许多经典算法,如快速排序、希尔排序等。
但实际应用时,经常会或多或少有一些特殊的要求。我们没必要套用那些经典算法,可以根据实际情况建立更好的解法。
比如,对一个整型数组中的数字进行分类排序:
使得负数都靠左端,正数都靠右端,0在中部。注意问题的特点是:负数区域和正数区域内并不要求有序。可以利用这个特点通过1次线性扫描就结束战斗!!
以下的程序实现了该目标。
static void sort(int[] x)
{
int p = 0;
int left = 0;
int right = x.length-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{
_________________________; //代码填空位置
}
}
}
如果给定数组:
25,18,-2,0,16,-5,33,21,0,19,-16,25,-3,0
则排序后为:
-3,-2,-16,-5,0,0,0,21,19,33,25,16,18,25
思路过程
1.已知负数区域和正数区域的排序,求0 的排序代码
2.分析一下已知排序代码
(1)如果x[p]<0,那么将x[p]与left下标元素进行互换,互换完后将p与left自增;
(2)如果x[p]>0,那么将x[p]与right下标元素进行互换,互换完后将right自减;
(3)关键问题出现了:为什么x[p]>0时,p不进行自增?
(4)x[p]<0,将数字交换后,永远保证左边区域是小于0的数;但是x[p]>0,将数字交换后,无法保证交换到左边的数字小于0,所以要对这个交换过来的数字继续进行判断
(5)这里又会产生疑问:为什们在x[p]<0交换后不用判断交换到右边的数字是否大于0?
(6)因为p自增,保证数组的判断方向从左到右,最后右边的数字也能进行排序
3.x[p]=0的代码
(1)因为无法确定正数与负数的个数,所以不可以将0的位置固定
(2)关键:0一定排在正数的左边,负数的右边
代码
public class Main {
public static void main(String[] args) {
int[] s = {25,18,-2,0,16,-5,33,21,0,19,-16,25,-3,0};
sort(s);
for(int i=0;i<s.length;i++){
System.out.println(s[i]);
}
}
public static void sort(int[] x)
{
int p = 0;
int left = 0;
int right = x.length-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{
int index=p+1;
while(x[index]==0){
index++;
}
if(index!=right){
x[p]=x[index];
x[index]=0;
}
else{
break;
}
}
}
}
}
总结
循环过程中,要注意边界条件,否则可能成为死循环