C++排序算法总结

冒泡法

**冒泡法的核心思想:**依次比较相邻的两个数,将比较小的数放在前面,比较大的数放在后面。
N个数字要排序完成,总共进行N-1趟排序,每i趟的排序次数为(N-i)次,
所以可以用双重循环语句,外层控制循环多少趟,内层控制每一趟的循环次数。
所以时间复杂度为O(n2) 
冒泡排序的优点:每进行一趟排序,就会少比较一次,因为每进行一趟排序都会找出一个较大值。

图片演示:
在这里插入图片描述

//代码演示
template<typename T>
void bubblesort(T a[],T n)//冒泡法排序
{ 
    for (int i = n - 1; i > 0; i--) 
    {
        for (int j = 0; j < i; j++)
        {
            if (a[j] > a[j + 1])
            {      
             swap(a[j] , a[j + 1]);//swap函数可以自己定义
                                  //本身包含在#include <algorithm>头文件中 
            }
        }
    }
} ;

插入法

原理:
1.从数组的第二个数据开始往前比较,即一开始用第二个数和他前面的一个比较,如果 符合条件(比前面的大或者小,自定义),则让他们交换位置。

2.然后再用第三个数和第二个比较,符合则交换,但是此处还得继续往前比较。
3.重复步骤二,一直到数据全都排完。

插入法排序动态演示

//代码演示
template<typename T>
void InsertSort(T a[], T n) {//插入法排序
    for (int i = 1; i < n; i++) {
        T key = a[i];
       T j = i - 1;
        while (j >= 0 && key < a[j]) {
            a[j + 1] = a[j];
            j--;
        }
        a[j + 1] = key;//大的挪到后面后插入合适位置
    }
}

选择法

选择排序法是从算法优化的角度对冒泡法的改进,
其改进的思想是:经过一轮的两两比较后,并不马上交换数的位置,而是找到本轮最小的数,
记下该数的位置(即在数组中的下标)(j),待本轮比较完毕后,通过一次交换即可将本轮
最小的数交换到位。

选择法排序

 template<typename T>
void SelcetSort(T a[], T n) {
    for (int i = 0; i < n; i++) {//选择法排序
       int min = a[i];
       int index = i;
        for (int j = i+1; j < n; j++) {
            if (a[j] < min) {
                min = a[j];
                index = j;
            }
        }
        swap(a[i], a[index]);//一轮下来找出最小值放在前面
    }

}

归并法

思路:假设数组有n个数,先将其分为两半,再对这两半继续对半分隔...
重复操作直到分隔后的小部分只有一个数。接着对这两个数进行归并操作,
归并后得到一个有序的两个数组成的小数组,再将其与另一个有序的两个数组成的小数组进行归并,
重复操作,直到所有数组有序。

图片演示

template<typename T>//归并过程
void Merge(T a[], T l, T mid, T r) //l为第1有序区的第1个元素,i指向第1个元素, r为第1有序区的最后1个元素
{
    int *t = new int[r - l + 1];//t数组暂存合并的有序序列
    int q = mid + 1;
    int i = 0;
    int left = l;
    while (left <= mid && q <= r)
     {
        if (a[left] <= a[q])
         {
            t[i] = a[left];
            i++;
            left++;
         }
        else
        {
            t[i] = a[q];
            i++;
            q++;    
        }
    }
    while (left <= mid) //若比较完之后,第一个有序区仍有剩余,则直接复制到t数组中
    {
        t[i] = a[left];
        i++;
        left++;
    }
    while (q <= r) 
    {
        t[i] = a[q];
        i++;
        q++;
    }
    for (T j = 0; l <= r; j++) 
    {
        a[l] = t[j];
        l++;
    }
    delete []t;//释放内存,由于指向的是数组,必须用delete []
};
template<typename T>
void MergeSort(T a[], T l, T r) //归并法排序
{
    T mid = l + (r-l) / 2;
    if (l >= r) 
    {
        return;// 终止递归的条件,子序列长度为1
    }
    MergeSort(a, l, mid); //对左半边递归
    MergeSort(a, mid + 1, r); // 对右半边递归
    Merge(a, l,mid, r); // 合并
}

快速排序

【思路】:每轮选择一个基准元素(比如第一个),将待排序的记录分割成两部分,
一部分的元素值均比基准元素值小,另一部分比基准值大,然后分别对这两部分用同样的方法排序。
一般基于递归实现。冒泡排序每次只调整了一个数或几个数的相对关系,而快速排序每遍都让两边保持相对关系。

图片演示

template<typename T>
void QuickSort(T left, T right,T arr[]) {//快速排序
    if (left >= right)
        return;
    int idx = rand() % (right - left + 1) + left;//加上随机数加快排序速度
    swap(arr[idx], arr[left]);
    int i, j, base, temp;
    i = left, j = right;
    base = arr[left];  //取最左边的数为基准数
    while (i < j)
    {
        while (arr[j] >= base && i < j)//必须先j--然后再i++
            j--;
        while (arr[i] <= base && i < j)
            i++;
        if (i < j)
        {
            swap(arr[i], arr[j]);
        }
    }
    //基准数归位
    arr[left] = arr[i];
    arr[i] = base;
    QuickSort(left, i - 1, arr);//递归左边
    QuickSort(i + 1, right, arr);//递归右边
  
}

下面是测试代码:

// 
int main()
{

    int n=10 ;
    int a[10] = { 2,3,5,6,4,9,4,5,2,1};
   
  
 
    QuickSort(0,9,a);
    
    for (int m = 0; m < n; m++)
    std::cout <<a[m]<<endl;
    return 0;
}
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值