交换排序

简单描述

交换排序是指通过比较键值的大小来交换这两个元素的位置,实现排序. 常见的交换排序有冒泡排序和快速排序. 冒泡排序的时间复杂度度是 O(n^2), 快速排序的时间复杂度度是 O(nlogn), 快速排序是对冒泡排序的改良.但是快速排序是不稳定的

冒泡排序

原理:
通过比较相邻两个数的大小来决定是否交换。
一轮比较下来,最右边的数就是最大或最小的,假设数组size=n,则需要n-1轮比较。
实现:
利用外层for循环控制比较轮数,内层for循环遍历比较相邻元素(j与j+1比较)。每轮过后,有序队列就会增加一个元素。如果在某轮比较中未交换元素, 则说明元素已是有序,不用在比较了.直接break.

完整代码

void sort(int arr[],int length)
{
    int i, j, flag;
    for(i = 0;i < length-1; i++)
    {
        for(j = 0; j < length-i-1; j++)
        {
            flag = 1;
            if(arr[j] > arr[j+1])
            {
                flag = 0;

                arr[j+1] += arr[j];
                arr[j] = (arr[j+1] - arr[j]);
                arr[j+1] = (arr[j+1] - arr[j]);

            }
        }
        if(flag)
        break;

    }
}

快速排序

原理:
快速排序是交换排序和分治思想的结合,其实现思路是通过一次交换,是数组的一边比另一边大,以两边的分界点,将数组分成两部分.然后分别对两边再经行同样的操作,这样不断细分下去.直到两边都只剩一个元素为止,此时数组就是有序的了.

实现:
按上述分析, 数组的拆分可以使用递归实现, 这里重点分析一趟排序的过程原理. 完成一趟排序, 要实现将一个集合分成一边大一边小的两个集合, 就需要有一个比较基准(key), key的选择对于排序效率也有影响. 这里暂不考虑,直接选择集合的第一个元素作为key. 定义两个下标i和 j 。 i = 集合开始下边,j = 集合最后一个元素的下边。i 从左向右遍历元素,j则相反。

i和j从两头出发交替遍历元素,j先开始 如果j遍历遇到比key小的元素则与i交换,然后i遍历到比key大的元素则让他与j交换。然后直到i和j相遇(i>=j)完成一趟排序。然后以i的值作为中点分割集合,再分别递归即可。

完整代码

void Quicksort(int arr[],int left,int right){
    int l = left, r = right;
    int key;

    if(left >= right){return;}//递归结束条件
    key = arr[left];
    while(left < right){
        //这里是arr[right] >= key,如果是arr[right] > key,当有相同的键值时会死循环.
        while(arr[right] >= key && right > left)
            right--;

        //这里的j和i的交换由于记录了i的值(key = arr[i]),所以直接覆盖即可,下面的i与j交换也直接覆盖,循环结束后再将key复制回来
        arr[left] = arr[right];

        while(arr[left] < key && left < right)
            left++;
        arr[right] = arr[left];

    }

    arr[left] = key;

    Quicksort(arr,l,left-1);
    Quicksort(arr,left+1,r);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值