排序算法总结
以剑指offer的最小K个数为列
详细介绍见:https://www.cnblogs.com/onepixel/p/7674659.html
插曲1:基数排序,计数排序,桶排序区别
“首先,基数排序和计数排序都可以看作是桶排序。 计数排序本质上是一种特殊的桶排序,当桶的个数取最大( maxV-minV+1 )的时候,就变成了计数排序。 基数排序也是一种桶排序。桶排序是按值区间划分桶,基数排序是按数位来划分;基数排序可以看做是多轮桶排序,每个数位上都进行一轮桶排序。
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
方法1;冒泡排序
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
//int* temp = new int[input.size()]
vector<int> res;
if(k>input.size())
return res;
for(int i=1;i<input.size();i++)//冒泡排序
{
for(int j=0;j<input.size()-i;j++)
{
if(input[j]>input[j+1])
swap(input[j],input[j+1]);
}
}
for(int i=0;i<k;i++)
res.push_back(input[i]);
return res;
}
void swap(int &a,int &b)//交换两个数
{
int c=a;
a=b;
b=c;
}
};
方法2:快排
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
//int* temp = new int[input.size()]
vector<int> res;
if(k>input.size())
return res;
Quicksort(input,0,input.size());
for(int i=0;i<k;i++)
res.push_back(input[i]);
return res;
}
void Quicksort(vector<int> &input,int left,int right)
{
if(left<right)
{
int p=left;
int q=left+1;
int tag=input[left];
while(q<right)
{
if(input[q]<input[left])
{
p++;
int temp=input[q];
input[q]=input[p];
input[p]=temp;
// swap(input[q],input[p]);
}
q++;
}
input[left]=input[p];
input[p]=tag;
Quicksort(input,left,p);
Quicksort(input,p+1,right);
}
}
};
方法3;选择排序
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
//int* temp = new int[input.size()]
vector<int> res;
if(k>input.size())
return res;
for(int i=0;i+1<input.size();i++)
{ //注意只能写成i<input.size()-1的形式,会报错
int min=i;
for(int j=i+1;j<input.size();j++)//选择排序
{
if(input[j]<input[min])
min=j;
}
if(i!=min)
swap(input[i],input[min]);
}
for(int i=0;i<k;i++)
res.push_back(input[i]);
return res;
}
void swap(int &a,int &b)
{
int c=a;
a=b;
b=c;
}
};
方法四:插入排序
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
//int* temp = new int[input.size()]
vector<int> res;
if(k>input.size())
return res;
for(int i=1;i<input.size();i++)
{//插入排序
int pre=i-1;
int cur=input[i];
while(pre>=0&&input[pre]>cur)
{
input[pre+1]=input[pre];
pre--;
}
input[pre+1]=cur;
}
for(int i=0;i<k;i++)
res.push_back(input[i]);
return res;
}
};
方法5:希尔(shell)排序
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
//int* temp = new int[input.size()]
vector<int> res;
if(k>input.size())
return res;
int gap = input.size()/2+1;//当取2时可以加1也可不加,取3时一定得加
while(gap)
{//shell排序
for(int i=gap;i<input.size();i++)
{
int temp=input[i];
int j=i;
while(j>=gap&&temp<input[j-gap])
{
input[j]=input[j-gap];
j-=gap;
}
input[j]=temp;
}
gap=gap/2;
}
for(int i=0;i<k;i++)
res.push_back(input[i]);
return res;
}
};
方法6:归并排序
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
//int* temp = new int[input.size()]
vector<int> res;
if(k>input.size())
return res;
MergeSort(input,0,input.size()-1);
for(int i=0;i<k;i++)
res.push_back(input[i]);
return res;
}
void MergeSort(vector<int> &input,int begin,int end)
{//归并排序
if(input.empty()||begin>=end) return ;
int mid=(begin+end)/2;//分解从两部分
MergeSort(input,begin,mid);
MergeSort(input,mid+1,end);
Merge(input,begin,mid,end);//融合
}
void Merge(vector<int> &input,int begin,int mid,int end)
{
int i=begin;
int j=mid+1;
vector<int> temp;
while(i<=mid&&j<=end)
{
if(input[i]<input[j])
temp.push_back(input[i++]);
else
temp.push_back(input[j++]);
}
while(i<=mid)
temp.push_back(input[i++]);
while(j<=end)
temp.push_back(input[j++]);
for(int i=0;i<temp.size();i++)
{
input[begin+i]=temp[i];
}
}
};
方法7:计数排序
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
//int* temp = new int[input.size()]
vector<int> res;
if(k>input.size())
return res;
CountSort(input);
for(int i=0;i<k;i++)
res.push_back(input[i]);
return res;
}
void CountSort(vector<int> &input)
{
if(input.empty()) return ;
int max=input[0];
for(int i=1;i<input.size();i++)
{//计数排序
if(input[i]>max)
max=input[i];//统计最大值
}
vector<int> temp(max+1);//默认初始化为0
for(int i=0;i<input.size();i++)
{
temp[input[i]]++;//统计每个值出现的次数
}
int index=0;
for(int i=0;i<max+1;i++)//
{
for(int j=0;j<temp[i];j++)
input[index++]=i;//通过下标排序
}
}
};
堆排序
void
adjust(vector<
int
> &arr,
int
len,
int
index)
{
int
left = 2*index + 1;
// index的左子节点
int
right = 2*index + 2;
// index的右子节点
int
maxIdx = index;
if
(left<len && arr[left] > arr[maxIdx]) maxIdx = left;
if
(right<len && arr[right] > arr[maxIdx]) maxIdx = right;
if
(maxIdx != index)
{
swap(arr[maxIdx], arr[index]);
adjust(arr, len, maxIdx);
}
}
// 堆排序
void
heapSort(vector<
int
> &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);
// 将未完成排序的部分继续进行堆排序
}
}
归并排序 O(1)
#include <iostream>
#include <cstdlib>
using namespace std;
void print(int *arr, int start, int end)
{
for (int i = start; i <= end; ++i)
cout << arr[i] << ' ';
cout << endl;
}
void randData(int *arr, int start, int end)
{
for (int i = start; i <= end; ++i)
arr[i] = rand() % 20;
print(arr, start, end);
}
void merge(int *arr, int start, int mid, int end)
{
int i, j, k, key;
i = start;
j = mid;
while (i < j && j <= end) //当i等于j或者j到达末尾时终止
{
if (arr[i] > arr[j])
{
k = j;
key = arr[j];
while (k > i && arr[k - 1] > key)
{
arr[k] = arr[k - 1];
--k;
}
arr[k] = key;
++j;
}
++i;
}
}
void mergeSort(int *arr, int start, int end)
{
if(start < end)
{
int mid = (end + start) / 2;
mergeSort(arr, start, mid);
mergeSort(arr, mid + 1, end);
merge(arr, start, mid + 1,end);
print(arr, start, end);
}
}