常用排序算法总结(c++版)

3 篇文章 0 订阅
1 篇文章 0 订阅

排序算法的空间时间复杂度如下:
在这里插入图片描述

冒泡排序

S1:从待排序序列的末尾位置开始,从后往前依次比较各个位置和其后一位置的大小并执行S2。
S2:如果当前位置的值小于其前一位置的值,就把他俩的值交换(完成一次全序列比较后,序列最开始位置的值即此序列最小值,所以其不需要再参与冒泡)。
S3:将序列的第一个元素从待排序序列中移除。若移除后的待排序序列不为空则继续执行S1,否则冒泡结束。
在这里插入图片描述

class BubbleSort {
public:
    int* bubbleSort(int* A, int n) {
        // write code here
        int temp;
        for(int i = 0; i < n-1; i++){
            for(int j = n-1; j > i; j--){
                if(A[j]<A[j-1]){
                    temp = A[j];
                    A[j] = A[j-1];
                    A[j-1] = temp;
                }
            }
        }
        return A;
        
    }
};

选择排序

选择排序的思路如下:
s1: 从待排序序列的首位开始,从前往后依次比较各个位置和其后一位置的大小,选出一个最小值。
s2:将该最小值与首位交换,将序列的首位指针向后移动一位,此时下次遍历的序列范围为 1~n-1,重复s1 。
s3:若序列的首位指针移动到序列的最后一位,排序结束
黄色范围为排好序的序列,蓝色为序列中与最小值交换的位置

class SelectionSort {
public:
    int* selectionSort(int* A, int n) {
        // write code here
        for(int i=0; i < n; i++){
            int min = INT_MAX;//无限大
            int index = 0;
            for(int j = i; j < n; j++){
                if(A[j]<min){
                    min= A[j];
                    index = j;
                }
            }
            swap(A[i], A[index]);
        }
        return A;
    }
};

插入排序

插入排序思路:
S1 首先将位置i上的数和前面的数进行比较,将小的数插入最前面
S2 i向后移动一位,重复s1,将i插入到前面有序数组的合适位置
S3 当i=n时,排序结束
黄色为排好序的区域

class InsertionSort {
public:
    int* insertionSort(int* A, int n) {
        // write code here
        for(int i=1;i<n;i++)//从第二个开始
        {
            int index=i;
            for(int j=i-1;j>=0;j--){
                if(A[index]<A[j]){
                    int temp=A[index];
                    A[index]=A[j];
                    A[j]=temp;
                    index=j;
                }
            }
        }
        return A;
    }
};

归并排序

归并排序思路:
S1:现将数组归并为长度为1的有序区间
在这里插入图片描述
S2:将数组归并为长度为1x2的有序区间并进行排序
在这里插入图片描述
在这里插入图片描述
S3:将数组归并为长度为2x2=4的有序区间并排序
在这里插入图片描述
S4:当归并长度为数组长度时停止排序
在这里插入图片描述

class MergeSort {
public:
    int* mergeSort(int* A, int n) {
        // write code here
        process(A, 0, n-1);
        return A;
    }
    void process(int* A, int left, int right){
        if(left == right) return;
        int mid = (left+right)/2;
        process(A, left, mid);
        process(A, mid+1, right);
        merge(A, left, mid, right);
    }
    //合并过程,分别将要合并的两个有序序列第一个元素进行比较,将最小的元素放入临时数组中
    void merge(int* A, int left, int mid, int right){
        int l = left;
        int r = mid+1;
        int temp[right-left+1];
        int index = 0;
        while(l<=mid&&r<=right){
            if(A[l] <= A[r])
                temp[index++] = A[l++];
            else
                temp[index++] = A[r++];
        }
        while(l<=mid)
            temp[index++] = A[l++];
        while(r<=right)
            temp[index++] = A[r++];
        for(int i = 0; i < index; i++)
            A[left+i] = temp[i];
    }
};

快速排序

算法思路:
S1:将序列的第一个值设为参考值,left指向数组第一个元素,right指向数组最后一个元素,具体排序步骤如下:
在这里插入图片描述
S2:使用递归的方法对整个数组进行分区,重复S1
S3:当left=right时结束排序

class QuickSort {
public:
    void swap(int * A, int i, int j){
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }
    int partion(int* A, int left, int right){
        int key = 0;
        key = A[left];
        while(left<right){
            while((left<right) && (A[right] >= key)) right--;
            swap(A, right, left);
            while((left<right) && (A[left] <= key)) left++;
            swap(A, left, right);
        }
        return left;
    }
    void sort(int* A, int left, int right){
        int index = 0;
        if(left >= right) return;
        index = partion(A, left, right);
        sort(A, left, index-1);
        sort(A, index+1, right);
    }
    int* quickSort(int* A, int n) {
        // write code here
        sort(A, 0, n-1);
        return A;
    }
};

堆排序

实现堆排序算法之前,先看下树的基本概念:
查找数组中某个数的父结点和左右孩子结点,比如已知索引为i的数,那么
父结点索引:(i-1)/2(这里计算机中的除以2,省略掉小数)
左孩子索引:2i+1
右孩子索引:2
i+2

堆排序算法主要是利用了一种堆的数据结构,具体的排序思路如下:
S1: 调整堆上的元素使其成为一个大根堆并输出堆顶元素,并将这个堆的最后一个元素与这个堆进行交换
在这里插入图片描述
S2: 输出堆顶元素,并将这个堆的最后一个元素放到数组末尾,重复S1。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
S3:当堆中元素只有一个时停止排序。
在这里插入图片描述

class HeapSort {
public:
    void swap(int* A, int i, int j){
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }
    void maxHeap(int* A, int root, int last){
        int parent = root;
        int largest = 2 * parent + 1;
        while(largest <= last){
            //如果右孩子存在并且大于左孩子
            if(largest< last && A[largest] < A[largest +1]){
                largest++;
            }
            //如果子节点大于父节点
            if(A[largest] > A[parent]){
                swap(A, largest, parent);
                parent = largest;
                //largest指向该节点的左节点
                largest = 2 * parent + 1;
            }
            else break;
        }
    }
    int* heapSort(int* A, int n) {
        // write code here
        if(A == NULL || n <=1) return A;
        //创建初始大根堆
        for(int i = n/2 + 1; i >= 0; i--){
            maxHeap(A, i, n-1);
        }
        //交换根节点和最后一个节点
        for(int i = n-1; i > 0; i--){
            swap(A, 0, i);
            maxHeap(A, 0, i-1);
        }
        return A;
    }
};

希尔排序

希尔排序的具体思路如下:
选择一个初始步长gap一般为n/2
S1:隔gap个数取一个数,分为gap个组,对每个组进行直接插入排序
S2:将gap数量减半重复S1
S3:当gap为0时结束排序
在这里插入图片描述

class ShellSort {
public:
    void swap(int *A, int i, int j){
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }
    void sort(int* A, int gap, int n){
        for (int i = gap; i < n; i++){
            int j = i - gap;
            while(j>=0){
                if(A[j] > A[j+gap]){
                    swap(A, j, j+gap);
                }
                j -= gap;
            }
        }
    }
    int* shellSort(int* A, int n) {
        // write code here
        if(n <= 1) return A;
        int gap = n/2;
        
        while(gap >= 1){
            sort(A, gap, n);
            gap = gap/2;
        }
        return A;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值