您的位置:首页 > 编程语言 > Java开发

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

2013-10-21 22:07 316 查看
最近看到一道创新工程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))),





因此,建堆的运行时间是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 node

for(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 stub
HeapSort obj = new HeapSort();	//堆排序

Random ran = new Random();
int[] R = new int
;		//声明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]
;
//initial matrix
for(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 stub
System.out.println("Young Matrix");
Young obj = new Young();
String result = obj.young(obj.getMatrix(4,5),17);
System.out.println(result);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: