二叉堆相关

本文介绍了二叉堆,它具有完全二叉树特征,采用数组存储,父节点与子节点值有大小关系。阐述了二叉堆的插入、删除、构建三个主要操作,还说明了堆排序的步骤、实现方法,分析了其空间复杂度为O(1),时间复杂度为O(nlogn),最后提及与快速排序对比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二叉堆博客:https://www.cnblogs.com/kubidemanong/p/9711705.html

二叉堆的特点:
  1.具有完全二叉树的特征:https://www.cnblogs.com/daniumeng/p/8598097.html 

             满二叉树是一颗特殊的完全二叉树,但完全二叉树不一定是满二叉树

             完全二叉树,除了最下一层k以外,每一层都有2^(k-1)个节点

             不同的是,二叉树一般菜用链表的方式来实现,但是二叉堆采用数组的方式来存储。

             根据完全二叉树的特点,假如一个节点的下标为n,则可以求得他的左孩子下标为2*n+1,右孩子为2*n+2

  2.任何一个父节点的值都大于等于他左右子节点的值,或者小于等于它左右子节点的值

 

二叉堆的三个主要操作:

 1.插入:本着插入节点后,其依然是完全二叉树的规则,将新节点插到完全二叉树的最后一个位置

              然后进行调整,让新插入的节点与其父节点进行比较,若新节点小于父节点,则让新节点上浮,然后继续与新的父节点进行比较,知道夫几点的值小于或者等于该节点,才停止,完成插入操作

  2.删除:一般对根节点进行删除操作,本着插入节点后,依然是完全二叉树的规则,所以删除根节点后,用二叉树的最后一个元素顶替上来,然后再经i选哪个调整,与其子节点比较,判断两个子节点哪个更小,然后与其父节点比较,如果父节点大,那么交换节点,再往下进行比较,直到子节点大于等于父节点为止,完成删除操作

  3.构建二叉堆:将一个无序的完全二叉树调整成二叉堆,那么需要将所有的非叶子节点一次下沉。下沉的顺序是从最后一个非叶子节点开始,一次往上。

 

堆排序的步骤:  https://yq.aliyun.com/articles/638038

1.把无序数组构建成二叉堆

2.循环删除堆顶元素,以到集合尾部,调节堆产生新的堆顶

那么如何实现:

有一个无序数组,通过从下往上的顺序,将除了最后一行的每个元素下沉变成最大堆 

然后再通过(length-1)--的方式循环删除堆顶元素(交换栈顶元素)并调节产生新的堆顶

直到i=0为止

package three;

import java.util.Arrays;

//最大堆
public class HeapSort {

	/**
	 * 
	 * 下沉调整
	 * 
	 * @param array
	 *            待调整的堆
	 * 
	 * @param parentIndex
	 *            要下沉的父节点
	 * 
	 * @param parentIndex
	 *            堆的有效大小
	 * 
	 */

	public static void downAdjust(int[] array, int parentIndex, int length) {

		// temp保存父节点值,用于最后的赋值

		int temp = array[parentIndex];

		int childIndex = 2 * parentIndex + 1;

		while (childIndex < length) {

			// 如果有右孩子,且右孩子大于左孩子的值,则定位到右孩子

			if (childIndex + 1 < length && array[childIndex + 1] > array[childIndex]) {

				childIndex++;

			}

			// 如果父节点小于任何一个孩子的值,直接跳出

			if (temp >= array[childIndex])

				break;

			// 无需真正交换,单向赋值即可

			array[parentIndex] = array[childIndex];

			parentIndex = childIndex;

			childIndex = 2 * childIndex + 1;

		}

		array[parentIndex] = temp;

	}

	/**
	 * 
	 * 堆排序
	 * 
	 * @param array
	 *            待调整的堆
	 * 
	 */

	public static void heapSort(int[] array) {

		// 1.把无序数组构建成二叉堆。

		for (int i = (array.length - 2) /

				2; i >= 0; i--) {
			downAdjust(array, i, array.length);

		}

		System.out.println(Arrays.toString(array));

		// 2.循环删除堆顶元素,移到集合尾部,调节堆产生新的堆顶。

		for (int i = array.length - 1; i > 0; i--) {

			// 最后一个元素和第一元素进行交换

			int temp = array[i];

			array[i] = array[0];

			array[0] = temp;

			// 下沉调整最大堆

			downAdjust(array, 0, i);

		}

	}

public static void main(String[] args) {

int[] arr = new int[] {1,3,2,6,5,7,8,9,10,0};

heapSort(arr);

System.out.println(Arrays.toString(arr));

}
}

堆排序的空间和时间复杂度:

 空间复杂度:O(1) 因为没有占用额外的空间

时间复杂度:O(logn) 第一步需要进行n/2次循环,每次都要排序一次,计算规模:n/2 * logn

                                       第二步需要进行n-1次循环,每次都要排序一次,计算规模:(n-1)*logn

                                      由于两者是并列关系,所以整体的时间复杂度同样是O(nlogn)

 

 

堆排序与快速排序的相同不同点:??  https://yq.aliyun.com/articles/638038

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值