三种简单排序算法 及其 mathematica 可视化

冒泡排序

算法思想

从未排序记录表的底部开始,依关键字逐次比较、交换相邻记录,将具有最小(大)键值的记录移至未排序记录表的顶部位置,直至记录表完全有序。冒泡排序示意图

代码

void BubbleSort(SqTable &L ) {
    for (i = L.len; i > 1; i--) {
        for (j = 1; j < i; j++) { 
            if (L.r[j+1].key < L.r[j].key) swap(L.r[j], L.r[j+1]); 
            }
        } 
    } //BubbleSort (升序)

算法分析

冒泡排序复杂度分析

算法改进

我们可以判断序列是否有序,避免多余的比较。

void BubbleSortII(int a[], int n){
    for (i=n-1,change=TRUE; i>0&&change; --i) { 
        change = FALSE; 
        for (j=0; j a[j+1]) {  
            swap(a[j],a[j+1]);  
            change = TRUE;  
            } 
        } 
}//BubbleSortII

稳定度分析

可以想到,由于冒泡排序的每次交换都发生在相邻元素间,所以相等的两个元素的相对位置必然不会发生改变。

故,冒泡排序是稳定的。

可视化

a = RandomSample@Range[15]; len = Length[a];
res = {};
Do[Do[If[a[[j]] > 
    a[[j + 1]], ({{a[[j]], a[[j + 1]]}}) = ({{a[[j + 1]], a[[j]]}}); 
   AppendTo[res, a]], {j, 1, len - i}], {i, 1, len - 1}]; ListAnimate[
 BarChart[#, ChartStyle -> "Pastel", 
    ChartLegends -> ToString /@ #] & /@ res]

冒泡排序可视化

选择排序

算法思想

依关键字在未排序记录表中查找记录,选择具有最小(大)键值的 记录并与未排序记录表的首元素交换放置,直至记录表完全有序。
选择排序示意图

代码

void SelectSort (SqTable &L) {
    for (i=1; i<L.len; ++i) { 
        lowIndex = i; //最小记录索引位置
        for (k=i+1; k<=L.len; k++ ) 
            if ( L.r[k].key < L.r[lowIndex].key ) 
                lowIndex =k;
        swap(L.r[i], L.r[lowIndex]); //交换记录
        }
    } //SelectSort

算法分析

选择排序复杂度分析

稳定度分析

在移动最小/大键值的元素时,相等元素的相对位置可能改变,故选择排序是不稳定的。
反例

可视化

mma代码

选择排序GIF

插入排序

算法思想

从未排序记录表中逐次选取一个记录,依关键字将其与已排序子序列进行比较并插入至正确位置,直至记录表完全有序。插入排序示意图

代码

/*对顺序表L作插入排序*/
void InsertSort (SqTable &L) {
    for ( i=2; i<=L.len; ++i )
        if ( L.r[i].key < L.r[i-1].key ){
            L.r[0] = L.r[i]; // 复制为哨兵
            for ( j=i-1; L.r[0].key<L.r[j].key; --j )
                L.r[j+1] = L.r[j]; // 记录后移
            L.r[j+1] = L.r[0]; // 插入到正确位置
        }
    } //InsertSort升序

稳定度分析

每次将一个元素插入已经排序好的序列中,相等的元素仍然按照初始时的先后顺序排列,相对位置没有发生改变。

故插入排序是稳定的。

算法分析

插入排序复杂度分析

可视化

mma代码
插入排序GIF

小结

三种排序算法复杂度比较

三者中,只有选择排序是不稳定的。

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值