冒泡排序的另一种写法

冒泡排序的另一种写法

冒泡排序虽然效率不高,但胜在容易理解,所以流传还是比较广泛,当年学校里数据结构这门课教的排序法就是冒泡排序。
冒泡排序的逻辑,冒泡排序的两种优化逻辑,网上都已有很多资料,这里就不重复说明,下面会直接给出代码。
这里想说的是另外一种冒泡排序逻辑:
1、把待排序队列分为前后两个子队列。初始状态下,待排序队列的第1个元素组成前子队列,剩下的元素组成后子队列。
2、这时,因为前子队列只有一个元素,所以可视为是有序的。
3、然后循环从后子队列中取与一个元素,插入到前子队列的合适位置,保持前子队列有序。
4、如此循环,直到后子队列的所有元素都插入到前子队列,完成排序。
很有意思的是,测试发现这种冒泡法与优化后的传统冒泡法,对相同队列排序所需的循环次数是一模一样的。看下面的代码(Go语言):

package main

import (
    "fmt"
    "math/rand"
    "time"
)

var (
    countB  = 0
    countB2 = 0
)

// 检查是否排序成功
func CheckSortedResult(list []int) (bool, int) {
    for i := 1; i < len(list); i++ {
        if list[i-1] > list[i] {
            return false, i
        }
    }
    return true, -1
}

//=====================================================
//优化后的冒泡排序法
func BubbleSort(list []int) {
    var iLen, iHead, iPoint, iMark int
    iLen = len(list)
    for iHead = 0; iHead < iLen-1; iHead++ {
        iMark = iLen
        for iPoint = iLen - 1; iPoint > iHead; iPoint-- {
            if list[iPoint-1] > list[iPoint] {
                list[iPoint-1], list[iPoint] = list[iPoint], list[iPoint-1]
                iMark = iPoint - 1 // 每当发生交换,记录最后发生交换的位置
                countB++
            }
        }
        if iMark == iLen { // 改进:当未发生过交换,说明整个列表已排好序
            break
        }
        if iMark > iHead+1 { // 改进2:当从某个位置到iHead位置都未发生交换,说明这一段已排好序,可以跳过
            iHead = iMark
        }
    }
}

// 另一种冒泡排序法
func BubbleSort2(list []int) {
    iLen := len(list)
    for i := 1; i < iLen; i++ {
        for j := i; j > 0; j-- {
            if list[j-1] > list[j] {
                list[j-1], list[j] = list[j], list[j-1]
                countB2++
            } else {
                break
            }
        }

    }
}

func main() {
    times := int64(time.Now().Nanosecond())
    rand.Seed(times)
    list := make([]int, 50)

    for i := 0; i < 49; i++ {
        list[i] = rand.Intn(100)
    }
    list2 := list[:]
    list2 = append(list, 51)
    list = append(list, 51)

    fmt.Printf("list: %v\n", list)
    BubbleSort(list)
    if ok, index := CheckSortedResult(list); !ok {
        fmt.Printf("Sort fail at: %d\n", index)
    }
    fmt.Printf("list: %v\n", list)
    fmt.Printf("BubbleSort run(%d)\n", countB)

    fmt.Printf("list2: %v\n", list2)
    BubbleSort2(list2)
    if ok, index := CheckSortedResult(list2); !ok {
        fmt.Printf("Sort fail at: %d\n", index)
    }
    fmt.Printf("list2: %v\n", list2)
    fmt.Printf("BubbleSort2 run(%d)\n", countB2)
}

输出结果:

> Output:
command-line-arguments
list: [32 91 38 20 8 76 2 38 52 20 4 31 29 50 52 60 22 43 16 94 67 41 30 85 55 18 99 22 33 14 5 4 99 45 52 34 7 90 52 83 80 50 81 13 2 35 17 77 77 0 51]
list: [0 2 2 4 4 5 7 8 13 14 16 17 18 20 20 22 22 29 30 31 32 33 34 35 38 38 41 43 45 50 50 51 52 52 52 52 55 60 67 76 77 77 80 81 83 85 90 91 94 99 99]
BubbleSort run(605)
list2: [32 91 38 20 8 76 2 38 52 20 4 31 29 50 52 60 22 43 16 94 67 41 30 85 55 18 99 22 33 14 5 4 99 45 52 34 7 90 52 83 80 50 81 13 2 35 17 77 77 0 51]
list2: [0 2 2 4 4 5 7 8 13 14 16 17 18 20 20 22 22 29 30 31 32 33 34 35 38 38 41 43 45 50 50 51 52 52 52 52 55 60 67 76 77 77 80 81 83 85 90 91 94 99 99]
BubbleSort2 run(605)
> Elapsed: 2.096s
> Result: Success
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值