八大排序

  本文主要介绍常用的排序方法——快速排序,归并排序,堆排序,选择排序,插入排序,冒泡排序,基数排序,桶排序

核心图

 1.快速排序

核心: partition 过程,  一个大于区和一个小于区和一个划分值,最初的划分值为数组的最后一位,小于区指针最初为 l-1,大于区指针为r。 

逻辑: 1.当前值小于划分值时, 将小于区的下一位和当前值交换,小于区向右扩一个位置(less++), 当前值跳下一个位置(l++)。

    2.当前值大于划分值时, 将大于区的前一位和当前值交换,大于区向左扩一个位置(more--)。

    3. 当前值等于划分值时,当前值直接跳下一个位置(l++)。

#include <iostream>
#include <vector>
using namespace std; 

class QuickSort {
public:
        vector<int> partition(vector<int>& arr1, int l, int r) {
               int less = l - 1;// 向左扩 开始的位置
               int more = r;
               int s;
               while (l < more) {
                       if (arr1[l] < arr1[r]) {
                              //该元素小于arr[r],将之放置在小于区域
                              //放置方法:将该元素与小于区域的右边界的下一个元素(l+1)交换,
                              //然后将l指针与less指针后移 (当前数与小于区域后一个数交换
                              ++less;
                              s = arr1[less];  
                              arr1[less] = arr1[l];
                              arr1[l] = s;
                              l++;
                       }
                       else if (arr1[l] > arr1[r]) {
                              //该元素大于arr[r],将之放置在大于区域
                              //放置方法:将该元素与大于区域的左边界的下一个元素(more-1)交换,
                              //more指针前进,这便完成了大于区域的扩大
                              --more;
                              s = arr1[more];
                              arr1[more] = arr1[l];
                              arr1[l] = s;
                       }
                       else {
                              l++;  //   如果相等就直接 将当前值跳到下一个
                       }
               }
               swap(arr1[more], arr1[r]);
               vector<int> p(2);
               p[0] = less + 1;
               p[1] = more;
               return p;
        }
        void SortProcess(vector<int>& arr1, int l, int r)
        {
               if (l < r) {
                       swap(arr1[l + rand() % (r - l)], arr1[r]); // 随机快排
                       vector<int> p = partition(arr1, l, r);//返回的是位置,小于值得右边和大于值得左边
                       //cout<< p.size()<<endl;
                       SortProcess(arr1, l, p[0] - 1);
                       SortProcess(arr1, p[1] + 1, r);
               }
        }
        void quickSort(vector<int>& arr1) {
               if (arr1.empty() == true || arr1.size() < 2)
               {
                       return;
               }
               SortProcess(arr1, 0, arr1.size() - 1);
        }
        vector<int> generateRandomArr(int maxsize, int minsize, int length) {
               vector<int> arr(length);
               for (int i = 0; i < length; i++) {
                       arr[i] = rand() % (maxsize - minsize) + minsize + 1;
               }
               return arr;
        }
};

  2.归并排序

#include<iostream>
#include <vector>
using namespace std; 
class Solution {
public:
        void mergeSort(vector<int> &arr) {
               if (arr.size() == 0 || arr.size() < 2) return;
               SortProcess(arr, 0, arr.size()-1);
        }
        //归并排序主体过程
        void SortProcess(vector<int> &arr, int l, int r) {
               if (r == l) return; // 递归停止
               int mid = l + (r - l)/2;
               SortProcess(arr, l, mid);
               SortProcess(arr, mid + 1, r);
               merge(arr, l, mid, r);
        }
        // 合并过程
        void merge(vector<int> &arr, int l, int mid, int r) {
               vector<int> helper(r - l + 1); // 辅助数组用来存放排序后的数组
               int i = 0;
               // 两个指针
               int p1 = l;
               int p2 = mid + 1;
               while (p1 <= mid && p2 <= r) {
                       if (arr[p1] < arr[p2]) {
                              helper[i++] = arr[p1++];
                       }
                       else {
                              helper[i++] = arr[p2++];
                       }
               }
               while (p1 <= mid) {// 注意这里可以等于
                       helper[i++] = arr[p1++];
               }
               while (p2 <= r) {
                       helper[i++] = arr[p2++];
               }
               // 将辅助数组元素位置拷贝会arr
               for (int i = 0; i < helper.size(); i++) {
                       arr[l + i] = helper[i];
               }
        }
        vector<int> generateRandomArr(int maxsize, int minsize, int length) {
               vector<int> arr(length);
               for (int i = 0; i < length; i++) {
                       arr[i] = rand() % (maxsize - minsize) + minsize + 1;
               }
               return arr;
        }
};

3.堆排序

核心(这里直接说大根堆):

heapinsert() : 将数组元素加入大根堆,即建立大根堆过程。 

heapify() : 大根堆中有值发生变化,调整大根堆过程。

#include<bits/stdc++.h> 
using namespace std; 

class Solution {
public:
        // 建立大根堆
        void heapInsert(vector<int>& array, int index) {
               while (array[index] > array[(index - 1) / 2]) {
                       swap(array[index], array[(index - 1) / 2]);// (index - 1) / 2 是 根节点, index是儿子
                       index = (index - 1) / 2;
               }
        }
        //大跟堆中有值发生变化,调整成依旧是大根堆
        void heapify(vector<int>& arr, int index, int heapsize) {
               int left = index * 2 + 1;//左孩子节点
               while (left < heapsize) {
                       int largest;
                       if (left + 1 < heapsize && arr[left + 1] > arr[left])
                              largest = left + 1;  // 较大的子树
                       else
                              largest = left;
                       if (arr[largest] < arr[index]) {
                              largest = index;
                       }
                       if (largest == index)// 已经在堆顶了
                              break;
                       swap(arr[largest], arr[index]);
                       //  交换根节点 与 最大儿子 的值,某个孩子比我大,那个孩子的位置就是largest
                       index = largest;
                       left = index * 2 + 1;
               }
        }
        void heapSort(vector<int>& arr)
        {
               if (arr.empty() == true || arr.size() < 2) {
                       return;
               }
               for (int i = 0; i < arr.size(); i++) {
                       heapInsert(arr, i);//变成大根堆
               }
               int heaplength = arr.size();
               swap(arr[0], arr[--heaplength]);
               while (heaplength > 0) {
                       heapify(arr, 0, heaplength);
                       swap(arr[0], arr[--heaplength]);
               }
        }
        vector<int> generateRandomArr(int maxsize, int minsize, int length) {
               vector<int> arr(length);
               for (int i = 0; i < length; i++) {
                       arr[i] = rand() % (maxsize - minsize) + minsize + 1;
               }
               return arr;
        }
};

4.选择排序

#include<bits/stdc++.h> 
using namespace std; 

class Solution {
public:
	void SelectionSort(vector<int>& arr) {
		
		for (int i = 0; i < arr.size()-1; i++) {
			int min_index = i; 
			for (int j = i + 1; j < arr.size(); j++) {
				if ( arr[j] < arr[min_index] ) {
					min_index = arr[j] < arr[min_index] ? j : min_index; 
				}
				swap(arr[j], arr[min_index]);
			}
		}

	}
	vector<int> generateRandomArr(int maxsize, int minsize, int length) {
		vector<int> arr(length);
		for (int i = 0; i < length; i++) {
			arr[i] = rand() % (maxsize - minsize) + minsize + 1;
		}
		return arr;
	}
};

 5.插入排序

#include<iostream> 
using namespace std; 

class Solution {
public:
        void insertSort(vector<int>& arr) {
               if (arr.size() == 0) {
                       return;
               }
               for (int i = 1; i < arr.size(); i++) {
                       for (int j = i - 1; j >= 0; j--) {
                              if (arr[j] > arr[j + 1]) {
                                      swap(arr[j], arr[j + 1]);
                              }
                       }
               }
        }
        vector<int> generateRandomArr(int maxsize, int minsize, int length) {
               vector<int> arr(length);
               for (int i = 0; i < length; i++) {
                       arr[i] = rand() % (maxsize - minsize) + minsize + 1;
               }
               return arr;
        }
};

 6.冒泡排序

#include<bits/stdc++.h> 
using namespace std; 

class Solution {
public:
        void BubbleSort(vector<int>& arr) { //优化版的的冒泡
               for (int i = 0; i < arr.size(); i++) {
                       bool swap_flag = false;
                       for (int j = arr.size()-1; j > i; j--) {
                              if (arr[j-1] > arr[j]) {
                                      swap(arr[j], arr[j -1]);
                                      swap_flag = true;
                              }
                       }
                       if (!swap_flag) {
                              return;
                       }
               }
        }
        vector<int> generateRandomArr(int maxsize, int minsize, int length) {
               vector<int> arr(length);
               for (int i = 0; i < length; i++) {
                       arr[i] = rand() % (maxsize - minsize) + minsize + 1;
               }
               return arr;
        }
};

//也可以这样, 大数往后面提
class Solution2 {
public:
        void BubbleSort(vector<int>& arr) { 
               for (int i = 0; i < arr.size(); i++) {
                       for (int j = 0; j < arr.size()-i-1; j++) {
                              if (arr[j] > arr[j+1]) {
                                      swap(arr[j], arr[j +1 ]);
                              }
                       }
               }
        }
        vector<int> generateRandomArr(int maxsize, int minsize, int length) {
               vector<int> arr(length);
               for (int i = 0; i < length; i++) {
                       arr[i] = rand() % (maxsize - minsize) + minsize + 1;
               }
               return arr;
        }
};

 7.基数排序

#include <bits/stdc++.h>
using namespace std; 
class Solution {
public:
    /**求数据的最大位数,决定排序次数*/
    int maxbit(int data[], int n)
    {
        int d = 1; //保存最大的位数
        int p = 10;
        for(int i = 0; i < n; ++i)
        {
            while(data[i] >= p)
            {
                p *= 10;
                ++d;
            }
        }
        return d;
    }
    void radixsort(int data[], int n) //基数排序
    {
        int d = maxbit(data, n);
        int tmp[n];
        int count[10]; //计数器
        int i, j, k;
        int radix = 1;
        for(i = 1; i <= d; i++) //进行d次排序
        {
            for(j = 0; j < 10; j++)
                count[j] = 0; //每次分配前清空计数器
            for(j = 0; j < n; j++)
            {
                k = (data[j] / radix) % 10; //统计每个桶中的记录数
                count[k]++;
            }
            //计算累加频数,用户计数排序
            for(j = 1; j < 10; j++)
                count[j] = count[j - 1] + count[j]; 
            for(j = n - 1; j >= 0; j--) //将所有桶中记录依次收集到tmp中
            {
                k = (data[j] / radix) % 10;
                tmp[count[k] - 1] = data[j]; //将tmp中的位置依次分配给每个桶
                count[k]--;
            }
            for(j = 0; j < n; j++) //将临时数组的内容复制到data中
                data[j] = tmp[j];
            radix = radix * 10;
        }
    }
};

 8.桶排序(这里写了python版的,感觉更加简洁)

'''
假设待排序的一组数统一的分布在一个范围中,并将这一范围划分成几个子范围,也就是桶
将待排序的一组数,分档规入这些子桶,并将桶中的数据进行排序
将各个桶中的数据有序的合并起来
'''
def bucket_sort(nums,n=3):
    max_value = max(nums)
    min_value = min(nums)
    ## 桶的个数
    bucket_count = int((max_value-min_value)/n) + 1
    
    ### 创建数量为桶个数的空列表
    buckets = [[] for _ in range(bucket_count)]
    
    ## 将原数组的元素放入到每个桶中
    for i in nums:
        bucket_index = int((i - min_value) // bucket_count)
        buckets[bucket_index].append(i)
    ## 创建返回的排序数组
    sort_nums = []
    for j in range(len(buckets)):
        ##对每个桶中的元素进行排序
        buckets[j].sort()
        for i in range(len(buckets[j])):
            sort_nums.append(buckets[j][i])
    return sort_nums

总结:这几个排序经常容易会忘记,个人觉得除了桶排序和基数排序不太平易近人,其他所有的排序算法最好掌握,特别是快排,归并,堆排。

原文地址:https://www.cnblogs.com/E-Dreamer-Blogs/p/12944766.html