Shell常见的排序和查找算法

Shell常见的排序和查找算法

一、排序算法

1、冒泡排序
1.1 基本思想

所谓冒泡排序,就是如同水里的泡泡一样,将合适的值一次次往上冒,直到所有数据全部处理完成。
在数据中的解释就是:从第一个数开始,每次都将前一个数与后一个数作比较,如果前一个数大于后一个数,则将两者交换位置(否则不交换),此时,后一个数值已变化,然后再将后一个数与后后一个数作比较,重复操作,直到所有的数都比较完成。

1.2 算法过程

先定义一个外循环,控制整个排序次数(排序次数为数据的个数),然后再内嵌一个内循环,在内循环中进行每次排序的比较,内循环的比较次数为:数据个数-当前排序次数,因为,比如说,在第一次比较时,比较得出的结果一定是数据中的最大值,并排在最后,此时,最大值已知,不用再进行比较了,以此类推,每次都会减少一次比较。

20210611113132421

1.3 时间复杂度

第一次循环n,第二次循环n,综合为O(n^2)。

1.4 shell实现
#!/bin/bash
a=(10 20 30 80 40 60 )
echo ${a[*] }
n=${#a[*]}         //提取数组长度
for (( i=1 ; i<n; i++ ))
do
        for ((j=0;j<n-i;j++)) //确定比较元素的位置,比较相邻两个元素,较大的数往后放,比较次数随比较轮数而减少
        do
                if [ ${a[$j]} -gt ${a[$j+1]} ] ; then
                c=${a[$j+1]} ; a[$j+1]=${a[$j]} ; a[$j]=$c;   //元素交互
                fi
        done
done
echo ${a[*]}

image-20220705111634663

image-20220705111659122

2、插入排序
2.1 基本思想

所谓插入排序,就是将后面的数与前面的数比较,如果后面的数小于前面的数,就将后面的数插入到前面的数的前面。

2.2 算法过程

所谓插入排序,就是从第二个数开始,依次向前比较,如果前面一个数小于这个数,那么就将前面一个数右移,将前面一个数的位置赋空(看了代码就明白),然后再比较这个数与前前一个数,如果前前一个数大于这个数,则将这个前前的数赋给这个空位置,前前一个数的原位置则就代表了空,重复以上操作,最后将空位置补上当前操作的数即可,直到全部比较完成。

1234546xczxdv

2.3 时间复杂度:

第一次循环n,第二次循环n,综合为O(n^2)。

2.4 Shell实现
#!/bin/bash
a=(1 4 3 2 9 7 6 8 5)
n=${#a[*]}
for (( i=1 ; i<n ; i++))
do
        cmp=${a[$i]}
        for (( j=i-1 ; j>=0 && a[j]>cmp; j-- )) //将比较的元素钱
        do
                a[j+1]=${a[j]}
        done
        a[$j+1]=$cmp
done
echo ${a[*]}

image-20220705112354754

image-20220705112717892

3、选择排序
3.1 基本思想

所谓选择排序,就是每次选择出当前比较数据的最小值,然后将其传递到数据的前面。

3.2 算法过程:

第一步:定义一个外层循环,控制排序次数,循环次数为数据个数-1。
第二步:定义一个变量k,这个变量等于外层循环的次数的起始值 i ,目的是存放当前需要操作的数据的第一个数,以便与后面的数比较。
第三步:定义一个内层循环,这个内层循环代表着当前需要比较的次数,起始值为k+1,因为k是当前数据的第一个位置,不需要让自己比自己,结束位置为数据末端,即数据的长度。
第四步:将k位置的数与数据比较,如果比较的数小于k位置的数,则将这个索引赋给k,以此类推,最后每次比较结束都会找到当前数据的最小值。
第五步,将第i的位置的数据与k的数据交换,即将最小值放到前面。
第六步:再次操作以上步骤,直到数据全部完成。

sfgsdgdsf

3.3 时间复杂度:

第一次循环n,第二次循环n,综合为O(n^2)。

3.4 Shell实现

还有两种方式,一种直接交互,一种是记下下标,最后交互。

方式一:

#!/bin/bash
a=(10 20 30 80 40 60 )
echo ${a[*] }
n=${#a[*]}
for (( i=0 ; i<n; i++ ))
do
        for ((j=i+1;j<n;j++))
        do
                if [ ${a[$i]} -gt ${a[$j]} ] ; then
                c=${a[$j]} ; a[$j]=${a[$i]} ; a[$i]=$c;  //比较成立的就交换,确保每次都是找出最小或最大值
                fi
        done
done
echo ${a[*]}

image-20220705113516126

image-20220705113529882

方式二:

#!/bin/bash
a=(10 20 30 80 40 60 )
echo ${a[*] }
n=${#a[*]}
for (( i=0 ; i<n; i++ ))
do
    	k=$i
        for ((j=i+1;j<n;j++))
        do
                if [ ${a[$k]} -gt ${a[$j]} ] ; then
                k=$i;  //比较成立不立即交互,记下下标,确保每次都是找出最小或最大值的下标
                fi
        done
        c=${a[$i]} ; a[$i]=${a[$k]} ; a[$k]=$c;  
done
echo ${a[*]}

image-20220705114509772

image-20220705114522004

二、查找算法

1、顺序查找
1.1 基本思想

对于任意一个序列以及一个给定的元素,将给定元素与序列中元素依次比较,直到找出与给定关键字相同的元素,或者将序列中的元素与其都比较完为止。

1.2 时间复杂度

只有一次循环n次,所以为综合为O(n)。

1.3 Shell实现
#!/bin/bash
read -p "请输入要查找的数值:" num
a=(10 20 30 80 40 60 )
echo ${a[*] }
n=${#a[*]}
f=0    //判断是否找到的标志位
for (( i=0;i<n;i++ ))
{
        if [[ ${a[$i]} = $num ]] ; then
                echo "数组中存在你要查找的${num},下标为$i" 
                f=1
        fi
}
if [ $f -eq 0 ] ; then
        echo 数组中不存在你要查找的$num 
fi

image-20220705120305341

image-20220705120221541

2、折半查找(二分法查找)
1.1 基本思想

首先将给定值key与表中中间位置元素的关键字比较,若相等,则查找成功,返回该元素的存储位置;若不等,则所需查找的元素只能在中间元素以外的前半部分或后半部分(例如,在查找表升序排列时,若给定值key大于中间元素的关键字,则所查找的元素只可能在后半部分)。然后在缩小的范围内继续进行同样的查找,如此重复,直到找到为止,或确定表中没有所需要查找的元素,则查找不成功,返回查找失败的信息。

1.2 时间复杂度

二分查找因为每次都是从中间点开始查找,所以每次都是n/2,在最坏的情况下,时间复杂度综合位O(log(n))。

1.3 Shell的实现
#!/bin/bash
mao()    //冒泡排序
{
for (( i=1 ; i<n; i++ ))
do
        for ((j=0;j<n-i;j++))
        do
                if [ ${a[$j]} -gt ${a[$j+1]} ] ; then
                c=${a[$j+1]} ; a[$j+1]=${a[$j]} ; a[$j]=$c;
                fi
        done
done
}
read -p "请输入要查找的数值:" num
a=(10 20 30 80 40 60 )
echo ${a[*] }
n=${#a[*]}
f=0
mao
echo "排序后数组:"${a[*]}   //调用冒泡排序函数后输出排序后的数组
top=0
let low=$n-1
while [ $top -le $low ]
do
        let mid=($top+$low)/2                      //去上下限值的中间值
        if [ $num -eq ${a[$mid]} ] ; then
                echo "数组中存在你要查找的${num},下标为$mid"
                f=1
                break
        elif [ $num -lt ${a[$mid]} ] ; then
                let low=$mid-1                     //修改上限值
        else
                let top=$mid+1                     //修改下限值
        fi
done

image-20220705125810241
image-20220705125617084

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值