我與代碼的日常:堆的基本操作

學習不易,需要堅持。

#pragma once
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

typedef int HPDataType ;
typedef struct Heap
{
	HPDataType* array ;
	int size ;
	int capcity ;
}Heap ;

//向下調整
void	AdjustDown(int array[], int size, int root)
{
	int tmp = 0 ; //臨時變量
	while(1)
	{
		int left = 2 * root + 1 ;
		int right = 2 * root + 2 ;
		int min = 0 ;
		//若沒有左右孩子,直接返回
		if(left >= size)
		{
			//越界
			return ;
		}
		//如果存在右孩子(必有左孩子),則找值最小的孩子
		if(right<size && array[right]<array[left])
		{
			min = right ;
		}
		else
		{
			min = left ;
		}
		//找到最小值後,再判斷它與根節點的值
		if(array[root] <= array[min])
		{
			return ;
		}
		else
		{
			tmp = array[root] ;
			array[root] = array[min] ;
			array[min] = tmp ;
			root = min ;
		}
	}
}

//向上調整
void AdjustUp(int array[], int size, int child)
{
	int parent = 0 ; //節點的雙親
	int tmp = 0 ; //臨時變量
	while(child != 0)
	{
		parent = (child - 1 ) / 2 ;
		if(array[child] > array[parent])
		{
			return ;
		}
		else
		{
			tmp = array[child] ;
			array[child] = array[parent] ;
			array[parent] = tmp ;
			child = parent ;
		}
	}
}

//建堆,本例子建小堆
void CreatHeap(int array[], int size)
{
	//從最後一個非葉子節點開始,一直調整到array[0]結束,
	//最後一個非葉子節點爲最後一個節點的雙親節點
	int i = 0 ;
	for(i=(size-2)/2; i>=0; i--)
	{
		AdjustDown(array,size,i) ;
	}
}

void HeapCreatHeap(Heap* heap, int array[], int size)
{
	int i = 0 ;
	heap->capcity = size * 2 ;
	heap->size = size ;
	heap->array = (int *) malloc (sizeof(int) * size) ;
	for(i=0; i<size; i++)
	{
		heap->array[i] = array[i] ;
	}
	CreatHeap(heap->array, heap->size ) ;
}

//增加元素
void HeapInsert(Heap* heap, int val)
{
	heap->array[heap->size] = val ;
	heap->size++ ;
	AdjustUp(heap->array, heap->size, heap->size - 1) ; //size-1就是 child
}

//刪除元素(只能刪除堆頂元素)
void HeapPop(Heap* heap)
{
	//堆的刪除元素算法思想:將最後一個元素覆蓋原堆頂元素,再從array[0]進行調整
	assert(heap->size > 0) ;
	heap->array[0] = heap->array[heap->size - 1] ;
	heap->size-- ;
	AdjustDown(heap->array, heap->size, 0) ;
}

//返回堆頂元素值
HPDataType HeapTop(Heap* heap)
{
	assert(heap->size > 0) ;
	return heap->array[0] ;
}

//打印
void HeapPrint(Heap* heap, int size)
{
	int i = 0 ;
	for(i=0; i<heap->size; i++)
	{
		printf("%d ", heap->array[i]) ;
	}
	printf("\n") ;
}

void Test()
{
	Heap heap ;
	int array[] = {3, 9, 1, 7, 5, 8, 14, 13, 2, 6, 9} ;
	int size = sizeof(array) / sizeof(array[0]) ;
	HeapCreatHeap(&heap, array, size) ;


	//打印初始的堆
	printf("建好的堆爲: \n") ;
	HeapPrint(&heap, size) ;

	//在堆裏插入一個元素
	HeapInsert(&heap, 15) ;
	printf("\n插入15後:\n") ;
	HeapPrint(&heap, size) ;
    
	// 返回新堆的堆頂元素
	printf("\n插入15後,堆頂元素爲: %d\n", HeapTop(&heap)) ;

	//再在堆裏插入一個元素
	HeapInsert(&heap, 0) ;
	printf("\n再插入0後的堆爲:\n") ;
	HeapPrint(&heap, size) ;

	printf("插入0後,堆頂元素爲: %d\n", HeapTop(&heap)) ;

	printf("\n建堆成功!\n") ;
}

int main()
{
	Test() ;
	printf("\n") ;
	return 0 ;
}

運行結果:
在這裏插入圖片描述

學習不易,需要堅持。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章