基本功之堆排序与快排序
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;
}
}
以上是关于基本功之堆排序与快排序的主要内容,如果未能解决你的问题,请参考以下文章