Quick Sort Algorithm (Improved Bubble Algorithm)

Sitting on the toilet and watching the algorithm: quick sort

The essence of the algorithm is that it is so lively and lively compared to it. . . This article is made by Ah Ha Lei complaining, saying that it is the first time I have seen such a cute variable, which simply subverts my traditional concept of variables as a weapon and algorithm as a race. Are you being bullied by algorithms? Come in and see:

Author: Ah Ha Lei Source: 51CTO Blog | 2014-03-03 16:44

[Free for a limited time] The strongest cloud computing conference at the end of the year, see how traditional, community, and Internet companies collide?


Fast and economical sorting algorithm

Is there a sorting algorithm that does not waste space and can be faster? That's "quick sort"! Just hearing the name makes you feel very high-end.

Suppose we now sort the 10 numbers "6 1 2 7 9 3 4 5 10 8". First, find a random number in this sequence as the reference number (don't be frightened by this term, it is a number used for reference, and you will know what it is used for later). For convenience, let the first number 6 be the base number. Next, you need to put all numbers larger than the reference number in the sequence to the right of 6, and numbers smaller than the reference number to the left of 6, similar to the following arrangement:

3  1  2 5  4  6  9 7  10  8

In the initial state, the number 6 is in the first position of the sequence. Our goal is to move 6 to a position in the middle of the sequence, let's say that position is k. Now we need to find this k, and take the kth bit as the dividing point, the numbers on the left are all less than or equal to 6, and the numbers on the right are all greater than or equal to 6. Come to think of it, is there a way you can do this?

Sorting Algorithm Shows Magical Power

The method is actually very simple: start "probing" from both ends of the initial sequence "6 1 2 7 9 3 4 5 10 8". First find a number less than 6 from right to left , then find a number greater than 6 from left to right, and then swap them. Two variables i and j can be used here, pointing to the leftmost and rightmost of the sequence, respectively. We give these two variables nice names "sentry i" and "sentry j". At the beginning, let the sentinel i point to the leftmost of the sequence (ie i=1), pointing to the number 6. Let sentinel j point to the far right of the sequence (ie = 10), pointing to the number.

094811yilrz1tkzkvlrriz.png

First sentinel j began to dispatch. Because the base number set here is the leftmost number, it is very important that sentinel j is dispatched first ( please think about why ). Sentinel j moves to the left step by step (i.e. j--) until it finds a number less than 6 and stops. Next, the sentinel i moves to the right step by step (i.e. i++) until it finds a number greater than 6 and stops. Finally, sentinel j stopped in front of the number 5, and sentinel i stopped in front of the number 7.

095430axy0qkhxxkktkktk.png

095437kdandfxhbtokk2qh.png

Now swap the values ​​of the elements pointed to by sentinel i and sentinel j. The sequence after the swap is as follows:

6  1  2  5  9 3  4  7  10  8

095448k1kevwlz41373e7k.png

095458ejza15wscjv7iw5c.png

At this point, the first exchange is over. Next, sentinel j continues to move to the left (a friendly reminder that sentinel j must start first each time). He found 4 (smaller than the benchmark number 6, which satisfies the requirement) and stopped. Sentinel i also continued to move to the right. He found 9 (larger than the reference number 6, which meets the requirements) and stopped. At this point, the exchange is performed again, and the sequence after the exchange is as follows:

6  1  2 5  4  3  9  7 10  8

第二次交换结束,“探测”继续。哨兵j继续向左挪动,他发现了3(比基准数6要小,满足要求)之后又停了下来。哨兵i继续向右移动,糟啦!此时哨兵i和哨兵j相遇了,哨兵i和哨兵j都走到3面前。说明此时“探测”结束。我们将基准数6和3进行交换。交换之后的序列如下:

3  1 2  5  4  6  9 7  10  8

095506uz7e1uuukcblhkxv.png

095514cag5fumuqqg5jnsw.png

095530e0jf6p0y6aaaw2ir.png

到此第一轮“探测”真正结束。此时以基准数6为分界点,6左边的数都小于等于6,6右边的数都大于等于6。回顾一下刚才的过程,其实哨兵j的使命就是要找小于基准数的数,而哨兵i的使命就是要找大于基准数的数,直到i和j碰头为止。

OK,解释完毕。现在基准数6已经归位,它正好处在序列的第6位。此时我们已经将原来的序列,以6为分界点拆分成了两个序列,左边的序列是“3  1 2  5  4”,右边的序列是“9  7  10  8”。接下来还需要分别处理这两个序列。因为6左边和右边的序列目前都还是很混乱的。不过不要紧,我们已经掌握了方法,接下来只要模拟刚才的方法分别处理6左边和右边的序列即可。现在先来处理6左边的序列现吧。

左边的序列是“3  1  2 5  4”。请将这个序列以3为基准数进行调整,使得3左边的数都小于等于3,3右边的数都大于等于3。好了开始动笔吧

如果你模拟的没有错,调整完毕之后的序列的顺序应该是:

2  1  3  5  4

OK,现在3已经归位。接下来需要处理3左边的序列“2 1”和右边的序列“5 4”。对序列“2 1”以2为基准数进行调整,处理完毕之后的序列为“1 2”,到此2已经归位。序列“1”只有一个数,也不需要进行任何处理。至此我们对序列“2 1”已全部处理完毕,得到序列是“1 2”。序列“5 4”的处理也仿照此方法,最后得到的序列如下:

1  2  3 4  5  6 9  7  10  8

对于序列“9  7  10  8”也模拟刚才的过程,直到不可拆分出新的子序列为止。最终将会得到这样的序列,如下

1  2  3 4  5  6  7  8 9  10

到此,排序完全结束。细心的同学可能已经发现,快速排序的每一轮处理其实就是将这一轮的基准数归位,直到所有的数都归位为止,排序就结束了。下面上个霸气的图来描述下整个算法的处理过程。

232129ogop8gk0r8y7l70k.png

这是为什么呢?

快速排序之所比较快,因为相比冒泡排序,每次交换是跳跃式的。每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样每次只能在相邻的数之间进行交换,交换的距离就大的多了。因此总的比较和交换次数就少了,速度自然就提高了。当然在最坏的情况下,仍可能是相邻的两个数进行了交换。因此快速排序的最差时间复杂度和冒泡排序是一样的都是O(N2),它的平均时间复杂度为O(NlogN)。其实快速排序是基于一种叫做“二分”的思想。我们后面还会遇到“二分”思想,到时候再聊。先上代码,如下

 
                            
  1. #include <stdio.h> 
  2. int a[101],n;//定义全局变量,这两个变量需要在子函数中使用 
  3. void quicksort(int left,int right) 
  4.     int i,j,t,temp; 
  5.     if(left>right) 
  6.        return
  7.                                 
  8.     temp=a[left]; //temp中存的就是基准数 
  9.     i=left; 
  10.     j=right; 
  11.     while(i!=j) 
  12.     { 
  13.                    //顺序很重要,要先从右边开始找 
  14.                    while(a[j]>=temp && i<j) 
  15.                             j--; 
  16.                    //再找右边的 
  17.                    while(a[i]<=temp && i<j) 
  18.                             i++; 
  19.                    //交换两个数在数组中的位置 
  20.                    if(i<j) 
  21.                    { 
  22.                             t=a[i]; 
  23.                             a[i]=a[j]; 
  24.                             a[j]=t; 
  25.                    } 
  26.     } 
  27.     //最终将基准数归位 
  28.     a[left]=a[i]; 
  29.     a[i]=temp; 
  30.                              
  31.     quicksort(left,i-1);//继续处理左边的,这里是一个递归的过程 
  32.     quicksort(i+1,right);//继续处理右边的 ,这里是一个递归的过程 
  33. int main() 
  34.     int i,j,t; 
  35.     //读入数据 
  36.     scanf("%d",&n); 
  37.     for(i=1;i<=n;i++) 
  38.                    scanf("%d",&a[i]); 
  39.     quicksort(1,n); //快速排序调用 
  40.                              
  41.     //输出排序后的结果 
  42.     for(i=1;i<=n;i++) 
  43.         printf("%d ",a[i]); 
  44.     getchar();getchar(); 
  45.     return 0; 
可以输入以下数据进行验证

1061279345108

运行结果是

12345678910

涨姿势环节

Quicksort was proposed by CAR Hoare (Charles Antony Richard Hoare) in 1960, and many others have made further optimizations since then. If you're interested in quicksort, check out Tony Hall's 1962 Computer Journal paper "Quicksort" and Chapter 7 of "Introduction to Algorithms." The quicksort algorithm was only the first display of Tony Hall's talent in the computer field. Later, he was appreciated and reused by his boss, and the company wanted him to design a new high-level language for new machines. You have to know that there was no such advanced stuff as PASCAL or C language at that time. Later, Tony Hall participated in the "ALGOL 60" training course held by Edsger Wybe Dijkstra (the winner of the Turing Award in 1972, we will talk about this great god later), he felt that he was not sure about it. To design a new language, it is better to improve the existing "ALGOL 60" so that it can be used on the company's new machines. So he designed a subset version of the "ALGOL 60". This version was second to none among the various versions of the "ALGOL 60" at that time in terms of execution efficiency and reliability, so Tony Hall was valued by the international academic community. Later, he also invented the well-known "case" statement in the design of "ALGOL X", which was later widely used by various high-level languages, such as PASCAL, C, Java and so on. Of course, Tony Hall's contributions to the field of computing are many, many more, and he won the Turing Award in 1980.

For more algorithm tutorials, please move to:

http://ahalei.blog.51cto.com/


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325797769&siteId=291194637