Bash : 冒泡排序
冒泡排序是非常基础的排序算法,本文我们看看在 Bash 脚本中如何写冒泡排序。本文的演示环境为 ubuntu 16.04。
冒泡排序的简要描述如下:
- 通过连续的比较对数组中的元素进行排序
- 比较两个相邻的元素,如果顺序不对,就交换这两个元素的位置
- 当第一轮比较结束之后,最 "重" 的元素就会被移动到最底部
- 当第二轮比较结束之后,第二 "重" 的元素就会被移动到次底部的位置
- 这意味着每轮比较不需要比较之前已经 "沉淀" 好的数据
- 如果有 n 个元素,则一共执行 n-1 轮比较
用 for 循环实现冒泡
准备一个数组(Bash 数组相关的内容请参考《Bash : 索引数组》一文):
declare -a myArr=( )
然后来主备一个交换数组元素的函数:
# 定义函数 exchangeEle() 交换数组中两个元素的位置
exchangeEle()
{
# 使用临时变量保存数组元素
local temp=${myArr[$]}
# 交换元素的位置
myArr[$]=${myArr[$]}
myArr[$]=$temp return
}
下面通过一个经典的两层循环来完成排序:
# 获取数组的长度
arrlen=${#myArr[@]} # 通过 for 循环对数组排序,注意此时是以字符串来比较的
for (( last = $arrlen ; last > ; last-- ))
do
for (( i = ; i < last - ; i++ ))
do
[[ "${myArr[$i]}" > "${myArr[$((i+1))]}" ]] && exchangeEle $i $((i+))
done
done
这就 OK 了,跑跑看:

好吧,数字被作为字符串来比较了。修正这个问题非常简单,把比较的代码换成下面的就可以了:
[[ "${myArr[$i]}" -gt "${myArr[$((i+1))]}" ]] && exchangeEle $i $((i+))
关于 Bash 中的比较操作,请参考《Bash : test 命令》一文。
再运行一次,就能看到正确结果了:

用 while 循序实现冒泡
下面我们来介绍使用 while 循序的版本。这次我们按字母序来排列数组中存放的国家名称:
myArr=(Netherlands Ukraine Zaire Turkey Russia Yemen Syria \
Brazil Argentina Nicaragua Japan Mexico Venezuela Greece England)
这里我们使用了转义符 \ 将数组元素的值放在不同的行上,这样可以避免行中的内容过长。具体的代码如下:
# 从索引 开始列出整个数
echo "The order of the original data in the array:"
echo "${myArr[*]}" # 获取数组的长度,并用来控制循环的次数。
n=${#myArr[@]} echo "Start bubbling sort:"
while [ "$n" -gt ] # 执行 n- 轮外部循环。
do
index= # 内部循环时的数组元素索引,在每轮循环开始之前需要重置。
while [ "$index" -lt $(expr $n - ) ] # 开始内部循环。
do
if [[ ${myArr[$index]} > ${myArr[$(expr $index + )]} ]]
then
exchangeEle $index $(expr $index + ) # 交换数组元素位置。
fi
let "index += 1"
done # 内部循环结束。
let "n -= 1" # 外部循环计数减 。
# 输出每轮排序后的结果。
echo "${myArr[*]}"
done # 外部循环结束。 echo "Sorted data order:"
echo "${myArr[*]}"
同样是两层循环,算法完全一样,只不过是写法有一点点不同。为了显示排序的过程,这次输出了每轮排序后的中间结果:

demo 代码
下面是本文中 demo 的完整代码:
#!/bin/bash
# bubble.sh, 本例主要用来演示索引数组的排序
# 冒泡排序的简要描述如下:
# 通过连续的比较对数组中的元素进行排序
# 比较两个相邻的元素,如果顺序不对,就交换这两个元素的位置
# 当第一轮比较结束之后,最 "重" 的元素就会被移动到最底部
# 当第二轮比较结束之后,第二 "重" 的元素就会被移动到次底部的位置
# 这意味着每轮比较不需要比较之前已经 "沉淀" 好的数据
# 一共执行 n- 轮比较 # 定义函数 exchangeEle() 交换数组中两个元素的位置
exchangeEle()
{
# 使用临时变量保存数组元素
local temp=${myArr[$]}
# 交换元素的位置
myArr[$]=${myArr[$]}
myArr[$]=$temp return
} declare -a myArr=( ) # 从索引 开始列出整个数组
echo "The order of the original data in the array:"
echo "${myArr[*]}" # 获取数组的长度
arrlen=${#myArr[@]} # 通过 for 循环对数组排序,注意此时是以字符串来比较的
for (( last = $arrlen ; last > ; last-- ))
do
for (( i = ; i < last - ; i++ ))
do
[[ "${myArr[$i]}" > "${myArr[$((i+1))]}" ]] && exchangeEle $i $((i+))
done
done echo "Sorted data order as string:"
echo "${myArr[*]}" # 通过 for 循环对数组排序,这次是作为整数来比较
for (( last = $arrlen ; last > ; last-- ))
do
for (( i = ; i < last - ; i++ ))
do
[[ "${myArr[$i]}" -gt "${myArr[$((i+1))]}" ]] && exchangeEle $i $((i+))
done
done echo "Sorted data order as number:"
echo "${myArr[*]}" myArr=(Ukraine Zaire Russia Yemen Syria \
Argentina Japan Mexico Greece)
#这里我们还使用转义符 \ 将数组元素的值放在不同的行上,这样可以避免行中的内容过长。 # 从索引 开始列出整个数
echo "The order of the original data in the array:"
echo "${myArr[*]}" # 获取数组的长度,并用来控制循环的次数。
n=${#myArr[@]} echo "Start bubbling sort:"
while [ "$n" -gt ] # 执行 n- 轮外部循环。
do
index= # 内部循环时的数组元素索引,在每轮循环开始之前需要重置。
while [ "$index" -lt $(expr $n - ) ] # 开始内部循环。
do
if [[ ${myArr[$index]} > ${myArr[$(expr $index + )]} ]]
then
exchangeEle $index $(expr $index + ) # 交换数组元素位置。
fi
let "index += 1"
done # 内部循环结束。
let "n -= 1" # 外部循环计数减 。
# 输出每轮排序后的结果。
echo "${myArr[*]}"
done # 外部循环结束。 echo "Sorted data order:"
echo "${myArr[*]}"
参考:
《高级 Bash 脚本编程指南》
Bash : 冒泡排序的更多相关文章
- shell数组应用
引言 在Linux平台上工作,我们经常需要使用shell来编写一些有用.有意义的脚本程序.有时,会经常使用shell数组.那么,shell中的数组是怎么表现的呢,又是怎么定义的呢?接下来逐一的进行讲解 ...
- shell编程-1到100的求和与冒泡排序
Shell编程 一. for循环 生成列表 {起始数..结束数} 命令生成列表 `seq [起始数] [步进长度] 结束数 ` for l in {1..5};do for l in `seq ...
- python-Day5-深入正则表达式--冒泡排序-时间复杂度 --常用模块学习:自定义模块--random模块:随机验证码--time & datetime模块
正则表达式 语法: mport re #导入模块名 p = re.compile("^[0-9]") #生成要匹配的正则对象 , ^代表从开头匹配,[0 ...
- python开发学习-day05(正则深入、冒泡排序算法、自定义模块、常用标准模块)
s12-20160130-day05 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...
- Python函数的冒泡排序、递归以及装饰器
函数的冒泡排序: 本质是,让元素换位置,逐个比较最终排序. 例1:实现a1,a2值互换: a1 = 123 a2 = 456 temp = a1 a1 = a2 a2 = temp print(a1) ...
- acm之简单博弈 Nim Bash Wythoff
前些日子我打算开了博弈基础,事后想进行总结下 一句话就是分析必胜或必败,异或为0. 以下内容来自转载: Nim游戏的概述: 还记得这个游戏吗?给出n列珍珠,两人轮流取珍珠,每次在某一列中取至少1颗珍珠 ...
- Bash脚本编程之数组
数组简介 在bash脚本编程当中,变量是存储单个元素的内存空间:而数组是存储多个元素的一段连续的内存空间. 数组由数组名和下标构成,如下. ARRAY_NAME[SUBSCRIPT] 数组按照下标的类 ...
- [C#][算法] 用菜鸟的思维学习算法 -- 马桶排序、冒泡排序和快速排序
用菜鸟的思维学习算法 -- 马桶排序.冒泡排序和快速排序 [博主]反骨仔 [来源]http://www.cnblogs.com/liqingwen/p/4994261.html 目录 马桶排序(令人 ...
- 算法与数据结构(十三) 冒泡排序、插入排序、希尔排序、选择排序(Swift3.0版)
本篇博客中的代码实现依然采用Swift3.0来实现.在前几篇博客连续的介绍了关于查找的相关内容, 大约包括线性数据结构的顺序查找.折半查找.插值查找.Fibonacci查找,还包括数结构的二叉排序树以 ...
随机推荐
- 简述 Spring Cloud 是什么2
一.概念定义 Spring Cloud是一个微服务框架,相比Dubbo等RPC框架, Spring Cloud提供的全套的分布式系统解决方案. Spring Cloud对微服务基础框架Ne ...
- 使用wxpy自动发送微信消息
思路整理:1.进入心灵鸡汤网页,使用python获取心灵鸡汤内容 2.登陆微信,找到需要发送的朋友 3.发送获取的内容 1.获取心灵鸡汤的内容 如下图,获取第一条鸡汤 实现如下: 2.登陆微信,搜索朋 ...
- tkinter中lable标签控件(二)
lable控件 对于tkinter来说,学起来很简单,只要设置好相应的参数即可出结果,所以不用刻意去记住这些参数.学习一遍后理解每个参数的作用是什么即可. 当下次用到的时候来笔记上看一下就行. 内容很 ...
- MD5生成
/// <summary> /// 32位MD5加密 /// </summary> /// <param name="input"></p ...
- 两个列表lst1和lst2,计算两个列表的公共元素和非公共元素
方法1: 列表推导式 lst1 = [1, 3, 7] lst2 = [3, 5, 4] a = [x for x in lst1 if x in lst2] b = [y for y in (lst ...
- 在同一个服务器(同一个IP)为不同域名绑定的免费SSL证书
越来越多的浏览器不在支持http协议了,这就要求你为你的网站必须绑定SSL证书.谷歌浏览器也将要在今年取消对http协议的支持,申请CA证书迫在眉睫.我购买有两个域名,一个虚拟机,没事鼓捣鼓捣,图个乐 ...
- DP E - Cheapest Palindrome
Keeping track of all the cows can be a tricky task so Farmer John has installed a system to automate ...
- 解决jqueryeasyUI dialog 弹出窗体超出浏览器,导致不能关闭的bug
使用panel的onMove事件攻克了panel,dialog以及window组件在被拖动时,会超出浏览器边界而无法拖回的情况. 当窗体被拖出浏览器有边界时.$(document).width();会 ...
- Redis本身是单线程线程安全的内存数据库,但是不代表你的使用就是线程安全的
网上一个错误示例:https://www.cnblogs.com/Simeonwu/p/7881100.html,部分代码如下: package com.me.config; import redis ...
- maven 打包生成doc和源码插件
<!--配置生成Javadoc包--> <plugin> <groupId>org.apache.maven.plugins</groupId> < ...