算法訓練-堆

1、堆

在這裏插入圖片描述
在這裏插入圖片描述

堆代碼實現與堆排序

#include<iostream>
#include<queue>
#include <math.h>
using namespace std;

#define MAX_HEAP_SIZE 11

/************************************************************************/
/*

6
3#4
1#9    2#8
10#7    5#    ##     ##


*/
/************************************************************************/

typedef union myheap
{
	int m_size;
	int m_heapmem[MAX_HEAP_SIZE];
}*ptrHeap;

void init_heap(ptrHeap* heap, int size = 10){
	if (size + 1>MAX_HEAP_SIZE)
	{
		printf("out of memery\n"); return;
	}
	*heap = (ptrHeap)malloc(sizeof(myheap));
	int temp[10] = { 6, 3, 4, 1, 9, 2, 8, 10, 7, 5 };
	(*heap)->m_size = size;
	for (int i = 0; i < size; ++i)
	{
		(*heap)->m_heapmem[i + 1] = temp[i];
	}
}
void swap(int& a, int& b){
	if (a == b)
	{
		return;
	}
	a = a^b;
	b = a^b;
	a = a^b;
}

//完全二叉樹 逐層層序遍歷,堆在數組中存儲時的程序遍歷只需遍歷一遍數組即可,時間複雜度爲O(n)
/*
教訓總結:
寫代碼前一定要想將思路理順了,跟着邏輯走,而不要跟着記憶走,“隱約的記得好像其他類似的做法是這樣的”這樣的思維方式很有問題,抓不住問題的本質,即使順着記憶做出來了,下次也可能會忘記,
而且容易沉溺於“想不起上次的做法”而苦惱的境地。

*/
void dump_heap(ptrHeap heap){
	int size = heap->m_size;
	queue<int> level;
	level.push(heap->m_heapmem[1]);

	int i = 0;
	int le = 0;
	while (i<size)
	{
		while (!level.empty())
		{
			printf(" %d ", level.front()); level.pop();
			i++;
		}
		printf("\n");

		//找到各層結點的開始下標和結束下標(太傻叉了 這個實現,完全沒有必要用隊列啊)
		for (int j = i / 2 + 1; j < i / 2 + 1 + (int)pow(2, le) && 2 * j <= size; ++j)
		{
			level.push(heap->m_heapmem[j * 2]);
			if (2 * j + 1 <= size)
			{
				level.push(heap->m_heapmem[j * 2 + 1]);
			}
		}
		le++;
	}
}


void dump_heap2(ptrHeap heap)
{
	int size = heap->m_size;
	int maxlevel = size / 2;
	int count = 0;
	//找到各層的起點和終點下標,然後進行遍歷
	for (int level = 0; level < maxlevel && count < size; ++level){
		int startIndex = (1 << level)            /* (int)pow(2, level)*/;
		int endIndex = startIndex + (1 << level) /*(int)pow(2, level)*/;

		for (; startIndex < endIndex && startIndex<=size; ++startIndex){
			printf("%d ", heap->m_heapmem[startIndex]);
			count++;
		}
		printf("\n");
	}
}

void heapify(ptrHeap* heap, int parent,int size){
	int maxIndex = 0;
	int left = 0;
	int right = 0;
	while (true)
	{
		maxIndex = parent;
		left = parent * 2;
		right = left + 1;

		if ((*heap)->m_heapmem[maxIndex] < (*heap)->m_heapmem[left] && (left <= size)){
			maxIndex = left;
		}
		if ((*heap)->m_heapmem[maxIndex] < (*heap)->m_heapmem[right] && (right <= size)){
			maxIndex = right;
		}
		if (maxIndex == parent){
			break;
		}
		swap((*heap)->m_heapmem[parent], (*heap)->m_heapmem[maxIndex]);
		parent = maxIndex;
	}
}
void dump(ptrHeap heap){
	printf("\n");
	int size = heap->m_size;
	for (int i = 1; i <= size; ++i){
		printf(" %d ", heap->m_heapmem[i]);
	}
	printf("\n");
}
void build_heap(ptrHeap heap)
{
	int size = heap->m_size;
	for (int i = size / 2; i > 0; --i){
		heapify(&heap, i,size);
	}
}
void heap_sort(ptrHeap pHeap){
	
	int size = pHeap->m_size;
	while (size>1)
	{
		//堆化
		for (int i = size / 2; i > 0; --i){
			heapify(&pHeap, i,size);
		}
		//堆化後將最大元素(第一個元素)放在最後一位
		swap(pHeap->m_heapmem[1], pHeap->m_heapmem[size]);
		size--;
	}

}


int main()
{
	ptrHeap pHeap = nullptr;
	cout << "before build heap:" << endl;
	init_heap(&pHeap);
	dump_heap2(pHeap);
	cout << "after build heap:" << endl;
	build_heap(pHeap);
	dump_heap2(pHeap);

	printf("before heap sort:\n");
	dump(pHeap);
	printf("after heap sort:\n");
	heap_sort(pHeap);
	dump(pHeap);
	system("pause");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章