数据结构C语言版 —— 二叉树的顺序存储堆的实现

Posted 爱敲代码的三毛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构C语言版 —— 二叉树的顺序存储堆的实现相关的知识,希望对你有一定的参考价值。

文章目录


二叉树顺序结构实现(堆)

1. 堆的概念

  • 堆在物理上是一个一维数组,在逻辑上是一颗完全二叉树
  • 满足父亲节点小于等于孩子节点的叫做小堆或者小根堆
  • 满足父亲节点大于等于孩子节点的叫做大堆或者大根堆

堆的孩子和父亲的下标关系

  1. 已知父亲(parent)的下标

    • 左孩子(left)下标等于 l e f t = 2 ∗ p a r e n t + 1 left = 2*parent+1 left=2parent+1
    • 右孩子(right)下标等于 r i g h t = 2 ∗ p a r e n t + 2 right = 2 * parent + 2 right=2parent+2
  2. 已知左孩子或右孩子下标(child)

    • 父亲节点下标等于 p a r e n t = ( c h i l d − 1 ) / 2 parent = (child-1)/2 parent=(child1)/2

2. 堆的基本操作

堆的向下调整算法

下面这个数组逻辑上可以看作是一棵完全二叉树,通过从根节点开的向下调整算法可以把它调整成一个堆(大堆或小堆),向下调整算法有以有一个前提:左右子树必须是一个堆,才能调整。我这里的是实现小堆的向下调整算法

建小堆的向下调整的基本思路就是:从堆顶开始,拿自己和较小的一个孩子进行比较大小,如果小就进行交换然后把交换的位置当作父节点继续向下调整,如果两个孩子都比自己小就停止调整,否则一直调整到叶子节点。

// 向下调整(小堆)
void AdjustDown(HPDataType* arr, int n, int index)

	int parent = index;
	int child = 2 * parent+1;
	while (parent < n)
	
		
		//找出两个孩子里的较小的
		if (child < n && child + 1 < n && arr[child] > arr[child + 1])
		
			child++;
		
		// 拿较小的孩子比较和父亲比价大小
		if (child < n && arr[child] < arr[parent])
		
			Swap(&arr[child], &arr[parent]);
			parent = child;
			child = 2 * parent + 1;
		
		else
		
			//说明无需调整
			break;
		
	

堆的向下调整每次调整的一个节点,假设树的高度为 h h h最坏情况下调整的次数就是 h − 1 h-1 h1,所以向下调整的时间复杂度就是树的深度 l o g 2 ( n − 1 ) log_2(n-1) log2(n1),最后得出 l o g 2 n log_2n log2n

堆的创建

我们知道堆的向下调整算法必须满足左右子树都是一个堆,那有的时候是一个普通的数组,也就是一颗普通的完全二叉树,所以要通过建堆来让一个数组变成堆。

建堆的实现思路:从最后一个节点的父节点,也就是第一个非叶子节点的父亲开始不断向下调整,直到整课树都被调整成一个堆。

//向下调整建堆
int i = 0;
//从倒数第一个非叶子节点开始向下调整
for (i = (n - 2) / 2; i >= 0; --i)//n为数组元素个数

    AdjustDown(arr,n ,i);

建堆的时间复杂度

我们知道时间复杂度就是计算最坏的时间复杂度,实际上就是计算一个满二叉树,这样每一棵树都会进行调整。

假设这一棵树的高度是 h h h

  1. 第一层的节点个数就是 2 0 2^0 20、第二层 2 1 2^1 21、第三层 2 2 2^2 22,第 n n n层就有 2 n − 1 2^n-1 2n1个,那么最后一层就有 2 h − 1 2^h-1 2h1个节点
  2. 每一层调整的高度:第一层 h − 1 h-1 h1、第二层 h − 2 h-2 h2、…、1

那么假设时间复杂度为 T n T_n Tn,时间复杂度就是从第一层到倒数第二层每个节点的调整次数之和

  • 时间复杂度: T ( n ) = 2 0 ∗ ( h − 1 ) + 2 1 ∗ ( h − 2 ) + 2 2 ∗ ( h − 3 ) + 2 3 ∗ ( h − 4 ) + . . . + 2 h − 3 ∗ 2 + 2 h − 2 ∗ 1 T(n) = 2^0*(h-1)+2^1*(h-2)+2^2*(h-3)+2^3*(h-4)+...+2^h-3*2+2^h-2*1 T(n)=20(h1)+21(h2)+22(h3)+23(h4)+...+2h32+2h21
  • 等式两边同时乘2: 2 ∗ T ( n ) = 2 1 ∗ ( h − 1 ) + 2 2 ∗ ( h − 2 ) + 2 3 ∗ ( h − 3 ) + 2 4 ∗ ( h − 4 ) + . . . + 2 h − 2 ∗ 2 + 2 h − 1 ∗ 1 2*T(n) = 2^1*(h-1)+2^2*(h-2)+2^3*(h-3)+2^4*(h-4)+...+2^h-2*2+2^h-1*1 2T(n)=21(h1)+22(h2)+23(h3)+24(h4)+...+2h22+2h11
  • 使用错位相减法(将上面两个等式进行相减): T ( n ) = 2 1 + 2 2 + 2 3 + 2 4 + . . . + 2 h − 2 + 2 h − 1 − h + 1 T(n) = 2^1+2^2+2^3+2^4+...+2^h-2+2^h-1-h+1 T(n)=21+22+23+24+...+2h2+2h1h+1
  • 错位相减后得到一个等比数列: T ( n ) = 2 0 + 2 1 + 2 2 + 2 3 + 2 4 + . . . + 2 h − 2 + 2 h − 1 − h T(n) = 2^0+2^1+2^2+2^3+2^4+...+2^h-2+2^h-1-h T(n)=20+21+22+23+24+...+2h2+2h1h
  • 通过等比数列公式$S_n = \\fraca_1(1-q^n)1-q $
  • 1 − 2 ( h − 1 ) ∗ 2 1 − 2 \\frac1-2^(h-1)*21-2 1212(h1)2
  • T ( n ) = 2 h − 1 − h T(n) = 2^h-1-h T(n)=2数据结构C语言 《四》二叉树,堆的基本概念以及堆的相关操作实现(上)

    数据结构C语言 《四》二叉树,堆的基本概念以及堆的相关操作实现(上)

    数据结构(12)---二叉树之顺序结构

    数据结构 二叉树

    数据结构 二叉树

    C语言 二叉树与堆