目录
0 综述
0.1算法分类
0.2 算法复杂度
0.3 相关概念
1 常考排序
1.1快速排序(Quick Sort)
1.2 归并排序(Merge Sort)
1.3 堆排序(Heap Sort)
2 普通排序算法
2.1冒泡排序
2.2选择排序(Selection Sort)
2.3 插入排序(Insertion Sort)
3 其他排序
3.1 希尔排序(Shell Sort)
3.2 基数排序(Radix Sort)
3.3 计数排序(Counting Sort)
3.4 桶排序(Bucket Sort)
4 排序思想应用题剑指offer
剑指 Offer 40. 最小的k个数 堆
剑指 Offer 41. 数据流中的中位数 最小堆 最大堆
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面 快排
剑指 Offer 45. 把数组排成最小的数 拼接 快排
剑指 Offer 51. 数组中的逆序对 归并排序
十种常见排序算法可以分为两大类:
十大经典排序算法(动图演示)https://www.cnblogs.com/onepixel/p/7674659.html
//快速排序
//双边循环法
int partion(int arr[],int low,int high)
{
int startIndex=low;
int pivot=arr[low];
while(low=pivot)
{
high--;
}
while((low
//归并排序
/*
使用分治思想:
假设两个子数组是有序的,将其按照有序序列合并,合并组成新的有序数组,再与其他部分合并
排序算法:归并排序【图解+代码】https://www.bilibili.com/video/BV1Pt4y197VZ?from=search&seid=7880178413492422518
*/
void merge(int arr[], int low, int mid, int high, int temp[])
{
int i = low; //左子数组开始位置
int j = mid + 1; //右子数组开始位置
int t = 0; //临时空间指针
while (i <= mid && j <= high)
{
if (arr[i] < arr[j])
temp[t++] = arr[i++];
else
temp[t++] = arr[j++];
}
//将左边剩余元素填充进temp中
while (i <= mid)
temp[t++] = arr[i++];
//将右边子数组剩余部分填充到temp中
while (j <= high)
temp[t++] = arr[j++];
//将融合后的数据拷贝到原来的数据对应的子空间中
t = 0;
while (low <= high)
{
arr[low++] = temp[t++];
}
}
void MergeSort(int arr[], int low, int high, int temp[])
{
if (low < high) //只有low==high为一个元素的时候不用再细分自分组,融合
{
int mid = (low + high) / 2;
//递归划分左半区
MergeSort(arr, low, mid, temp);
//递归划分右半区
MergeSort(arr, mid + 1, high, temp);
//合并已经排序的部分
merge(arr, low, mid, high, temp);
}
}
//堆排序
#include
#include
using namespace std;
// 递归方式构建大根堆(len是arr的长度,index是第一个非叶子节点的下标)
void adjust(vector &arr, int len, int index)
{
int left = 2*index + 1; // index的左子节点
int right = 2*index + 2;// index的右子节点
int maxIdx = index;
if(left arr[maxIdx]) maxIdx = left;
if(right arr[maxIdx]) maxIdx = right;
if(maxIdx != index)
{
swap(arr[maxIdx], arr[index]);
adjust(arr, len, maxIdx);
}
}
// 堆排序
void heapSort(vector &arr, int size)
{
// 构建大根堆(从最后一个非叶子节点向上)
for(int i=size/2 - 1; i >= 0; i--)
{
adjust(arr, size, i);
}
// 调整大根堆
for(int i = size - 1; i >= 1; i--)
{
swap(arr[0], arr[i]); // 将当前最大的放置到数组末尾
adjust(arr, i, 0); // 将未完成排序的部分继续进行堆排序
}
}
int main()
{
vector arr = {8, 1, 14, 3, 21, 5, 7, 10};
heapSort(arr, arr.size());
for(int i=0;i
//冒泡排序
//[0,1,2,3,4,5,6,7,8]
//len=9
//有8轮,i最大是7
void Bubble_Sort_v1(int* A,int len){
for(int i=0;iA[j+1]){
int t = A[j+1];
A[j+1] = A[j];
A[j] = t;
}
}
}
}
void Bubble_Sort_v2(int* A,int len){
for(int i=0;iA[j+1])
{
int t = A[j+1];
A[j+1] = A[j];
A[j] = t;
// 有元素交换,所以不是有序,标记变为false
is_Sorted=false;
}
}
if (is_Sorted)
{
break;
}
}
}
void Bubble_Sort_v3(int* A,int len){
// 记录最后一次交换的位置
int last_exchange_index = 0;
// 无序数列的边界,每次比较只需要比到这里为止
int sort_border = len-1;
for(int i=0;iA[j+1])
{
int t = A[j+1];
A[j+1] = A[j];
A[j] = t;
// 有元素交换,所以不是有序,标记变为false
is_Sorted=false;
// 把无序数列的边界更新为最后一次交换元素的位置
last_exchange_index = j;
}
};
sort_border = last_exchange_index;
if (is_Sorted)
{
break;
}
}
}
//选择排序法
/*
从该位置后面选择最小的元素放在该位置
*/
void SelectSort(int a[],int len)
{
//外层循环跑n趟
for (int i = 0; i < len; i++){
//内层循环找出最小值进行交换
int tmp;
for (int j = i; j < len; j++){
if (a[j] < a[i]){
tmp = a[j];
a[j] = a[i];
a[i] = tmp;
}
}
}
}
// 插入排序法
/*
插入排序法:
拿着当前位置元素和前面的元素进行比较,只要当前元素比前面的元素大,则插入到该元素前面
直到前面的元素不满足要求,记录插入位置。
先拿出来 再比较插入
*/
void InsertSort(int a[], int len)
{
int i, j, k;
int tmp;
for (i = 1; i < len; i++) {
k = i; //待插入元素位置
tmp = a[k]; //先拿出来
for (j = i - 1; (j >= 0) && (a[j] > tmp); j--){
a[j + 1] = a[j]; //只要大,则元素后移
k = j; //记录移动的位置
}
a[k] = tmp; //元素插入
}
}
https://leetcode-cn.com/problems/zui-xiao-de-kge-shu-lcof/solution/zi-jie-ti-ku-jian-40-jian-dan-zui-xiao-de-kge-shu-/
//堆思想
class Solution {
public:
vector getLeastNumbers(vector& arr, int k) {
if(arr.empty() || k == 0) {return {};}
vector res(k);
priority_queue max_heap;
for(int i = 0; i < k; ++i) {max_heap.push(arr[i]);} // 用 arr 的前 k 个数填充最大堆
for(int i = k; i < arr.size(); ++i) {
if(arr[i] < max_heap.top()){
max_heap.pop();
max_heap.push(arr[i]); // 循环更新最大堆
}
}
for(int i = 0; i < k; ++i) {
res[i] = max_heap.top(); // 填充 res
max_heap.pop();
}
return res;
}
};
https://leetcode-cn.com/problems/find-median-from-data-stream/solution/zi-jie-ti-ku-295-kun-nan-shu-ju-liu-de-zhong-wei-s/
class MedianFinder {
public:
/** initialize your data structure here. */
priority_queue, less > maxheap;
priority_queue, greater > minheap;
MedianFinder() {
}
void addNum(int num) {
if(maxheap.size() == minheap.size()) {
maxheap.push(num);
minheap.push(maxheap.top());
maxheap.pop();
}
else {
minheap.push(num);
maxheap.push(minheap.top());
minheap.pop();
}
}
double findMedian() {
return maxheap.size() == minheap.size() ? ((maxheap.top() + minheap.top()) * 0.5) : minheap.top();
}
};
//双边循环法
class Solution {
public:
vector exchange(vector& nums) {
int low = 0,high = nums.size() - 1;
while(low
//单边循环法
class Solution {
public:
vector exchange(vector& nums) {
int low = 0,high = nums.size() - 1;
int mark=low;
for (int i=low;i<=high;i++)
{
if (nums[i]%2!=0)
{
int tmp=nums[i];
nums[i]=nums[mark];
nums[mark]=tmp;
mark++;
}
}
return nums;
}
};
C++ 先转换成字符串再组合https://leetcode-cn.com/problems/ba-shu-zu-pai-cheng-zui-xiao-de-shu-lcof/solution/c-xian-zhuan-huan-cheng-zi-fu-chuan-zai-zu-he-by-y/
//c++之to_string()函数 功能:将数值转化为字符串。返回对应的字符串。
class Solution {
public:
string minNumber(vector& nums) {
vectorstrs;
string ans;
for(int i = 0; i < nums.size(); i ++){
strs.push_back(to_string(nums[i]));
}
sort(strs.begin(), strs.end(), [](string& s1, string& s2){return s1 + s2 < s2 + s1;});
for(int i = 0; i < strs.size(); i ++)
ans += strs[i];
return ans;
}
};
拓跋阿秀pdf
class Solution {
public:
int reversePairs(vector& nums) {
if( nums.size() <= 1) return 0;
vector tmp(nums.size());
return mergeSort(0, nums.size() - 1, nums, tmp);
}
private:
int mergeSort(int l, int r, vector& nums, vector& tmp) {
// 终止条件
if (l >= r) return 0;
// 递归划分
int m = l+(r-l)/2,res=0;
// 合并阶段
int i = l, j = m + 1, t = l;
int leftRes = mergeSort(l, m, nums, tmp);
int rightRes = mergeSort(m+1, r, nums, tmp);
while (i <= m && j <= r)
{
if (nums[i] <= nums[j])
{
tmp[t++] = nums[i++];
}
else
{
res += (m - i + 1 );
tmp[t++] = nums[j++];
}
}
while(i<=m)
{
tmp[t++] = nums[i++];
}
while(j<=r)
{
tmp[t++] = nums[j++];
}
//注意要有这一行
while (l <= r) {
nums[l] = tmp[l];
l++;
}
return res + leftRes + rightRes;
}
};