java之堆排序

java之堆排序

直接上代码:
--------------------------------------------------------
package com.mylearn;

import java.util.*;

/**
 * 本程序是进行堆排序 首先需要明白堆是一种特殊的完全二叉树,并且它的孩子结点永远小于父母结点 —— 基本思想:
 * 堆排序是一种树形选择排序,是对直接排序算法的有效改进。堆的定义如下:具有n个元素的序列(h1,h2,…,hn),当且仅当满足(hi>=h2i,hi>=2i
 * +1)或(hi<=h2i,hi<=2i+1)
 * (i=1,2,…,n/2)时称之为堆。在这里只讨论满足前者条件的堆。由堆的定义可以看出,堆顶元素(即第一个元素)必为最大项(大顶堆)。
 * 完全二叉树可以很直观地表示堆的结构。堆顶为根,其它为左子树、右子树。初始时把要排序的数的序列看作是一棵顺序存储的二叉树,调整它们的存储序,使之成为一个堆,
 * 这时堆的根节点的数最大。然后将根节点与堆的最后一个节点交换。然后对前面(n-1)个数重新调整使之成为堆。依此类推,直到只有两个节点的堆,并对它们作交换,
 * 最后得到有n个节点的有序序列。从算法描述来看,堆排序需要两个过程,一是建立堆,二是堆顶与堆的最后一个元素交换位置。所以堆排序有两个函数组成。
 * 一是建堆的渗透函数,二是反复调用渗透函数实现排序的函数。
 * 
 * @author H
 *
 */

public class DuiPaiXu
   
     {

	public static void main(String[] args) {
		// 声明一个列表,存储数据
		Integer[] list = { 1, 0, -2, 3, 5, 1, 2, 10, 11, 21, 3, 2 };
		heapsort(list);

		for (Integer element : list)
			System.out.println(element);
	}

	/*
	 * 首先编写堆类 堆类用线性列表来存储数据
	 * 
	 */
	private ArrayList
    
      list = new ArrayList
     
      ();

	public DuiPaiXu(E[] objects) {
		for (int i = 0; i < objects.length; i++)
			add(objects[i]);
	}

	public DuiPaiXu() {

	}

	public void add(E object) {
		list.add(object);
		int currentindex = list.size() - 1;

		while (currentindex > 0) {
			int parentindex = (currentindex - 1) / 2;
			/*
			 * 如果父类结点小于子类结点,则将它们交换值 这个过程一直持续到父类结点不再小于子类结点为止
			 */
			if (list.get(parentindex).compareTo(list.get(currentindex)) < 0) {
				E temp = list.get(currentindex);
				list.set(currentindex, list.get(parentindex));
				list.set(parentindex, temp);
			} else
				break;
			currentindex = parentindex;// 把新加的数的下标更新
		}
	}

	@SuppressWarnings("unchecked")
	public E remove() {
		if (list.size() == 0)
			return null;
		/*
		 * 基本思想是 remove()方法只能移除根处的元素 然后重新组建堆 首先把最后一个元素移到根处
		 * 然后将根与它的结点进行比较,若小于其子结点,则交换下移即可 直到下标最大为止
		 */
		E removedObject = list.get(0);
		list.set(0, list.get(list.size() - 1));
		list.remove(list.size() - 1);

		int currentindex = 0;
		while (currentindex < list.size()) {
			int leftchildindex = 2 * currentindex + 1;// 左孩子
			int rightchildindex = 2 * currentindex + 2;// 右孩子

			if (leftchildindex >= list.size())
				break;
			/*
			 * 下面语句确定左边子结点与右边子结点的大小 以便将父结点与最大的子结点进行比较 进而确定是否执行交换动作
			 */
			int maxindex = leftchildindex;
			if (rightchildindex < list.size()) {
				if (list.get(maxindex).compareTo(list.get(rightchildindex)) < 0)
					maxindex = rightchildindex;
			}

			/*
			 * 下面开始执行交换动作 若父结点比最大的子结点要小 则交换它们
			 */
			if (list.get(currentindex).compareTo(list.get(maxindex)) < 0) {
				E temp = list.get(currentindex);
				list.set(currentindex, list.get(maxindex));
				list.set(maxindex, temp);
				currentindex = maxindex;
			}
			/*
			 * 直到父结点不再小于最大的子结点为止
			 */
			else
				break;
		}
		return removedObject;
	}

	public static 
      
        void heapsort(E[] list) {
		DuiPaiXu
       
         heap = new DuiPaiXu
        
         (); for (int i = 0; i < list.length; i++) heap.add(list[i]); for (int i = list.length - 1; i >= 0; i--) list[i] = heap.remove(); } }
        
       
      
     
    
   

------------------------------------------------------------------------------------------------------------------------------------

更多请关注:FlyTester,关注技术的测试

QQ群:456850134

web站:www.flytester.org

微信扫描二维码关注:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值