zoukankan      html  css  js  c++  java
  • 八大排序

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

    核心图

     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
Copyright © 2011-2022 走看看