排序-交换排序-冒泡排序

冒泡排序

冒泡排序是一种最简单的交换排序方法,它通过两两比较相邻记录的关键字,如果发生逆序,则进行交换, 从而使用关键字小的记录如气泡一般逐渐往上“漂浮”(左移),或者使关键字大的记录如石块一样逐渐“堕落”(右移)。

算法思路

[算法步骤]

① 设待排序的记录存在数组r[1…n]中。首先将第一个记录的关键字和和第二个记录的关键字进行比较,若为逆序(既L.elem[1].key>L.elem[2].key),则交换两个记录。然后比较第二个记录和第三个记录的关键字。依次类推,直到第n-1个记录和第n个记录的关键字进行过比较为止。
上述过程成为第一趟起冒泡排序,其结果使得关键字最大的记录被安置到最后一个记录的位置上。
② 然后进行第二趟起冒泡排序,对前n-1个记录进行同样的操作,其结果是使得关键字次大的记录被安置到第n-1个纪律的位置上。
③ 重复上述比较和交换过程,第i趟是从L.elem[1]到l.elem[n-i+1]依次比较相邻两个记录的关键字,并在“逆序”时交换相邻记录,其结果是着n-i+1个记录中关键字最大的记录被交换到n-i+1的位置上。
直到在某一趟排序过程中没有进行交换记录的操作,说明序列已全部达到排序要求。

算法实现

定义存放记录的线性表结构

 //记录
 typedef struct ElemType{
    
    
     int key;
     string info;
 }ElemType;

#define Maxsize 50
 typedef struct {
    
    
     ElemType elem[Maxsize];
     int length;
 }SqList;
 
/**
 * 对顺序表L进行降序 冒泡排序
 */
void BubbleSort(SqList &L);
/**
 * 对顺序表L进行升序 冒泡排序
 */
void Bubble_Sort(SqList &L);

void toString(SqList L);

void InitSqList(SqList &L);

void swap(ElemType &a, ElemType &b);

升序核心实现

void Bubble_Sort(SqList &L) {
    
    
    int n = L.length;
    for (int i = 0; i < n-1; i++) {
    
    
        cout << " -------------------------进行 i = " << i << " 趟排序------------------------------------------------- " << endl;
        bool flag = false;  //表示本趟冒泡是否发生的标志
        for (int j = n - 1; j > i; j--) {
    
     //一趟冒泡过程
            cout << " j = " << j;
            if (L.elem[j - 1].key > L.elem[j].key) {
    
     //若为逆序
                swap(L.elem[j - 1], L.elem[j]); //交换
                flag = true;
                cout << " 交换: " << j-1 << "," << j;
            }
            cout << endl;
            toString(L);
            if (!flag) {
    
    
                return; //若本趟遍历后没有发生交换,说明已经达到排序要求。
            }
        }
    }
}

降序核心实现

void BubbleSort(SqList &L) {
    
    
    int m = L.length - 1;
    bool flag = true; //flag 用来记录某一趟排序是否发生交换
    while ((m > 0) && flag) {
    
    
        cout << " -------------------------剩余 m = " << m << "躺排序------------------------------------------------- " << endl;
        flag = false; //置为false 如果本趟没有发生交换,则不会指向下一趟排序
        for (int j = 0; j < m; j++) {
    
    
            cout << " j = " << j;
            if (L.elem[j].key < L.elem[j + 1].key) {
    
    
                flag = true; //本趟发生了交换
                swap(L.elem[j], L.elem[j + 1]);  //交换
                cout << " 交换: " << j << "," << j + 1;
            }
            cout << endl;
            toString(L);
        }
        m--;
    }
}

测试案例

void testBubbleSort() {
    
    
    SqList L;
    InitSqList(L);
    cout <<" ----------------------------------初始 L---------------------------------------- "<< endl;
    toString(L);
    BubbleSort(L);
    cout <<" ----------------------------------降序冒泡L---------------------------------------- "<< endl;
    toString(L);
    Bubble_Sort(L);
    cout <<" ----------------------------------升序冒泡L---------------------------------------- "<< endl;
    toString(L);
}

int main() {
    
    
    testBubbleSort();
    return 0;
}

测试结果

 ----------------------------------初始 L---------------------------------------- 
L.key  [ 41 67 34 0 69 24 78 58 62 64 ]
 -------------------------剩余 m = 9躺排序------------------------------------------------- 
 j = 0 交换: 0,1
L.key  [ 67 41 34 0 69 24 78 58 62 64 ]
 j = 1
L.key  [ 67 41 34 0 69 24 78 58 62 64 ]
 j = 2
L.key  [ 67 41 34 0 69 24 78 58 62 64 ]
 j = 3 交换: 3,4
L.key  [ 67 41 34 69 0 24 78 58 62 64 ]
 j = 4 交换: 4,5
L.key  [ 67 41 34 69 24 0 78 58 62 64 ]
 j = 5 交换: 5,6
L.key  [ 67 41 34 69 24 78 0 58 62 64 ]
 j = 6 交换: 6,7
L.key  [ 67 41 34 69 24 78 58 0 62 64 ]
 j = 7 交换: 7,8
L.key  [ 67 41 34 69 24 78 58 62 0 64 ]
 j = 8 交换: 8,9
L.key  [ 67 41 34 69 24 78 58 62 64 0 ]
 -------------------------剩余 m = 8躺排序------------------------------------------------- 
 j = 0
L.key  [ 67 41 34 69 24 78 58 62 64 0 ]
 j = 1
L.key  [ 67 41 34 69 24 78 58 62 64 0 ]
 j = 2 交换: 2,3
L.key  [ 67 41 69 34 24 78 58 62 64 0 ]
 j = 3
L.key  [ 67 41 69 34 24 78 58 62 64 0 ]
 j = 4 交换: 4,5
L.key  [ 67 41 69 34 78 24 58 62 64 0 ]
 j = 5 交换: 5,6
L.key  [ 67 41 69 34 78 58 24 62 64 0 ]
 j = 6 交换: 6,7
L.key  [ 67 41 69 34 78 58 62 24 64 0 ]
 j = 7 交换: 7,8
L.key  [ 67 41 69 34 78 58 62 64 24 0 ]
 -------------------------剩余 m = 7躺排序------------------------------------------------- 
 j = 0
L.key  [ 67 41 69 34 78 58 62 64 24 0 ]
 j = 1 交换: 1,2
L.key  [ 67 69 41 34 78 58 62 64 24 0 ]
 j = 2
L.key  [ 67 69 41 34 78 58 62 64 24 0 ]
 j = 3 交换: 3,4
L.key  [ 67 69 41 78 34 58 62 64 24 0 ]
 j = 4 交换: 4,5
L.key  [ 67 69 41 78 58 34 62 64 24 0 ]
 j = 5 交换: 5,6
L.key  [ 67 69 41 78 58 62 34 64 24 0 ]
 j = 6 交换: 6,7
L.key  [ 67 69 41 78 58 62 64 34 24 0 ]
 -------------------------剩余 m = 6躺排序------------------------------------------------- 
 j = 0 交换: 0,1
L.key  [ 69 67 41 78 58 62 64 34 24 0 ]
 j = 1
L.key  [ 69 67 41 78 58 62 64 34 24 0 ]
 j = 2 交换: 2,3
L.key  [ 69 67 78 41 58 62 64 34 24 0 ]
 j = 3 交换: 3,4
L.key  [ 69 67 78 58 41 62 64 34 24 0 ]
 j = 4 交换: 4,5
L.key  [ 69 67 78 58 62 41 64 34 24 0 ]
 j = 5 交换: 5,6
L.key  [ 69 67 78 58 62 64 41 34 24 0 ]
 -------------------------剩余 m = 5躺排序------------------------------------------------- 
 j = 0
L.key  [ 69 67 78 58 62 64 41 34 24 0 ]
 j = 1 交换: 1,2
L.key  [ 69 78 67 58 62 64 41 34 24 0 ]
 j = 2
L.key  [ 69 78 67 58 62 64 41 34 24 0 ]
 j = 3 交换: 3,4
L.key  [ 69 78 67 62 58 64 41 34 24 0 ]
 j = 4 交换: 4,5
L.key  [ 69 78 67 62 64 58 41 34 24 0 ]
 -------------------------剩余 m = 4躺排序------------------------------------------------- 
 j = 0 交换: 0,1
L.key  [ 78 69 67 62 64 58 41 34 24 0 ]
 j = 1
L.key  [ 78 69 67 62 64 58 41 34 24 0 ]
 j = 2
L.key  [ 78 69 67 62 64 58 41 34 24 0 ]
 j = 3 交换: 3,4
L.key  [ 78 69 67 64 62 58 41 34 24 0 ]
 -------------------------剩余 m = 3躺排序------------------------------------------------- 
 j = 0
L.key  [ 78 69 67 64 62 58 41 34 24 0 ]
 j = 1
L.key  [ 78 69 67 64 62 58 41 34 24 0 ]
 j = 2
L.key  [ 78 69 67 64 62 58 41 34 24 0 ]
 ----------------------------------降序冒泡L---------------------------------------- 
L.key  [ 78 69 67 64 62 58 41 34 24 0 ]
 -------------------------进行 i = 0 趟排序------------------------------------------------- 
 j = 9 交换: 8,9
L.key  [ 78 69 67 64 62 58 41 34 0 24 ]
 j = 8 交换: 7,8
L.key  [ 78 69 67 64 62 58 41 0 34 24 ]
 j = 7 交换: 6,7
L.key  [ 78 69 67 64 62 58 0 41 34 24 ]
 j = 6 交换: 5,6
L.key  [ 78 69 67 64 62 0 58 41 34 24 ]
 j = 5 交换: 4,5
L.key  [ 78 69 67 64 0 62 58 41 34 24 ]
 j = 4 交换: 3,4
L.key  [ 78 69 67 0 64 62 58 41 34 24 ]
 j = 3 交换: 2,3
L.key  [ 78 69 0 67 64 62 58 41 34 24 ]
 j = 2 交换: 1,2
L.key  [ 78 0 69 67 64 62 58 41 34 24 ]
 j = 1 交换: 0,1
L.key  [ 0 78 69 67 64 62 58 41 34 24 ]
 -------------------------进行 i = 1 趟排序------------------------------------------------- 
 j = 9 交换: 8,9
L.key  [ 0 78 69 67 64 62 58 41 24 34 ]
 j = 8 交换: 7,8
L.key  [ 0 78 69 67 64 62 58 24 41 34 ]
 j = 7 交换: 6,7
L.key  [ 0 78 69 67 64 62 24 58 41 34 ]
 j = 6 交换: 5,6
L.key  [ 0 78 69 67 64 24 62 58 41 34 ]
 j = 5 交换: 4,5
L.key  [ 0 78 69 67 24 64 62 58 41 34 ]
 j = 4 交换: 3,4
L.key  [ 0 78 69 24 67 64 62 58 41 34 ]
 j = 3 交换: 2,3
L.key  [ 0 78 24 69 67 64 62 58 41 34 ]
 j = 2 交换: 1,2
L.key  [ 0 24 78 69 67 64 62 58 41 34 ]
 -------------------------进行 i = 2 趟排序------------------------------------------------- 
 j = 9 交换: 8,9
L.key  [ 0 24 78 69 67 64 62 58 34 41 ]
 j = 8 交换: 7,8
L.key  [ 0 24 78 69 67 64 62 34 58 41 ]
 j = 7 交换: 6,7
L.key  [ 0 24 78 69 67 64 34 62 58 41 ]
 j = 6 交换: 5,6
L.key  [ 0 24 78 69 67 34 64 62 58 41 ]
 j = 5 交换: 4,5
L.key  [ 0 24 78 69 34 67 64 62 58 41 ]
 j = 4 交换: 3,4
L.key  [ 0 24 78 34 69 67 64 62 58 41 ]
 j = 3 交换: 2,3
L.key  [ 0 24 34 78 69 67 64 62 58 41 ]
 -------------------------进行 i = 3 趟排序------------------------------------------------- 
 j = 9 交换: 8,9
L.key  [ 0 24 34 78 69 67 64 62 41 58 ]
 j = 8 交换: 7,8
L.key  [ 0 24 34 78 69 67 64 41 62 58 ]
 j = 7 交换: 6,7
L.key  [ 0 24 34 78 69 67 41 64 62 58 ]
 j = 6 交换: 5,6
L.key  [ 0 24 34 78 69 41 67 64 62 58 ]
 j = 5 交换: 4,5
L.key  [ 0 24 34 78 41 69 67 64 62 58 ]
 j = 4 交换: 3,4
L.key  [ 0 24 34 41 78 69 67 64 62 58 ]
 -------------------------进行 i = 4 趟排序------------------------------------------------- 
 j = 9 交换: 8,9
L.key  [ 0 24 34 41 78 69 67 64 58 62 ]
 j = 8 交换: 7,8
L.key  [ 0 24 34 41 78 69 67 58 64 62 ]
 j = 7 交换: 6,7
L.key  [ 0 24 34 41 78 69 58 67 64 62 ]
 j = 6 交换: 5,6
L.key  [ 0 24 34 41 78 58 69 67 64 62 ]
 j = 5 交换: 4,5
L.key  [ 0 24 34 41 58 78 69 67 64 62 ]
 -------------------------进行 i = 5 趟排序------------------------------------------------- 
 j = 9 交换: 8,9
L.key  [ 0 24 34 41 58 78 69 67 62 64 ]
 j = 8 交换: 7,8
L.key  [ 0 24 34 41 58 78 69 62 67 64 ]
 j = 7 交换: 6,7
L.key  [ 0 24 34 41 58 78 62 69 67 64 ]
 j = 6 交换: 5,6
L.key  [ 0 24 34 41 58 62 78 69 67 64 ]
 -------------------------进行 i = 6 趟排序------------------------------------------------- 
 j = 9 交换: 8,9
L.key  [ 0 24 34 41 58 62 78 69 64 67 ]
 j = 8 交换: 7,8
L.key  [ 0 24 34 41 58 62 78 64 69 67 ]
 j = 7 交换: 6,7
L.key  [ 0 24 34 41 58 62 64 78 69 67 ]
 -------------------------进行 i = 7 趟排序------------------------------------------------- 
 j = 9 交换: 8,9
L.key  [ 0 24 34 41 58 62 64 78 67 69 ]
 j = 8 交换: 7,8
L.key  [ 0 24 34 41 58 62 64 67 78 69 ]
 -------------------------进行 i = 8 趟排序------------------------------------------------- 
 j = 9 交换: 8,9
L.key  [ 0 24 34 41 58 62 64 67 69 78 ]
 ----------------------------------升序冒泡L---------------------------------------- 
L.key  [ 0 24 34 41 58 62 64 67 69 78 ]

进程已结束,退出代码0

算法分析

① 时间复杂度:

  • 最好情况:初始正序,进行一趟排序,在排序过程中进行n-1次关键字对比,且不移动记录。
  • 最坏情况:初始逆序,进行n-1趟排序,总的关键字对比次数KCN和记录移动次数RMN(每次交换都需要移动3次记录)分别为:
    (n-1)+(n-2)+…(3-1)+(2-1) = n ( n − 1 ) 2 \frac{n(n-1)}{2} 2n(n1)
    KCN ≈ n 2 2 \frac{n^2}{2} 2n2
    3[(n-1)+(n-2)+…(3-1)+(2-1)] = 3 [ n ( n − 1 ) 2 ] 3[\frac{n(n-1)}{2}] 3[2n(n1)]
    RMN ≈ 3 n 2 2 3 \frac{n^2}{2} 32n2
    时间复杂度O(n^2)

② 空间复杂度
冒泡排序只有在两个记录交换位置时,才需要一个辅助空间用作暂存记录,所以空间复杂度为O(1).

[算法特点]

① 稳定排序
② 可用于链式存储结构
③ 移动记录次数比较多,算法平均时间性能比直接插入排序差。当初始记录无序,n比较大时,此算法不宜采用。

猜你喜欢

转载自blog.csdn.net/QQ657205470/article/details/127738548