初等排序(选择、冒泡、插入、稳定性)

参考教材来自《挑战程序设计竞赛2》

0x01选择排序

思路:

输入的一串无序数字中,在第一次排序前,整个数组都是未排序状态,找出未排序部分最小的值的位置,与第一个值的位置交换(如果就是第一个最小则不换,后面的思路也是一样),本次交换后,第一个数是已排序部分,后面是未排序部分,然后再找未排序部分的第一个数(就是整个数组的第二个),再找到未排序部分的最小数位置交换位置,已排序部分加一……一直循环

#include<bits/stdc++.h>
using namespace std;
int selectionSort(int a[], int  n) {
    int i, j, t, sw = 0, minj;
    for(i = 0; i < n; i++) {
        minj = i;
        for(j = i; j < n; j++) {
            if(a[j] < a[minj])
                minj = j;
        }
        t = a[i];
        a[i] = a[minj];
        a[minj] = t;
        if(i != minj)
            sw++;
    }
    return sw;
}
int main () {
    int a[100], n, i, sw;
    cin >> n;
    for(i = 0; i < n; i++) {
        cin >> a[i];
    }
    sw = selectionSort(a, n);
    for(i = 0; i < n; i++) {
        if(i > 0) cout << " ";
        cout << a[i];
    }
    cout << endl;
    cout << sw << endl;
    return 0;
}
/*
in:
6
5 6 4 2 1 3

out:
1 2 3 4 5 6
4





*/

0x02 冒泡排序

这个太简单了....谭浩强的书上讲得很详细,直接上代码了

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6;
int a[maxn];
int main () {
    int n;
    cin >> n;
    for(int i = 0; i < n; i++) {
        cin >> a[i];
    }
    for(int i = 0; i < n - 1; i++) {
        for(int j = 0; j < n - i - 1; j++)
            if(a[j] > a[j + 1]) {
                int t = a[j];
                a[j] = a[j + 1];
                a[j + 1] = t;
            }
    }
    for(int i = 0; i < n; i++) {
        cout << a[i] << " ";
    }
    cout << endl;
    return 0;
}

 

0x03 插入排序

思路:

书上举的例子很好,就像是给扑克牌排序一样,第二个数跟第一个数比较大小,如果第二个小就交换位置,第三个数和第一个数比较,如果a[2](第三个) < a[0]则插入到第一个位置,如果a[1] > a[2] > a[0],则插入第二个位置,以此类推

#include<bits/stdc++.h>
using namespace std;
void print(int a[], int n) {
    int i;
    for(i = 0; i < n; i++) {
        cout << a[i];
        if(i >= 0)
            cout << " ";
    }
    cout << endl;
}
void insertionsort(int a[], int n) {
    int j, i,v;
    for(i = 1; i < n; i++) {
        v = a[i];
        j = i - 1;
        while(j >= 0 && a[j] > v) {
            a[j + 1] = a[j];
            j--;
        }
        a[j + 1] = v;
        print(a, n);
    }
}
int main () {
    int n;
    int a[100];
    cin >> n;
    for(int i = 0; i < n; i++) {
        cin >> a[i];
    }
    print (a, n);
    insertionsort(a, n);
    return 0;
}
/*
in:
6
5 2 4 6 1 3

out:
5 2 4 6 1 3
2 5 4 6 1 3
2 4 5 6 1 3
2 4 5 6 1 3
1 2 4 5 6 3
1 2 3 4 5 6














*/

 

0x04 稳定性

稳定性是判断当有多个数字相同时,他们的前后顺序是否发生改变,若没有改变则是稳定的,反之则为不稳定,由此得知,冒泡排序是一种稳定排序,书上的例子是给所有的数字前加上字母表示扑克牌的花色和数字,由此来判断两个相同的数的前后顺序是否改变,用稳定排序的结果和冒泡排序的结果比较来判断这个排序是否稳定

 

#include<bits/stdc++.h>
using namespace std;
struct Card {
    char suit, value;
};
void bubble (struct Card a[], int n) {
    for(int i = 0; i < n; i++)
        for(int j = n - 1; j >= i + 1; j--)
            if(a[j].value < a[j - 1].value) {
                Card t = a[j];
                a[j] = a[j - 1];
                a[j - 1] = t;
            }
}

void insertionsort (struct Card a[], int n) {
    for(int i = 0; i < n; i++) {
        int minj = i;
        for(int j = i; j < n; j++) {
            if(a[j].value < a[minj].value)
                minj = j;
        }
        Card t = a[i];
        a[i] = a[minj];
        a[minj] = t;
    }
}

void print(struct Card a[], int n) {
    for(int i = 0; i < n; i++) {
        if(i >0)
            cout << " ";
        cout << a[i].suit << a[i].value;
    }
    cout << endl;
}
bool isStable(struct Card c1[],struct Card c2[], int n) {
    for(int i = 0; i < n; i++) {
        if(c1[i].suit != c2[i].suit)
            return false;
    }
    return true;
}
int main () {
    struct Card c1[100], c2[100];
    int n;
    cin >> n;
    for(int i = 0; i < n; i++) {
        cin >> c1[i].suit >> c1[i].value;
        c2[i] = c1[i];
    }
    bubble(c1, n);
    insertionsort(c2, n);
    print(c1, n);
    cout << "Stable" << endl;
    print(c2, n);
    if(isStable(c1, c2, n)) {
        cout << "Stabel" << endl;
    }
    else cout << "Not stable" << endl;
    return 0;
}
/*
in:
5
H4 C9 S4 D2 C3

out:
D2 C3 H4 S4 C9
Stable
D2 C3 S4 H4 C9
Not stable











*/

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值