算法-排序

一、冒泡排序

进行 N 趟循环,每趟循环进行相邻两数比较,根据排序的规则交换位置,每趟完成后将极值移至有序区。
时间复杂度:O(N^2)
#include<iostream>
using namespace std;

void bubble_sort(int a[], int size) {
    for (int i = 0; i<size; i++) {
        int flag = 0;
        for (int j = 0; j<size-i; j++) {
            if (a[j]>a[j+1]) {
                int tmp = a[j+1];
                a[j+1] = a[j];
                a[j] = tmp;
                flag++;
            }
        }
        if (flag == 0) {
            break;;
        }
    }
}

int main() {
    int n;
    while (cin >> n) {
        int a[n];
        for(int i = 0; i<n; i++) {
            cin >> a[i];
        }
        bubble_sort(a,n);
        for (int i = 0; i<n; i++) {
            cout << a[i] << " " << endl;
        }
    }
    return 0;
}

二、选择排序

进行 i(0~N-1) 趟循环,每一趟循环将最小的数放到第i个位置,形成有序区。
时间复杂度:O(N^2)

#include<iostream>
using namespace std;

void select_sort(int a[], int size) {
    for (int i = 0; i < size-1; i++) {
        int min_num = i+1;
        for(int j = i; j < size; j++) {
            if (a[j] < a[min_num]) {
                min_num = j;
            }
        }
        int tmp = a[i];
        a[i] = a[min_num];
        a[min_num] = tmp;
    }
}

int main() {
    int n;
    while (cin >> n) {
        int a[n];
        for(int i = 0; i<n; i++) {
            cin >> a[i];
        }
        select_sort(a,n);
        for (int i = 0; i<n; i++) {
            cout << a[i] << " " << endl;
        }
    }
    return 0;
}

三、插入排序

进行 i(0~N-1) 趟循环,每一趟循环将第 i 个位置的数与之前的数进行比较,并排到符合条件的位置,形成有序区。
时间复杂度:O(N^2)
#include<iostream>
using namespace std;

void insertion_sort(int a[], int size) {
    for (int i = 1; i < size; i++) {
        for (int j = i-1; j>=0; j--) {
            int tmp = a[j+1];
            if (a[j+1] < a[j]) {
                a[j+1] = a[j];
                a[j] = tmp;
            }
        }
    }
}

int main() {
    int n;
    while (cin >> n) {
        int a[n];
        for(int i = 0; i<n; i++) {
            cin >> a[i];
        }
        insertion_sort(a,n);
        for (int i = 0; i<n; i++) {
            cout << a[i] << " " << endl;
        }
    }
    return 0;
}

四、快速排序

对于数组选取第一个元素,通过归位将其放入特定位置,然后以该位置为边界将列表分为两部分,递归调用快速排序。
时间复杂度:O(NlogN), 最坏情况下是 O(N^2)
#include<iostream>
using namespace std;
int oh_partition(int a[], int left, int right) {
    int tmp = a[left];
    while (left < right) {
        while (a[right] >= tmp && left < right) {
            right --;
        }
        a[left] = a[right];
        while (a[left] <= tmp && left < right) {
            left ++;
        }
        a[right] = a[left];
    }
    a[left] = tmp;
    return left;
}

void quick_sort(int a[], int left, int right) {
    if (left < right) {
        int mid = oh_partition(a, left, right);
        quick_sort(a, left, mid-1);
        quick_sort(a, mid+1, right);
    }
}

int main() {
    int n;
    while (cin >> n) {
        int a[n];
        for(int i = 0; i<n; i++) {
            cin >> a[i];
        }
        quick_sort(a, 0, n-1);
        for (int i = 0; i<n; i++) {
            cout << a[i] << " " << endl;
        }
    }
    return 0;
}

五、堆排序

二叉堆:近似完全二叉树。
父节点与左子节点的下标关系 i --> 2*i+1;
父节点与右子节点的下标关系 i --> 2*i+2;
大根堆:子节点大于等于父节点,堆中的最大值处于根节点;
小根堆:子节点小于等于父节点,堆中的最小值处于根节点;
推排序算法使用的是大根堆。
1、将数组维护成大根堆的形式
2、交换根节点与最后叶子节点的值,将最后的叶子节点屏蔽在后续的操作,即指定前一位节点为最后的叶子节点
3、继续维护成大根堆直至堆顶
时间复杂度:O(NlogN)
#include<iostream>
using namespace std;
void heapify(int a[], int root, int last) {
    int i = root;
    int tmp = a[root];
    // j 指向左子节点
    int j = i*2+1;
    // 条件:只要 j 有值
    while(j <= last) {
        // 右子节点存在且右子节点大于左子节点
        if (a[j+1] > a[j] && j + 1 < last) {
            j+=1;// j 指向右子节点
        }
        if(a[j] > tmp) {
            a[i] = a[j];
            i = j;//向下一层
            j = i*2+1;
        } else {
            break;
        }
    }
    a[i] = tmp;// 把提出来的tmp 放到空的节点中
}

void heap_sort(int a[], int size) {
    //从最低叶子节点的父节点开始
    for (int i = size/2 - 1; i >=0; i--) {
        heapify(a, i, size - 1);//维护成最大堆
    }
    for (int i = size - 1; i >= 0; i--) {
        //交换根节点的值
        int tmp = a[0];
        a[0] = a[i];
        a[i] = tmp;
        //同时将最后的叶子节点减1,然后维护成最大堆
        heapify(a, 0, i-1);
    }
}

int main() {
    int n;
    while (cin >> n) {
        int a[n];
        for(int i = 0; i<n; i++) {
            cin >> a[i];
        }
        heap_sort(a, n);
        for (int i = 0; i<n; i++) {
            cout << a[i] << " " << endl;
        }
    }
    return 0;
}

六、归并排序

分解待排序的 n 个元素的序列成 n/2 个元素的子序列。
递归排序子序列,合并已排序的子序列以产生整体排序序列。
时间复杂度:O(NlogN)

#include<iostream>
using namespace std;
void oh_merge(int a[], int left, int mid, int right) {
    int len1 = mid - left + 1;
    int len2 = right - mid;
    int L[len1+1];
    int R[len2+1];
    for (int i = 0; i < len1; i++) {
        L[i] = a[left+i];
    }
    L[len1] = INT_MAX;
    for (int i = 0; i < len2; i++) {
        R[i] = a[mid+i+1];
    }
    R[len2] = INT_MAX;
    int i = 0;
    int j = 0;
    int k = left;
    while (k <= right) {
        if (L[i] <= R[j]) {
            a[k] = L[i];
            i++;
        } else {
            a[k] = R[j];
            j++;
        }
        k++;
    }
}

void merge_sort(int a[], int left, int right) {
    if (left < right) {
        int mid = (left + right) / 2;
        merge_sort(a, left, mid);
        merge_sort(a, mid+1, right);
        oh_merge(a, left, mid, right);
    }
}

int main() {
    int n;
    while (cin >> n) {
        int a[n];
        for(int i = 0; i<n; i++) {
            cin >> a[i];
        }
        merge_sort(a, 0, n-1);
        for (int i = 0; i<n; i++) {
            cout << a[i] << " " << endl;
        }
    }
    return 0;
}


七、希尔排序

将序列分为 d = n/2 组,每组的元素为原序列中间隔为 d 的元素。对每组元素进行插入排序。然后将序列分为 d = d/2 组,对每组元素进行插入排序。直到 d 为 1停止。
这里的间隔参数不一定是除 2。
时间复杂度:小于等于 O(N^2)
#include<iostream>
using namespace std;
void insertion_gap(int a[], int size, int gap) {
    for (int i = gap; i < size; i++) {
        for (int j = i-gap; j>=0; j-=gap) {
            int tmp = a[j+gap];
            if (tmp < a[j]) {
                a[j+gap] = a[j];
                a[j] = tmp;
            }
        }
    }
}

void shell_sort(int a[], int size) {
    int d = size / 2;
    while (d >= 1) {
        insertion_gap(a, size, d);
        d/=2;
    }
}

int main() {
    int n;
    while (cin >> n) {
        int a[n];
        for(int i = 0; i<n; i++) {
            cin >> a[i];
        }
        shell_sort(a, n);
        for (int i = 0; i<n; i++) {
            cout << a[i] << " " << endl;
        }
    }
    return 0;
}

八、计数排序

假设 n 个输入元素的每一个都是在 0 到 k 区间内的一个整数。对于每一个输入元素 x,确定小于 x 的元素个数,利用这一属性,就可以将 x 放到它在输出数组的位置上。
时间复杂度:O(N)
#include<iostream>
using namespace std;
void count_sort(int a[], int b[], int size, int k) {
    int c[k+1];
    for (int i = 0; i <= k; i++) {
        c[i] = 0;
    }
    for (int i = 0; i < size; i++) {
        c[a[i]] += 1;
    }
    for (int i = 1; i <= k; i++) {
        c[i] = c[i]+c[i-1];
    }
    for (int i = size - 1; i >= 0; i--) {
        // tmp1 = a[i] 为待排序的值
        // tmp2 = c[tmp1] 为待排序的值前面有多少小于等于它的元素,由此可以得到待排序的值的下标为 tmp2 - 1
        // b[tmp2] = tmp1;
        b[c[a[i]]-1] = a[i];
        // 将 tmp2 减 1,这样后续的遍历中遇到与 tmp1 相同的值,就直接往 tmp2 上放。相同的值总是紧挨着的。
        c[a[i]] -= 1;
    }
}

int main() {
    int n;//输入的序列长度
    int k;//输入的序列中最大的值
    while (cin >> n >> k) {
        int a[n];
        int b[n];
        for(int i = 0; i<n; i++) {
            cin >> a[i];
        }
        count_sort(a, b, n, k);
        for (int i = 0; i<n; i++) {
            cout << b[i] << " " << endl;
        }
    }
    return 0;
}

九、基数排序

基于位数关键字大小比较,将序列分成一定的“桶”,然后对“桶”中的数据进行排序,最后将数据回收回原序列中
时间复杂度:O(k*n)
#include<iostream>
using namespace std;
void radix_Sort(int a[], int size, int max_num) {
    for (int i = 1; max_num / i > 0; i+=10) {
        int buckets[size][10];
        memset(buckets, 0, sizeof(buckets));
        for (int j = 0; j < size; j++) {
            int num = (a[j] / i) % 10;
            buckets[j][num] = a[j];
        }
        int k = 0;
        for (int j = 0; j < 10; j++) {
            for (int s = 0; s < size; s++) {
                if (buckets[s][j] != 0) {
                    a[k++] = buckets[s][j];
                }
            }
        }
    }
}

int main() {
    int n;
    int k;
    while (cin >> n >> k) {
        int a[n];
        for(int i = 0; i<n; i++) {
            cin >> a[i];
        }
        radix_Sort(a, n, k);
        for (int i = 0; i<n; i++) {
            cout << a[i] << " " << endl;
        }
    }
    return 0;
}


全部评论

相关推荐

学java时间比较短不到三个月,基本的技术栈都过了一遍就是都不太深,有个小项目。是继续找实习还是沉淀准备秋招呢?找实习的话会花很多时间在八股,放弃的话又怕秋招简历太难看。有无大佬支招
今天java了吗:1.一定要找实习,实习不一定要去,但是找实习过程中的面试经验和心态经验才是最重要的 2.八股本来就是大头,甚至比项目重要 3.这个时间段也是面试比较多的阶段,可以抓住机会锻炼。面试才会发现自己的不足,感觉自己会了和能给面试官娓娓道来是两码事
点赞 评论 收藏
分享
代码飞升:别用口语,后端就写后端,前端就写前端,最后别光后悔
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务