排序算法5--交换排序--快速排序

快速排序

1.快速排序是有冒泡排序改进的来的。在冒泡排序的过程中,只对相邻的两个记录进行比较,因此每次交换两个相邻记录时只能消除一个逆序。如果通过两个不相邻记录进行交换,消除多个逆序,则会大大加快排序的速度。快速排序方法中一次交换可以消除多个逆序

算法方法:

  从右侧找第一个比key值小的进行交换,从左侧找第一个比key值大的进行交换,但是交换的并非是key值
  最后得到key值左边都是比key小的,右边是比key大的,但是左右区间并不一定是有序的,需要进行递归调用
  元素正序和逆序时效果最差,数据越无序,效果越好

例如:

    初始:   3 5 6 2 4 1(3作为key值,从后向前找第一个比3小的值为1,与3交换;从前向后找第一个比3大的值5与3交换,前面的逐渐加1,后面的逐渐减1,直到到同一个位置)
  第一步:1 2 3 6 4 5 (3左边都是比3小的,3后面都是比3大的,但是区间内部不一定是有序的,需要进行递归再次调整)
  第二步:1 2 3 6 4 5 
  第三步:1 2 3 6 4 5 
  第四步:1 2 3 5 4 6 
  第五步:1 2 3 4 5 6

  第六步:1 2 3 4 5 6

数据结构课本上有一个例子:

2.时间复杂度

最好情况下(每一趟排序后都能将记录序列均匀的分割成两个长度大致相等的子表,类似折半查找)时间复杂度是O(logn)

最坏情况(在待排序序列已经排好序的情况下,其递归成单只树,每次划分只能得到一个比上一次少一个记录的子序列)时间复杂度是O(n)

平均时间复杂度是O(nlogn)

具体时间复杂度等分析,请参考:http://www.cnblogs.com/zhangxue521/p/6748085.html

3.算法特点

①.记录非顺次的移动导致排序方法是不稳定的

②.排序过程中需要定位表的上界和下界,所以适合顺序存储,不适合链式

③.元素正序和逆序时效果最差,数据越无序,效果越好

java实现:

 1 package 平时常用;
 2
 3 import java.util.Scanner;
 4
 5 public class _3快速排序 {
 6   public static void main(String[] args) {
 7       int a[] = new int[6];
 8       Scanner scanner = new Scanner(System.in);
 9       for (int i = 0; i < a.length; i++) {
10           a[i] = scanner.nextInt();
11       }
12       sort(a, 0, a.length - 1);
13       for (int m : a) {
14           System.out.print(m+" ");
15       }
16
17   }
18   public static void sort(int a[],int low,int high){
19       int key = a[low];//基数
20       int start = low;
21       int end = high;
22       //从前往后找比基数大的放基数右边,从后往前找比基数小的放基数左边
23       while(end >start){//从两端交替向中间交换
24           //从后往前找,找比关键值小的,如果没有小的,end--
25           while(end >start && a[end] >= key) end--;
26           if (a[end] <= key) {//找到比key值小的了,交换位置
27               int temp = a[end];
28               a[end] = a[start];
29               a[start] = temp;
30           }
31         //从前往后找,找比关键值大的,如果没有大的,strat++
32           while(end >start && a[start] <= key) start++;
33           if (a[start] >= key) {//找到比key值小的了,交换位置
34               int temp = a[start];
35               a[start] = a[end];
36               a[end] = temp;
37           }
38         //此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
39       }
40       //测试每轮的输出
41 //      for (int m : a) {
42 //            System.out.print(m+" ");
43 //        }
44 //        System.out.println();
45 //        递归
46       key = a[start];
47       if(start>low) sort(a,low,start-1);//左边序列。第一个索引位置到关键值索引-1
48       if(end<high) sort(a,end+1,high);//右边序列。从关键值索引+1到最后一个
49   }
50 }

js实现:

 1 function kuaisuSort(a,low,high){
 2     var start=low;
 3     var end = high;
 4     var key = a[low];
 5     var temp;
 6     while(start < end){
 7         //从后往前
 8         while(start <end&&a[end]>=key) end--;
 9         if(a[end]<key){
10             temp = a[end];
11             a[end] = a[start];
12             a[start] = temp;
13         }
14         //从前往后
15         while(start <end&&a[start] <=key) start++;
16         if(a[start] > key){
17             temp = a[start];
18             a[start] = a[end];
19             a[end] = temp;
20         }
21     }
22     key = a[start];
23     if(start > low) kuaisuSort(a,low,start-1);
24     if(end < high) kuaisuSort(a,end+1,high);
25 }
26 var a = new Array(7,2,6,5,1,4,3);
27 kuaisuSort(a,0,a.length);
28 document.write("_5快速排序:"+a +"<br />");
时间: 2024-08-26 16:47:00

排序算法5--交换排序--快速排序的相关文章

常用排序算法实现[交换排序之冒泡排序、快速排序]

相关知识 1. 稳定排序和非稳定排序: 稳定排序算法会依照相等的关键(换言之就是值)维持纪录的相对次序. 如果排序算法是稳定的,就是当有两个有相等关键的纪录R和S,且在原本的列表中R出现在S之前,在排序过的列表中R也将会是在S之前. 2. 内排序和外排序 在排序过程中,所有需要排序的数都在内存,并在内存中调整它们的存储顺序,称为内排序: 在排序过程中,只有部分数被调入内存,并借助内存调整数在外存中的存放顺序排序方法称为外排序. 3.算法分类 排序算法从理论上分为如下几类: (1) 交换排序法:

图形化排序算法比较:快速排序、插入排序、选择排序、冒泡排序

图形化排序算法比较:快速排序.插入排序.选择排序.冒泡排序

排序算法学习之快速排序

快速排序基本思想:选取一个枢轴元素(图简单可选第一个),通过对序列一次遍历(中间涉及到数的交换),将该枢轴放置到序列合适位置,保证其左边数都比它小,右边数都比它大,然后利用递归思想对其左右两个子序列进行同样排序. 快熟排序的基本实现过程:将枢轴元素key备份,序列头尾各设置一个游标--i和j,尾部游标j先移动(如果选择的最后一个元素为枢轴则i先移),直到遇到比key小的元素,将其移到原枢轴处覆盖之,此时j处元素空着了,然后再对i进行移动,直到遇到比key大的元素,将其移到右边下表为j的空白处 v

排序算法系列:快速排序算法

概述 在前面说到了两个关于交换排序的算法:冒泡排序与奇偶排序. 本文就来说说交换排序的最后一拍:快速排序算法.之所以说它是快速的原因,不是因为它比其他的排序算法都要快.而是从实践中证明了快速排序在平均性能上的确是比其他算法要快一些,不然快速一说岂不是在乱说? 本文就其原理.过程及实现几个方面讲解一下快速排序算法. 版权声明 著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 作者:Coding-Naga 发表日期:2016年3月1日 链接:http://blog.csdn.n

常用算法之排序算法三【快速排序】

快速排序是东尼·霍尔在1962提出的划分交换排序,并采用一种分治的策略.在这,我们先总结一下:快速排序 = 划分交换排序 + 分治.然后我们在一一介绍他. 划分交换排序 在讨论它时,感觉有种看了崔颢<黄鹤楼>之后,再去写黄鹤楼的感觉,因为MoreWindows写 得白话经典算法系列之六 快速排序 快速搞定已经足够出色了.我在这只是进行简单的复述,你需要了解更多请看他的博文. 先来看看划分交换排序的具体算法描述: 1.从数列中选出一个数作为基准 2.从数组中选出比它大的数放右边,比它小的数放左边

排序算法总结之快速排序

快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序.它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod). 分治法的基本思想 分治法的基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题.递归地解这些子问题,然后将这些子问题的解组合为原问题的解. 快速排序的基本思想 从待排序的数据序列中任取一个数据(如第一个数据)作为分界值,所有比它小的数据元素一律放到左边,所有比它大的数据元素放到右边.这样一趟后,就形成了两个子序列:左序列

排序算法之交换排序

首先,上脑图. 1.为什么要学习排序算法? 这是算法学习的基础,经典的排序算法有着很广泛的用途,一遍遍的被人所使用.而且,在面试找工作的时候,数据结构中的排序算法,也是一个很重要的基本功,经常会被用人单位拿来出题目. 2.如何学习排序算法? 第一步是理解排序算法的原理,这也是最重要的一步. 第二步就是看经典的算法实现,抠细节一个个理解原理到实现经过了哪些变化. 第三部是用纸把算法实现抄一遍,这个时候会发掘出认识和实际的偏差. 第四步是把算法默写出来,这也是很重要的一步,类似于牛吃了食物之后的反刍

js实现两种实用的排序算法——冒泡、快速排序

零:数据准备,给定数组arr=[2,5,4,1,7,3,8,6,9,0]; 一:冒牌排序 1思想:冒泡排序思想:每一次对比相邻两个数据的大小,小的排在前面,如果前面的数据比后面的大就交换这两个数的位置       要实现上述规则需要用到两层for循环,外层从第一个数到倒数第二个数,内层从外层的后面一个数到最后一个数 2特点:排序算法的基础.简单实用易于理解,缺点是比较次数多,效率较低. 3实现: var times=0; var bubbleSort=function(arr){ for(var

排序算法入门之快速排序(java实现)

快速排序也是一种分治的排序算法.快速排序和归并排序是互补的:归并排序将数组分成两个子数组分别排序,并将有序的子数组归并以将整个数组排序,会需要一个额外的数组:而快速排序的排序方式是当两个子数组都有序时,整个数组就自然有序了,快速排序可以不产生额外的数组. 对于小数组(N<=20),快速排序不如插入排序.所以,小数组建议使用其他排序. 快速排序可以由以下几步组成: 1.如果数组S中的元素个数是0或1,则返回. 2.取S中任一元素v,称为枢纽元. 3.将S中其余元素(除枢纽元)分为两部分,一部分是小

三种排序算法(归并排序、快速排序,堆排序)

归并排序:建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列:即先使每个子序列有序,再使子序列段间有序.若将两个有序表合并成一个有序表,称为二路归并. 归并排序算法稳定,数组需要O(n)的额外空间,链表需要O(log(n))的额外空间,时间复杂度为O(nlog(n)),算法不是自适应的,不需要对数据的随机读取. 工作原理: 1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后