基本功之堆排序与快排序

Posted 超级码厉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基本功之堆排序与快排序相关的知识,希望对你有一定的参考价值。

Elgar 简介:  

(1)毕业于国内Top 2名校计算机

(2)在外企、硅谷做过全栈软件工程师

(3)出过10套笔试题,面试人数超过1000人


Elgar自述:

在过去的10年的工作生涯中,面试技术人员超过1000人。每次面试我必然会考求职者两个算法,一个是快速排序,一个是将二叉排序树转化成双向链表。 令人惊讶的是,能将快速排序写出来的人居然不超过40%;能同时将两个算法都写出来的人不超过5%。求职者中,不乏清华、北大、悉尼大学、加州大学洛杉矶分校等知名学校的毕业生,也不乏宣称算法精通的职场高手。为什么通过率如此之低? 我想大概是基础不扎实,缺乏思考、总结与实践。实际工作中,虽然我们不直接用到算法,但算法的逻辑无处不在。接到一个任务,将任务拆解、优先级划分、与他人协作,这些事情都是需要逻辑的。好了,废话少说。先来两道基础算法题。


一、快速排序

原理:

(1) 通过n次排序,把n个数逐一放到排序后的位置

(2) 每一次排序的过程:选中一个数,通过交换,把所有小于该数的数排在其左边,把所有大于该数的数排在其右边

  (3)  两根指针,一个游标: 每次排序把数组的第一个数选成游标,两根指针分别从数组的前后开始与游标比较及需要时进行数据交换,当前后指针相遇时,把游标指向的第一个数与前后指针相遇的数交换

  (4)  递归把前后指针相遇索引处的前后两组数分别进行排序


public class QuickSort {
public void quickSort(int[] arrs, int start, int end) {
if(start >= end || arrs == null || arrs.length < 2) { return; }
int pivot = start; int i = start; int j = end;
while(i != j) { while( (i < j) && (arrs[j] >= arrs[pivot])) { j--; } while((i < j) && arrs[i] <= arrs[pivot]) { i++; } if(i < j) { int tmp = arrs[i]; arrs[i] = arrs[j]; arrs[j] = tmp; } }
int swap = arrs[pivot]; arrs[pivot] = arrs[i]; arrs[i] = swap;
quickSort(arrs, start, i - 1); quickSort(arrs, i + 1, end); }
public static void main(String[] args) { QuickSort test = new QuickSort(); int[] arrs = {10, 9 ,6, 7, 3, 0, 2, 1}; test.quickSort(arrs, 0 ,arrs.length - 1); for(int i = 0; i < arrs.length; i++) { System.out.println(arrs[i]); }
}}


二、堆排序

原理:

(1)所谓堆,是将以数组形式存储的数据结构逻辑上转换成完全二叉树,且对于非叶子节点满足如下定义:

arrs[i] >= arrs[2 * i + 1];

arrs[i] >= arrs[2 * i + 2];

需要调用[arrs.length / 2] 次可以判断是否为堆


(2)完全二叉树

一颗深度为k的二叉树,有n个节点,对这颗树进行编号,如果所有的编号跟满二叉树对应,那么这颗树是满二叉树。

满二叉树: 一个深度为k,节点个数为2^k - 1的二叉树为满二叉树

 

(3)建堆 -> 调整节点 -> 排序    


/*1.build heap   2.adjust heap  3.heap sort     minimum heap * full binary tree * */public class HeapSort1 { //build heap的过程就是从第n/2个数元素到0个元素adjust的过程 public void buildHeap(int[] heap,int size){ if(heap==null||heap.length==0){ return; } int index = size/2 - 1; for(int i = index; i >= 0; i--){ headAdjust(heap,i,size); } return; } /* 1. 先把root root.left root.right 三者最小值得index求出来 * 2. 若 root不是最小值,则swap(root,minIndex,size),然后递归 headAdjust(heap,minIndex,size) * */ public void headAdjust(int[] heap,int index,int size){ int left = index * 2 + 1; int right = index * 2 + 1; int minIndex = index;  if(left < size && heap[minIndex] > heap[left]){ minIndex = left; }  if(right < size && heap[minIndex] > heap[right]){ minIndex = right; }  if(minIndex != index){ swap(heap,index,minIndex); headAdjust(heap,minIndex,size); }   return } /* build heap => 0与 index-i(i range:1,2,...,index-1) 逐步交换 * 1.把第0个元素与第n-1个元素swap,然后build第0到第n-2个元素 * */ public void heapSort(int[] heap){ int size = heap.length; buildHeap(heap,size); int index; for(index = size - 1; index > 0; index--){ swap(heap,0,index); headAdjust(heap,0,index - 1); } }  public void swap(int[] heap,int indexA,int indexB){ int tmp = heap[indexA]; heap[indexA] = heap[indexB]; heap[indexB] = tmp; }  } 


以上是关于基本功之堆排序与快排序的主要内容,如果未能解决你的问题,请参考以下文章

Java八大基本排序之堆排序

基本排序算法之堆排序

基本排序算法之堆排序

算法排序02——归并排序介绍及其在分治算法思想上与快排的区别(含归并代码)

八大排序之堆排序

排序之堆排序