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  #如果标准值小于最大坐标内的元素值,那么最大坐标收敛1

         let e=e-1

     elif [ $tmp -gt ${arr[$e]} ]; then   #如果标准值大于最大坐标内的元素值,那么将其赋值给标准值数组内位置,起始点收敛1;此时标准值在临时变量tmp中

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

         let s=s+1

         f=1 #修改此值,if条件将会变为false,下次循环走另一个分支

     fi

   else

     if [ $tmp -ge ${arr[$s]} ]; then #果标准值等于最大坐标内的元素值,那么直接收敛起始值1

         let s=s+1

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

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

         let e=e-1

         f=2 修改此值,if条件将会变为true,下次循环走另一个分支

     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.参数可以是一个变量,变量可以是数组,但本例未这么实用,只是测试可以这么用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乐大师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值