冒泡排序和快速排序
冒泡排序
其实冒泡排序和快速排序都属于交换排序的范畴什么是交换排序,可以参照一下前面的希尔排序代码里面的两个元素比较大小交换位置。
同样的冒泡排序也是比较两个元素大小然后交换位置。
这里讲解的代码是从后往前赶同时我们也可以从前往后赶。
从后往前(或从前往后)两两⽐较相邻元素的值,若为逆序(即A[i-1]>A[i]),则交换它们,直到序列⽐较完。称这样过程为“⼀趟”冒泡排序。
接下来演示一下过程
就是这样的从后往前的元素依次比较若是前面个元素大的话就交换位置使得小的个元素在靠前的位置。这样一趟下来两两对比可以使得第一个元素一定是最小的,然后再一次比较剩下的元素关于第一个元素的处理,你要是不考虑复杂度其实也可以对比第一个元素,但是正常来说是不需要对比的
接下来给你们看第二趟
剩下的元素处理过程同上
直到第四回处理结束开始第五次的处理
可以注意到第五次的待处理元素已经是正确的顺序了此时我们在对比也不会交换元素,但是我们必须对比保证代码的连贯性因为机器不知道。但是我们可以用一个标志位来显示是否产生了交换,要是没有说明从小到大的顺序已经排列完毕。
接下里我们看一下代码
接下来进行代码的解释
可以看到swap函数这个就是很基础的C语言交换函数不做解释
接下来我们看代码主体
首先看第一个for循环这个循环控制了循环次数同时对每一次的初始循环交换标记位置为false
接着看第二个循环首先设置对应的位置就是数组的最后一个元素,这里注意一下数组下标和位序的关系就很容易理解了,
用于控制不再和前面已经排好序的数组元素对比了简化一部分操作。
使得j的值不断减小实现从后到前的比较效果。
接着看第二个循环体里面的内容如果前一个元素大于后一个元素就调用swap函数实现位置的交换
同时将交换的标志位设置为true。结束循环,当标志位没变时说明没有发生交换也叫是说排序已经好了如果标志变了则不执行操作直接进入第二次的循环。
对于时间复杂度和空间复杂度的分析直接看PPT
需要强调一下冒泡排序同样适合于链表只是交换函数需要变为指针的切换而已。
快速排序
快速排序是代码题里面常用的暴力解法一定要熟悉。
快速排序最主要的思想分块和划分,找一个基准元素把大于他的和小于他的全部甩到一边通过不断地分块和划分达到有序的目的,接下里我对代码的实现过程演示一下。
首先开始也是两个指针low和high同时选取一个基准元素一般选取第一个元素也就是low初始的元素
然后两两比较元素,找到基准元素的位置
这里给给诀窍针对于手算法,记住谁空着不动谁
对比high和基准元素
发现一样,那就先不管直接后移,后移到27
由于49>27就将27放入low的位置,同时high的位置就空了此时就移动low,low变成38
38小于49元素不变快排的思想分块小于的元素就直接放左边大于的放右边。
65大于49放到后面去
接着移动high
13移到前面去
最后low等于high
再次的对左右分块进行同样的操作
接下来介绍一下代码的实现
看函数的主题内容,调用栈的事情先不要去管,
首先看右面的函数主体部分,
传入数组和low与high的位置关系
如果还是low小于high的话就进入递归,不是的话就跳出递归,比如当只有一个元素了low等于high那么就不需要再分了就直接跳出这一层的递归返回上一层去处理另外一部分的内容
可以观察一下if里面的三个语句
这里先定义一个函数来存储枢轴元素的位置方便于下一层循环的进入也就是对左右半部份的处理。接着看这里划分了左子表范围是low到基准元素-1的位置然后递归,当左面处理完以后就返回上一层处理上一次划分的右半部分的内容,直到所有内容处理完毕。
看左面的函数体,这里理解函数体一定要结合我们前面的函数思想来看。
首先第一次的调用函数是由先前的传参传入数组以及low和high的值,剩下的调用是基于Q函数的递归来传递的参数。
具体内容我们看函数体。
定义枢轴值
然后借助while循环来实现分堆的操作
当low小于high进入循环体,为什么这样设置,当相等的时候就跳出循环体输出基准元素的位置
接下来我们看循环体
大while里面嵌套了两个小的文化循环用于比较交换元素同时移动low与high的位置的功效。
先看第一个首先要确保low小于high同时high的值要大于基准元素,此时high向后移动。为什么要这样因为思想就是如此规定的大于基准元素就不动位置,若小于就放入low的位置。
接着看第一个循环,若是违反循环条件即high小于low时跳出循环将小元素放入low的位置然后low向上加再比较,再次比较时就调用到了第二个循环体也就是当low小于high同时满足low小于基准元素时,一直移动low元素直到违反low大于基准元素的值时需要将low放入high的位置也就是最外面的大层循环。如此往复达到分层的效果,当跳出最外层的while循环时将low所指的位置放入基准元素同时返回基准元素的下标给主函数以方便于下一层的递归。
对于复杂度的分析我们记住平均复杂度就欧克了。