shell小技巧(六十七)快速排序

快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)。具体算法描述如下:

从数列中挑出一个元素,称为 “基准”(本例中使用了第一个元素作为基准);
重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

#!/bin/bash

arr=(101 0 35 27  87 99 51 6 33 37 28 62 90 111 222 333 550 22 18 5 11 17 23 50 78 30 61)

icount=0

low0=0

arrlen=${#arr[*]}

let high0=arrlen-1

function getIndex()

{

 

 s=$1

 e=$2

 tmp=${arr[$s]}

 f=2

 while [ $s -lt $e ]; do

   if [ $f -eq 2 ]; then 

     if [ $tmp -le ${arr[$e]} ]; then

         let e=e-1

     elif [ $tmp -gt ${arr[$e]} ]; then

         arr[$s]=${arr[$e]}

         let s=s+1

         f=1

     fi

   else

     if [ $tmp -ge ${arr[$s]} ]; then

         let s=s+1

     elif [ $tmp -lt ${arr[$s]} ]; then

         arr[$e]=${arr[$s]}

         let e=e-1

         f=2

     fi

   fi  

 done

 arr[$s]=$tmp

 return $s

}

function quicksort()

{

 r[$icount]=0

 low=$1 

 high=$2

 let y0=high-low

 if [ $y0 -gt 1 ]; then

   getIndex $low $high

   x=$?

   let icount=icount+1

   low1=$low

   let low2=x+1

   let high1=x-1

   high2=$high0

   let y1=high1-low1

   let y2=high2-low2

   if [  $y1 -gt 1 ]; then

     quicksort $low1 $high1

   elif [ $y1 -eq 1 ]; then

     tt=${arr[$low1]}

     ttt=${arr[$high1]}

     if [ $tt -gt $ttt ]; then

        arr[$low1]=$ttt

        arr[$high1]=$tt

       return 0

     fi

   fi

   if [ $y2 -gt 0 ]; then

      quicksort $low2 $high2

   elif [ $y2 -eq 1 ]; then

     tt=${arr[$low2]}

     ttt=${arr[$high2]}

     if [ $tt -gt $ttt ]; then

        arr[$low2]=$ttt

        arr[$high2]=$tt

       return 0

     fi

   fi

 else

   return 0

 fi

}

echo ${arr[@]}

echo "--->>>"

quicksort $low0 $high0

echo ${arr[@]}

echo "END"

总结:

本例与之前的冒泡排序、插入排序、选择排序不同,其使用递归方式获得所有元素的顺序。

递归是本例的重点,也是难点。需要设定合理的终止条件,否则无法得到正确结果。

调试过程中也花了很多时间,代码中遗留了一些无用的代码。

另一个问题就是函数返回值和参数使用以及应用范围。这里给出本例实践结论:

1.主程序中的变量,在函数中可以使用,包括修改

2.函数返回值使用$?,使用中每次调用会覆盖前次执行返回值,但递归执行中只要再次调用前取出该值不影响最后结果。

3.参数可以是一个变量,变量可以是数组,但本例未这么实用,只是测试可以这么用。

你可能感兴趣的:(Shell技巧)