排序
排序分为简单排序和高级排序,简单排序包括冒泡排序、选择排序、插入排序等;高级排序分为快速排序、归并排序、希尔排序等。
冒泡排序、选择排序、插入排序参考文章
插入排序
插入排序是简单排序中最快的排序算法,虽然时间复杂度仍然为O(n*n),但是却比冒泡排序和选择排序快很多。
(1)原理:
1、将指针指向某个元素,假设该元素左侧的元素全部有序,将该元素抽取出来,然后按照从右往左的顺序分别与其左边的元素比较,遇到比其大的元素便将元素右移,直到找到比该元素小的元素或者找到最左面发现其左侧的元素都比它大,停止;
2、此时会出现一个空位,将该元素放入到空位中,此时该元素左侧的元素都比它小,右侧的元素都比它大;
3、指针向后移动一位,重复上述过程。每操作一轮,左侧有序元素都增加一个,右侧无序元素都减少一个。
(2)例子:
待比较数据:7, 6, 9, 8, 5,1
1. 第一轮:指针指向第二个元素6,假设6左面的元素为有序的,将6抽离出来,形成7,,9,8,5,1,从7开始,6和7比较,发现7>6。将7右移,形成,7,9,8,5,1,6插入到7前面的空位,结果:6,7,9,8,5,1
2. 第二轮:指针指向第三个元素9,此时其左面的元素6,7为有序的,将9抽离出来,形成6,7,_,8,5,1,从7开始,依次与9比较,发现9左侧的元素都比9小,于是无需移动,把9放到空位中,结果仍为:6,7,9,8,5,1
3. 第三轮:指针指向第四个元素8,此时其左面的元素6,7,9为有序的,将8抽离出来,形成6,7,9,,5,1,从9开始,依次与8比较,发现8<9,将9向后移,形成6,7,,9,5,1,8插入到空位中,结果为:6,7,8,9,5,1
4. 第四轮:指针指向第五个元素5,此时其左面的元素6,7,8,9为有序的,将5抽离出来,形成6,7,8,9,,1,从9开始依次与5比较,发现5比其左侧所有元素都小,5左侧元素全部向右移动,形成,6,7,8,9,1,将5放入空位,结果5,6,7,8,9,1。
5. 第五轮:同上,1被移到最左面,最后结果:1,5,6,7,8,9。
快速排序
首先上图:
从图中我们可以看到:
left指针,right指针,base参照数。
其实思想是蛮简单的,就是通过第一遍的遍历(让left和right指针重合)来找到数组的切割点。
第一步: 首先我们从数组的left位置取出该数(20)作为基准(base)参照物。
第二步: 从数组的right位置向前找,一直找到比(base)小的数,
如果找到,将此数赋给left位置(也就是将10赋给20),
此时数组为:10,40,50,10,60,
left和right指针分别为前后的10。
第三步: 从数组的left位置向后找,一直找到比(base)大的数,
如果找到,将此数赋给right的位置(也就是40赋给10),
此时数组为:10,40,50,40,60,
left和right指针分别为前后的40。
第四步: 重复“第二,第三“步骤,直到left和right指针重合,
最后将(base)插入到40的位置,
此时数组值为: 10,20,50,40,60,至此完成一次排序。
第五步: 此时20已经潜入到数组的内部,20的左侧一组数都比20小,20的右侧作为一组数都比20大,
以20为切入点对左右两边数按照"第一,第二,第三,第四"步骤进行,最终快排大功告成。
快速排序具有最好的平均性能(average behavior),但最坏性能(worst case behavior)和插入排序
相同,也是O(n^2)。 尽管如此,需要排序的情况几乎都是乱序的,自然性能就保证了。据书上的测试图来看,在数据量小于20的时候,插入排序具有最好的性能。当大于20时,快速排序具有最好的性能,归并(merge sort)和堆排序(heap sort)也望尘莫及,尽管复杂度都为nlog2(n)。
LeetCode 148 链表排序题
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
java实现
class Solution {
public ListNode sortList(ListNode head) {
//采用快速排序
qSort(head, null);
return head;
}
public static void qSort(ListNode head, ListNode end) {
if (head != end) {
ListNode node = partion(head, end);
qSort(head, node);
qSort(node.next, end);
}
}
public static ListNode partion(ListNode head, ListNode end) {
ListNode left = head, right = head.next;
//走到末尾才停
while (right != end) {
//大于key值时,left向前走一步,交换left与right的值
if (right.val < head.val) {
left = left.next;
int temp = left.val;
left.val = right.val;
right.val = temp;
}
right = right.next;
}
if (left != head) {
int temp = left.val;
left.val = head.val;
head.val = temp;
}
return left;
}
}
leetcode 测试平台:
python实现
python实现,但超时,暂时不清楚原因
class Solution:
def sortList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
self.quicksort(head,None)
return head
def quicksort(self,head, end):
if head!=end:
node = self.partion(head,end)
self.quicksort(head, node)
self.quicksort(node.next, end)
def partion(self, head, end):
p1 = head
p2 = head
while p2!=end:
if p2.val<head.val:
p1 = p1.next
temp = p1.val
p1.val = p2.val
p2.val = temp
p2 = p2.next
if p1 != head:
temp = p1.val
p1.val = head.val
head.val = temp
return p1