堆排序(JAVA)实现和杨氏矩阵查找

来源:互联网 发布:sql union和union all 编辑:程序博客网 时间:2024/05/22 03:09

         最近看到一道创新工程2014年校招的题目:输入一个整形无序数组,用堆排序的方法使其有序。楼主网上搜罗各种资料,然后自己花了点时间认真的研究一番堆排序。以下为参考的网址:http://student.zjzk.cn/course_ware/data_structure/web/paixu/paixu8.4.2.2.htm(数据结构网站)http://www.cnblogs.com/zabery/archive/2011/07/26/2117103.html堆排序与分析。

一、 堆排序定义
     n个关键字序列Kl,K2,…,Kn称为堆,当且仅当该序列满足如下性质(简称为堆性质):
     (1) ki≤K2i且ki≤K2i+1 或(2)Ki≥K2i且ki≥K2i+1(1≤i≤ )

     若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。
【例】关键字序列(10,15,56,25,30,70)和(70,56,30,25,15,10)分别满足堆性质(1)和(2),故它们均是堆,其对应的完全二叉树分别如小根堆示例和大根堆示例所示。

         

二、大根堆和小根堆

     根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最小者的堆称为小根堆。
     根结点(亦称为堆顶)的关键字是堆里所有结点关键字中最大者,称为大根堆。
  注意:
     ①堆中任一子树亦是堆。
     ②以上讨论的堆实际上是二叉堆(Binary Heap),类似地可定义k叉堆。

    三、堆排序特点
     堆排序(HeapSort)是一树形选择排序。
     堆排序的特点是:在排序过程中,将R[l..n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系【参见二叉树的顺序存储结构】,在当前无序区中选择关键字最大(或最小)的记录。

   四、堆排序与直接插入排序的区别
     直接选择排序中,为了从R[1..n]中选出关键字最小的记录,必须进行n-1次比较,然后在R[2..n]中选出关键字最小的记录,又需要做n-2次比较。事实上,后面的n-2次比较中,有许多比较可能在前面的n-1次比较中已经做过,但由于前一趟排序时未保留这些比较结果,所以后一趟排序时又重复执行了这些比较操作。
     堆排序可通过树形结构保存部分比较结果,可减少比较次数。

五、性能分析

  • 调堆:上面已经分析了,调堆的运行时间为O(h)。
  • 建堆:每一层最多的节点个数为n1 = ceil(n/(2^(h+1))),

image

因此,建堆的运行时间是O(n)。

  • 循环调堆(代码67-74),因为需要调堆的是堆顶元素,所以运行时间是O(h) = O(floor(logn))。所以循环调堆的运行时间为O(nlogn)。
总运行时间T(n) = O(nlogn) + O(n) = O(nlogn)。对于堆排序的最好情况与最坏情况的运行时间,因为最坏与最好的输入都只是影响建堆的运行时间O(1)或者O(n),而在总体时间中占重要比例的是循环调堆的过程,即O(nlogn) + O(1) =O(nlogn) + O(n) = O(nlogn)。因此最好或者最坏情况下,堆排序的运行时间都是O(nlogn)。而且堆排序还是原地算法


六、程序代码:

package cn.edu.test1;import java.util.Random;/** * 堆排序 * 堆排序定义:n个关键字序列Kl,K2,…,Kn称为堆,当且仅当该序列满足如下性质(简称为堆性质):     (1) ki≤K2i且ki≤K2i+1 或(2)Ki≥K2i且ki≥K2i+1(1≤i≤ ) */public class HeapSort {public static int N = 10000000;  //数组的长度/** *  * @param R 待排序数组 */private void buildHeap(int[] R){int length = R.length;int begin = length/2 -1; //The last leaf nodefor(int i=begin;i>=0;i--){heapify(R,length,i);   //adjust heap}}/** * 调整无序为一个新的堆 * @param R 待调整数组R * @param start 调整数组的无序 * @param end  调整数组的无序区结束位置 */private void heapify(int[] R,int hlen,int i){int left =2*i+1;  //节点i的左孩子节点int right =2*i+2;//节点i的右孩子节点int largest = i;int temp;while(left<hlen || right<hlen){if(left<hlen && R[largest]<R[left]){largest = left;}if(right<hlen && R[largest]<R[right]){largest = right;}if(i !=largest){//如果最大值不是父节点,则交换父节点和拥有最大值的子节点交换temp=R[largest];R[largest]=R[i];R[i] =temp;i = largest;//新的父节点,以备迭代调堆left = 2*i+1;//新的子节点right =2*i+2;}else{break;}}}/** * 打印输出数组数据 * @param R */private void printArray(int[] R){int length = R.length;for(int i=0;i<length;i++){System.out.print(R[i]+",");if((i+1)%20==0)System.out.println();}System.out.println();}/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubHeapSort obj = new HeapSort();//堆排序Random ran = new Random();int[] R = new int[N];//声明n+1个数组,R[0]作为交换位for(int i=0;i<N;i++){R[i]=ran.nextInt(N); //}int hlen = R.length;int temp;//obj.printArray(R);//初始化后的输出    obj.buildHeap(R);//init heap  //  obj.printArray(R);//构建堆后的输出        while(hlen>1){    temp = R[hlen-1];    R[hlen-1] = R[0];    R[0] =temp;    hlen--;//堆的大小减一    obj.heapify(R, hlen, 0);  //修改后重新调整堆    }    // System.out.println(hlen);    obj.printArray(R);// System.out.println("堆排序流程");}}

杨氏矩阵:在一个m行n列二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

定位法思路:

定位法,时间复杂度O(m+n)。首先直接定位到最右上角的元素,再配以二分查找,比要找的数(6)大就往左走,比要找数(6)的小就往下走,直到找到要找的数字(6)为止,如下图所示:

Java代码实现:

package cn.edu.test1;/** * 在一个m行n列二维数组中,每一行都按照从左到右递增的顺序排序, * 每一列都按照从上到下递增的顺序排序。请完成一个函数, * 输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 * @author Tomas * */public class Young {/** *  * @param m 矩阵行 * @param n矩阵列 * @return */private int[][] getMatrix(int m,int n){if(m<0 ||n<0)return null;int k = 1;int[][] matrix = new int[m][n];//initial matrixfor(int i=0;i<m;i++){for(int j=0;j<n;j++){matrix[i][j]=k++;}}return matrix;}/** * 杨氏矩阵,定位法解决问题 */public  String young(int[][] matrix,int value){int row = matrix.length;int column = matrix[0].length;int i =0,j=column;while(i<row && j>0){if(matrix[i][j-1]>value){j--;}else if(matrix[i][j-1]<value){i++;}else{return "Find it in "+(i+1)+" row and "+j+" column";}}return "Not Find it";}public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println("Young Matrix");Young obj = new Young();String result = obj.young(obj.getMatrix(4,5),17);System.out.println(result);}}



原创粉丝点击