7大比较类排序算法的C++实现(详细注释)

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;
}

参考文献:

1、十大经典排序算法(动图演示)

2、经典排序算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值