线性表的交换排序

基于交换排序算法有两种:冒泡排序和快速排序
示例数组:int keys[] = new int[]{32,26,87,72,26,17};

冒泡排序

比较相邻两个元素,大的往后排。最简单的一个排序方法了。

public static void bubbleSort(int[] a) {
        int temp = 0;
        boolean exchange = true;
        for (int i = a.length - 1; i > 0&&exchange; --i) {
            exchange =false;
            for (int j = 0; j < i; ++j) {
                if (a[j]>a[j+1]) {
                    exchange = true;
                    temp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = temp;
                }
            }
        }
    }
  • 最好情况,数据排列有序,只需要一趟扫描,比较n次,没有数据移动,时间复杂度为O(n)(因为那个flag的存在,如果扫描一圈一个值都没有改变,证明本来就是有序的,无需再次扫描,循环结束,算法结束)
  • 最坏情况,数据序列随机排序和反序排列,需要n-1趟扫描,比较次数和移动次数都是O(n2
  • 空间复杂度需要一个元素交换两个元素,空间复杂度为O(1)
  • 冒泡排序是稳定的

快速排序

以上面的示例数组32,26,87,72,26,17为例,我们发现,当我们第一次 把87下沉的时候87和72交换一次,其中有一次到达了temp位置,87和26又交换一次,到达temp位置,87又和17交换了一次,到达了temp位置,到达又离开,存在重复的数据移动,为了尽可能的避免这种事情的发生于是出现了快速排序。算法描述{36,36,97,75,61,19,26,49}:

  1. 选取序列的第一个元素keys[i]38作为基准值vot,空出keys[i]的值
  2. 在序列后端寻找一个小于基准值的元素,交换到序列前端。即比较keys[j]元素26与基准值的大小。若小则将keys[j]元素26移动到keys[i]位置,i++,此时keys[j]位置空出
  3. 在序列前端寻找大于基准值的元素,交换到序列后端。再比较keys[i]元素97与基准值,若大则将keys[i]元素97移动到序列后端的keys[j]位置,j–,keys[i]位置空出。不移动与基准值相等的元素
  4. 重复执行2,3步骤。直到i==j,表示序列中的每一个元素都与基准值比较过了。并且已经将小于基准值的元素移动到前端,将大于基准值的元素移动到了后端。当前i(j)的位置则是基准值的最终位置。
  5. 一趟快速排序将数据序列划分为两个子序列,范围分别为begin~j-1,i+1~end。每个子序列较短,再对两个子序列分别进行快速排序,直到子序列长度为1。
  6. 看下面的图,图选的是最后一个为基准。
    这里写图片描述
private static void quickSort(int[] keys,int begin,int end) {
        if (begin<end) {
            int i=begin,j=end,vot=keys[i];
            while(i!=j){
                while (i<j&&keys[j]>=vot) {//从后向前寻找较小值,不移动与基准值相同的值
                    j--;
                }
                if (i<j) {
                    keys[i++] = keys[j];//子序列后端较小元素向前移动,等同于keys[i] = keys[j];i++;
                }
                while (i<j&&keys[i]<=vot) {//从前向后寻找较大值,不移动与基准值相等元素
                    i++;
                }
                if (i<j) {
                    keys[j--] = keys[i];//子序列前端较大值向后移动
                }
            }
            keys[i] = vot;//基准值到达最终位置
            quickSort(keys,begin,j-1);
            quickSort(keys,i+1,end);
        }       
    }
  • 时间复杂度
    • 最好情况 每趟排序将序列分成长度最近的两个子序列,时间复杂度为O(n*log2n)
    • 最坏情况 每趟排序将序列分成长度差异很大的两个子序列,时间复杂度为O(n2)
  • 空间复杂度
    • 递归调用需要使用栈来保存参数,栈所占用的空间与递归调用的次数有关,空间复杂度O(n*log2n)~O(n)
  • 当n较大而且数据序列随机排列的时候,快速排序是快速的,当n很小或者基准值轩却不合适的时候,快速排序则较慢
  • 快速排序是不稳定排序
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
直接插入排序: 直接插入排序的基本思想是将一个记录插入到已排好序的有序表中,从而得到一个新的、记录数增加1的有序表。 具体步骤如下: 1.将第一个元素看作是一个有序的子序列,然后从第二个元素开始,依次将每个元素插入到已经排好序的子序列中。 2.将未排序的第一个元素,即a[1]与a[0]比较大小,如果a[1] < a[0],则将a[1]插入到a[0]前面,否则a[1]已经是有序的了。 3.将未排序的第二个元素,即a[2]与已经排好序的子序列比较大小,找到合适的位置插入,依次类推。 简单选择排序: 简单选择排序的基本思想是在未排序的序列中找到最小元素,然后将其放到已排序序列的末尾。 具体步骤如下: 1.将序列分为已排序和未排序部分,初始时已排序部分为空,未排序部分包括所有元素。 2.在未排序部分中找到最小的元素,将其放到已排序部分的末尾。 3.重复步骤2,直到未排序部分为空。 冒泡排序冒泡排序的基本思想是比较相邻的个元素,如果前一个元素比后一个元素大,则交换个元素位置,从而使较大的元素逐渐往后移动。 具体步骤如下: 1.从序列的第一个元素开始,依次比较相邻的个元素,如果前一个元素比后一个元素大,则交换个元素位置。 2.重复步骤1,直到序列中所有相邻的元素都被比较过一次。 3.重复步骤1和步骤2,直到序列中的所有元素都排好序。 快速排序快速排序的基本思想是通过一趟排序将待排序序列分割成独立的部分,其中一部分的所有元素都比另一部分的所有元素小,然后再按照此方法依次对部分继续进行排序,直到整个序列有序。 具体步骤如下: 1.选取一个基准元素,一般选择第一个元素或者最后一个元素。 2.将序列中所有小于基准元素的元素放在基准元素的左边,所有大于基准元素的元素放在基准元素的右边。 3.对左右个子序列分别进行快速排序,直到整个序列有序。 归并排序: 归并排序的基本思想是将个有序的子序列合并成一个有序的序列。 具体步骤如下: 1.将序列分成个子序列,分别进行归并排序。 2.将个有序的子序列合并成一个有序的序列。 3.重复步骤1和步骤2,直到序列有序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值