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查找,还包括数结构的二叉排序树以 ...
随机推荐
- 自己搭建anki同步服务器
最近帮孩子找学习的软件,发现了anki 不过同步速度太慢,但发现可以自己搭建同步服务器 具体方法见https://github.com/dsnopek/anki-sync-server 我的安装过程如 ...
- EntityFramework Code-First 简易教程(十)-------多对多
配置Many-to-Many(多对多)关系: 这里有两个类,Student和Course,一个Student可以有多个Course,一个Course也可以有多个Student,所以这就成了多对多关系. ...
- Nginx日志格式log_format详解
PS:Nginx日志相关指令主要有两条,一条是log_format,用来设置日志格式,另外一条是access_log,用来指定日志文件的存放路径.类型.缓存大小等,一般放在Nginx的默认主配置文件/ ...
- 请问在EXECUTE IMMEDIATE中如何使用带有引号
转自:http://bbs.csdn.net/topics/300191423 从第一引号向后,如果遇到第二个引号,则看这个引号后面时候有紧挨着的引号,如果有则第二个引号被转义,即该保留该引号后面紧跟 ...
- Alpha版本 - 测试报告
Alpha版本 - 测试报告 总体测试计划 前端 模块 子模块 测试项 预期结果 测试工具 执行人 登录/注册模块 无网络 提示无网异常 robolectric 陈龙江 登录 输入用户名/密码为空,点 ...
- webpack 开发环境与生成环境的 配置
写在前面 最近学习react,之前做vue项目的时候,一直都是拿来主义,浑浑噩噩,感觉不太好,趁学习react的机会,在顺带学习一下webpack.一般配置文件分两份,为开发环境和生成环境.有此区分, ...
- oracle dataguard主从切换
前言: 众所周知DataGuard一般的切换分成两种,一种是系统正常的情况下的切换这种方式为:switchover是无损切换,不会丢失数据:另外一种方式属于灾难情况下的切换,这种情况下一般主库已经启动 ...
- mybatis基础系列(四)——关联查询、延迟加载、一级缓存与二级缓存
关本文是Mybatis基础系列的第四篇文章,点击下面链接可以查看前面的文章: mybatis基础系列(三)——动态sql mybatis基础系列(二)——基础语法.别名.输入映射.输出映射 mybat ...
- 【Codeforces 1114F】Please, another Queries on Array?
Codeforces 1114 F 题意:给你一个序列\(a_{1\dots n}\),以及\(q\)次查询,每次查询有两种格式: TOTIENT \(l\) \(r\):求出\(\phi(\Pi_{ ...
- ubuntu 系统查看opencv 的版本
有很多的时候 ,我们想知道自己的电脑里面安装的opencv版本是多少 在终端中运行下面的命令. pkg-config --modversion opencv 为什么要知道自己电脑的opencv 版本, ...