【C++】七大排序实践

常用排序算法实践

  1. 冒泡排序
  2. 选择排序
  3. 插入排序
  4. 希尔排序
  5. 归并排序
  6. 快速排序
  7. 堆排序
#include <iostream>
using namespace std;
#include<vector>
#include<algorithm>

void swap(vector<int> &array, int first, int second)
{
    
    
    int temp;
    temp = array[first];
    array[first] = array[second];
    array[second] = temp;
}

void Printf(vector<int> &array)
{
    
    
    for (vector<int>::iterator it = array.begin(); it != array.end(); it++)
    {
    
    
        cout << *it << " ";
    }
    cout << endl;
}

/*
    array: vector<int>型数组
    size:  数组长度array.size()
    特点: 从大到小排序
*/

//冒泡排序
void BubbleSort(vector<int> &array,int size)
{
    
    
    if (size < 2) return;
    for (int i = 0; i < size; i++)   //第一层循环
    {
    
    
        for (int j = 0; j < size - 1 - i; j++)  //第二层循环
        {
    
    
            if (array[j] > array[j+1])   //相邻两个元素比较
            {
    
    
                swap(array, j, j+1);    //交换结果
            }
        }
    }
}


//选择排序(冒泡排序的一种改进)
void SelectSort(vector<int> &array, int size)
{
    
    
    if (size < 2) return;
    for (int i = 0; i < size-1; i++)   //第一层总共循环size次
    {
    
    
        int max = i;
        for (int j = i+1; j < size; j++)   //每次找到子序列中最大值及其下标
        {
    
    
            if (array[max] < array[j])
            {
    
    
                max = j;
            } 
        }
        if (max != i)
            swap(array, i, max);
    }
}

//插入排序(类似与打扑克牌,从左到右整理牌)
void InsertSort(vector<int> &array, int size)
{
    
    
    for (int i = 1; i < size; i++)   //总共整理size-1次
    {
    
    
        int temp = array[i];        
        int j;
        for (j = i - 1; j >= 0 && temp > array[j]; j--)//目标牌大于前1张时,则前一张向后移动1次位置
        {
    
    
            array[j + 1] = array[j];    
                                        //然后j减一,继续与插数比较,若任然大于则重复上述过程,否则退出
        }
        array[j + 1] = temp;  //退出循环后,将插值放入正确位置	
    }
}

//辅助函数,希尔排序(参数:子序列,步长,起点)
void insert(vector<int> &array, int step, int size)
{
    
    
    for (int i = step; i < size; i++)
    {
    
    
        int temp = array[i];   //i表示子序列的第2张牌
        int j;
        for (j = i - step; j >= 0 && temp<array[j]; j -= step)
        {
    
    
            array[j + step] = array[j];
        }
        array[j + step] = temp;
    }
}

//希尔排序
void ShellSort(vector<int> &array, int size)
{
    
    
    for (int step = size / 2; step > 0; step /= 2)  //增量设置
        insert(array, step, size);       //插入排序处理子序列
}


//辅助函数
void Merge(vector<int> &arr, int start, int mid, int end)
{
    
    
    int N = end - start + 1;        //临时数组存储arr[start,end]元素
    int* tmp = new int[N];          
    for (int k = start; k <= end; k++)    //将[start,end]copy到临时数组中
        tmp[k - start] = arr[k];          

    int left = start;               //合并数组左边起点
    int right = mid + 1;            //合并数组右边起点
    for (int step = start; step <= end; step++)    //合并操作仅需要比较end-start+1次
    {
    
    
        if (left > mid)     //当左边已经排序完,则剩下依次处理右边即可
        {
    
    
            arr[step] = tmp[right - start];
            right++;
        }
         
        else if (right > end)   //跟上面同样道理
        {
    
    
            arr[step] = tmp[left - start];
            left++;
        }
        else if (tmp[left - start] <= tmp[right - start])  //左区间小于有区间值时候
        {
    
    
            arr[step] = tmp[left - start];   //
            left++;
        }
        else
        {
    
    
            arr[step] = tmp[right - start];
            right++;
        }

    }
}

//归并排序
void MregeSort(vector<int> &array, int start,int end)
{
    
    
    if (start == end)   //长度为1就退出
        return;
    int mid = (start + end) / 2;
    MregeSort(array, start, mid);     //不断分治,直到最小单元[a]
    MregeSort(array, mid + 1, end);
    Merge(array, start, mid, end);    //合并函数
}


/*
    快排思想:分治+递归;单次循环就是在干1件事,即是把base不
    断推动到数组的中间位置,从而使得base左右两边相对有序;
    然后在进行分治递归,在子序列中重复这个操作。它与归并排
    序分治操作相反,这个自上而下分治,相对就是自下而上。
*/

//快速排序(起点,终点)
void QuickSort(vector<int> &array, int start,int end)
{
    
    
    if (start >= end) return;

    int left = start;
    int right = end;
    int base = array[start];      //一般把数组首元素作为基准值

    while (left < right)
    {
    
    
        while (array[right] <= base && left < right)
        {
    
    
            right--;
        }   //当跳出上述循环表示找到一个数小于flage
        swap(array, left, right);   //更新base位置,此时left就是表示base位置

        while (array[left] >= base && left < right)
        {
    
    
            left++;
        }   //当跳出循环表示找到一个数大于flage
        swap(array, left, right); //更新base位置,此时right就是表示base位置
    }
    QuickSort(array, start, left - 1);
    QuickSort(array, left + 1, end);
}


void Find(vector<int> &array, int father,int size)
{
    
    
    int temp = array[father];  //存储起始节点数字

    //将无序的序列调整为一个大顶堆
    for (int child = 2 * father + 1; child < size; child = 2 * child + 1)
    {
    
    
        if (child + 1 < size && array[child] < array[child + 1])   //若右边存在且,大于左孩子
            child++; //那么就转向右边

        if (temp < array[child]) //比较起始节点(父节点)与较大的子节点的大小关系
        {
    
    
            swap(array, father, child);   //交换,此时起始节点是以它为顶点的树中的最大值
            father = child;              //将旧的子节点(也是进行交换的子节点)作为下一轮的父节点
        }

        else
            break;
    }
}


//堆排序:利用大顶堆或者小顶堆思想
void HeapSort(vector<int> &array,int size)
{
    
    
    // 第一步将无序序列变为大(小)顶堆;自下而上的构建大顶堆
    for (int i = ((size - 1) - 1) / 2; i >= 0; i--)
        Find(array, i, size);

    // 将最后的叶节点与得到的大顶堆顶点交换,并将剩余序列重复进行第一步操作
    for (int j = size - 1; j >0; j--)
    {
    
    
        swap(array, 0, j);  //交换
        //由于交换大顶堆顶节点与树中的最后面节点,对于后面剩下序列的重新
        //大顶堆构建而言,只是顶节点产生了变化,所以只需要自上而下的对树
        //进行大顶堆构建就可以了。
        Find(array, 0, j);
    }
}


void test(void)
{
    
    
    vector<int> T = {
    
     2, 4, 3, 5, 6 };
    Printf(T);
}


void main()
{
    
    
    vector<int> Array = {
    
     5, 6, 2, 7, 9, 3, 1 };
    HeapSort(Array, Array.size());
    //QuickSort(Array, 0, Array.size() - 1);
    Printf(Array);
    system("pause");
    return;
}

猜你喜欢

转载自blog.csdn.net/qq_32643313/article/details/108180613