バブルソート
バブル ソートは、最も単純な交換ソート方法です。隣接するレコードのキーワードをペアごとに比較します。順序が逆になると交換され、小さなキーワードを含むレコードがバブルのように徐々に上に「浮いて」いきます ( (左シフト)、または大きなキーワードを含むレコードを石のように徐々に「落下」させます (右にシフト)。
アルゴリズムのアイデア
【アルゴリズムステップ】
① ソート対象のレコードが配列 r[1...n] に格納されているとします。まず、1 番目のレコードのキーの合計と 2 番目のレコードのキーワードを比較し、順序が逆 (つまり、L.elem[1].key > L.elem[2].key) の場合は、キーの合計を交換します。 2枚のレコードです。次に、2 番目のレコードと 3 番目のレコードのキーワードを比較します。以降、n-1 番目のレコードと n 番目のレコードのキーワードが比較されるまで続きます。
以上の処理がバブルソートの1パス目となり、キーワードが最も大きいレコードが最終レコードの位置に配置されることになります。
② 次に 2 回目のバブルソートを実行し、最初の n-1 レコードに対して同じ操作を実行すると、2 番目に大きいキーワードを持つレコードが n-1 番目の分野の位置に配置されます。
③ 上記の比較・交換処理を繰り返す i 回目では、L.elem[1] から l.elem[n-i+1] までの隣接する 2 つのレコードのキーワードを比較し、隣接するレコードを「逆順」に交換します。 「order」レコードの場合、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
アルゴリズムの分析
① 時間計算量:
- 最良のケース: 最初の正の順序、1 回の並べ替え、並べ替えプロセス中に 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 ( n − 1 )
工業団地 ≈ 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 ( n − 1 )]
RMN ≈3 n 2 2 3 \frac{n^2}{2}32n2
時間計算量 O(n^2)② スペース複雑さ:
バブル ソートでは、2 つのレコードの位置が交換されるときに一時レコード用の補助スペースのみが必要となるため、スペース複雑さは O(1) です。
【アルゴリズムの特徴】
① 安定したソート
② 連鎖ストレージ構造に使用可能
③ 移動するレコード数が比較的多く、アルゴリズムの平均時間パフォーマンスは直接挿入ソートよりも劣ります。最初のレコードの順序が正しくなく、n が比較的大きい場合、このアルゴリズムは使用すべきではありません。