1、比较类排序算法和非比较类排序算法的分类以及它们的时间复杂度:
2、本文主要实现了比较类排序算法,其中多路归并没有实现
以下是C++实现的代码:
#include<iostream>
#include<vector>
#include <stdlib.h>
# include <functional>
//#include <string.h>
#include<queue>
#include<set>
#include<stack>
#include <algorithm>
#include<array>
#include <string>
using namespace std;
class Solution {
public:
//各种排序算法的实现
//1、快排
//快速排序(从小到大)//当选左边为基准点时,一定要保证先从右边开始走
void quickSort(int left, int right, vector<int>& arr)
{
if(left >= right)
return;
int i, j, base, temp;
i = left, j = right;
base = arr[left]; //取最左边的数为基准数
while (i < j) //当i==j时 就跳出这个循环了
{
while (arr[j] >= base && i < j) //当选左边为基准点时,一定要保证先从右边开始走
j--;
while (arr[i] <= base && i < j)
i++;
if(i < j)
{
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
//基准数归位
arr[left] = arr[i];
arr[i] = base;
quickSort(left, i - 1, arr);//递归左边
quickSort(i + 1, right, arr);//递归右边
}
// 2、插入排序
//有一种从后往前的感觉
void insertSort(vector<int> &input)
{
for(int i=1;i<input.size();i++)
{
for(int j=i-1;j>=0&&input[j+1]<input[j];j--)
{
swap(input[j+1],input[j]);
}
}
}
void swap(int &a,int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
//3、选择排序
//每次都是找到最小值放在最左面
void select_sort(vector<int> &input)
{
for(int i=0;i<input.size();i++)
{
int min=i;
for(int j=i+1;j<input.size();j++)
{
if(input[j]<input[min])
{
min = j;
}
}
if(min!=i)
{
int temp;
temp = input[i];
input[i] = input[min];
input[min] = temp;
}
}
}
//4、冒泡排序
//相邻位置两两互换 每次都是将最大值放在最右面
void bubble_sort(vector<int> &input)
{
for(int i=0;i<input.size()-1;i++)
{
for(int j=0;j<input.size()-1-i;j++)
{
if(input[j]>input[j+1])
{
int temp;
temp = input[j];
input[j] = input[j+1];
input[j+1] = temp;
}
}
}
}
//5、希尔排序
// 根绝gap对数组进行分组,然后在组内进行插入排序,然后缩小gap进行迭代,直至gap为1
void shell_sort(vector<int> &input)
{
//int gap_deta = 2;
int gap = input.size()/2;
while(gap) //gap>=1的时候
{
for(int i=gap;i<input.size();i++)// 分组,在每个子序列中进行插入排序
{
int insert = input[i]; //将当前的元素值先存起来方便后面插入
int j = i;
while(j>=gap&&input[j-gap]>insert) //寻找插入位置
{
input[j] = input[j-gap];
j = j-gap;
}
input[j] = insert;
}
gap = gap/2;
}
}
// 6、堆排序
//解法一:建立最大堆结构
//注意:是把一个数组想象成了最大堆!!!!!!
//利用最大堆这种数据结构进行排序:先构建个最大堆,
//然后将根节点(此时根节点的值即为最大值)与数组最后一个元素交换,然后对剩下的N-1个元素进行迭代(建堆、交换)
void heap_sort1(vector<int> &input)
{
//build_heap(input);
// 1、先建堆!!!!!!!
//从第一个非叶子节点开始调整的原因在于叶子节点没有孩子,那么显然它也就满足堆的性质,也就没有调整的必要了。
for(int i=input.size()/2-1;i>=0;i--)//根节点为0,最后一个叶节点的下标为n-1,
//其父节点是第一个非叶节点,下标为((n-1)-1 )/ 2 = (n-2)/2 = n/2 - 1
{
heap_max(input,i,input.size()); //建堆时候这个参数n(第三个参数)一直不变,但是i在变
}
///2、把最大元素移除 接着进行见堆!!!!
for(int j=input.size()-1;j>0;j--) //这里的j是大于0 没有等于
{
// 将根节点(最大值)与数组待排序部分的最后一个元素交换,这样最终得到的是递增序列
int temp;
temp = input[0];
input[0] = input[j];
input[j] = temp;
// 待排序数组长度减一,只要对换到根节点的元素进行排序,将它下沉就好了。
heap_max(input,0,j); //这个时候i这个参数不变,但是参数n(j)一直在变
}
}
// void build_heap(vector<int> &input) //构建最大堆
// {
// //从第一个非叶子节点开始调整的原因在于叶子节点没有孩子,那么显然它也就满足堆的性质,也就没有调整的必要了。
// for(int i=input.size()/2-1;i>=0;i--)//根节点为0,最后一个叶节点的下标为n-1,
// //其父节点是第一个非叶节点,下标为((n-1)-1 )/ 2 = (n-2)/2 = n/2 - 1
// {
// heap_max(input,i,input.size());
// }
// }
void heap_max(vector<int> &input, int i,int n)//将i节点为根的堆中大的数依次上移,n表示堆中的数据个数
{
int left = 2*i+1; // i节点的左孩子
int right = 2*i+2; // i节点的右孩子
int largest = i; //先设置父节点和子节点三个节点中最大值的位置为父节点下标
if(left<n&&input[left]>input[largest])
{
largest = left;
}
if(right<n&&input[right]>input[largest])
{
largest = right;
}
if(largest!=i) //最大值不是父节点,则进行交换
{
int temp;
temp = input[i];
input[i] = input[largest];
input[largest] = temp;
heap_max(input,largest,n); //递归调用,保证子树也是最大堆
}
}
//堆排序解法二:利用STL的优先级队列
void heap_sort2(vector<int> &input)
{
//priority_queue< int, vector<int>, greater<int> > a; // 小顶堆
//priority_queue< int, vector<int>, less<int> > q; // 大顶堆
priority_queue<int> a; //默认是大顶堆
for(int i=0;i<input.size();i++)
{
a.push(input[i]);//优先级队列在push的时候就已经自动排序了,最大值在第一个,后面的没有排序
}
for(int j=0;j<input.size();j++)
{
input[input.size()-1-j] = a.top(); //把最大值给到最后一个
//input[j] = a.top();//小顶堆是直接对应赋值
a.pop();
}
}
//堆排序解法3:利用#include <algorithm>里的把迭代器指定的range当堆 以及make_heap、push_heap、pop_heap、sort_heap
//pop_heap()并没有删除元素,而是将堆顶元素和数组最后一个元素进行了替换,如果要删除这个元素,还需要对数组进行pop_back()操作
void heap_sort3(vector<int> &input)
{
//make_heap(input.begin(),input.end(), less<int>());//创建大顶推 此时向量第一个元素为最大值
//make_heap(input.begin(),input.end(), greater<int>());//创建小顶推 此时向量第一个元素为最小值
for(int i=0;i<input.size()-1;i++)
{
make_heap(input.begin()+i,input.end(), greater<int>());
}
}
//7、归并排序
void merge_sort(vector<int> &input,int low,int high)
{
if(low>=high)
{
return;
}
int mid = low+(high-low)/2;
merge_sort(input,low,mid);
merge_sort(input,mid+1,high);
merge(input,low,mid,high);//一开始merge时候 每个序列只有一个元素,所以都是有序的
}
void merge(vector<int> &input,int low,int mid,int high) //这种合并两个子序列的方法有效的前提是:两个子序列是有序的
{
vector<int> temp; //定义一个暂存vector
temp.clear();
int i=low,j=mid+1;//i j 分别指向两个子序列的第一个元素
while (i<=mid&&j<=high)
{
if(input[i]<=input[j])
{
temp.push_back(input[i]);
i++;
}
else
{
temp.push_back(input[j]);
j++;
}
}
while(i<=mid)
{
temp.push_back(input[i]);
i++;
}
while(j<=high)
{
temp.push_back(input[j]);
j++;
}
for(int k=low,q=0;k<=high;k++,q++)
{
input[k] = temp[q];
}
}
};
int main(){
Solution s;
vector<int> input = {4,5,1,6,2,7,3,8};
//int k = 4;
//vector<int> result;
//s.quickSort(0,7,input);
//s.insertSort(input);
//s.select_sort(input);
//s.bubble_sort(input);
//s.shell_sort(input);
//s.heap_sort1(input);
//s.heap_sort2(input);
//s.heap_sort3(input);
s.merge_sort(input,0,7);
for(int i=0;i<input.size();i++)
{
cout<<input[i]<<endl;
}
return 0;
}
参考文献: