Heap sort (with small top heap source code)

binary tree

        Full binary tree: satisfy two conditions at the same time

                1. Either have two kids or have no kids

                2. Leaf nodes are on the same layer

        law:

                 If it is the nth layer, then the number of nodes in this layer must be 2 to the n-1th power

                How many nodes are there in total: 2 to the nth power -1

complete binary tree

        That is, a full binary tree is deleted from right to left, from bottom to top, not deleted in the middle, or a complete binary tree

        A full binary tree must be a complete binary tree

        A complete binary tree is not necessarily a full binary tree

        Why is there a complete binary tree, because although it is a tree structure, it does not want to describe it with a tree structure (it can be described with an array)

        Because except for the last row of a complete binary tree, everything else is in order and can be represented by subscripts, that is, it has the advantages of a tree structure and an array.

heap

                As long as you get the heap, you can get the complete binary tree

        Because the heap is a special complete binary tree: an ordered complete binary tree, the heap

        Its order is different, it requires the order between father and son (no matter between brothers or other nodes)

Parent is greater than child: max heap (big top heap)

Parent is smaller than child: min heap (small top heap)

Use an array to describe the heap

The subscript of the parent node is n

Then the left child: 2n+1

Right child: 2n+2

so

It is known that the subscript of the left child is m, and the subscript of the parent node is: (m-1)/2

It is known that the subscript of the right child is m, and the subscript of the parent node is: (m-2)/2

It is known that the subscript of the child is m, and the subscript of the parent node must be: (m-1)/2 [because the left child must be an odd number, and the right child must be an even number] because it can be calculated, so there is no need for a pointer

The time complexity is log2n, not particularly stable

 

head File:

#pragma once
//小顶堆
#include<iostream>
using namespace std;

//不需要写节点来搞指针,因为做的是数组
template<class T>
class myHeap
{
public:
	myHeap() 
	{	
		pRoot = NULL;
		len = maxLen = 0; 
	}
	~myHeap()
	{
		if (pRoot)
		{
			delete[]pRoot;
		}; 
		pRoot = NULL; len = maxLen = 0;
	}
	//数组需要什么函数,它就需要什么函数
	//插入
	void insertNode(const T& data);
	//删除
	void deleteNode(const T& data);
	//删除堆顶 这个比较特殊
	T pop();
	//遍历
	void travel();
	//直接用数组的方式来构建堆
	void initHeap(T* arr, int size);

public:
	T*		pRoot;	//指向根节点的指针
	size_t	len;	//元素个数
	size_t	maxLen;	//容量
};

//插入
template<class T>
void myHeap<T>::insertNode(const T& data)
{
	//要往上做插入排序,因为小顶堆,子大于父
	//一开始直接进来,然后比较,覆盖
	//1.插入进来
	if (maxLen<=len)//需不需要申请内存
	{
		maxLen = maxLen+(((maxLen >> 1) > 1) ? maxLen >> 1 : 1);
		//开内存
		T* pNew = new T[maxLen];
		if (pRoot)
		{
			memcpy(pNew, pRoot, sizeof(T) * len);
			delete[] pRoot;
		}
		pRoot = pNew;
	}
	//上面开内存是可以省略的


#if 0 //下面可以优化



	pRoot[len++] = data;
	//2.循环和父节点比较,如果冲突,交换,不冲突,循环结束(和插入排序很像)
	if (len==1)//根节点进来直接结束
	{
		return;
	}
	int currentIdx = len - 1;//插入数的下标
	int parentIdx = (currentIdx - 1) / 2;

	while (1)
	{
		if (currentIdx<=0)//没有父节点
		{
			break;
		}
		parentIdx = (currentIdx - 1) / 2;
		if (pRoot[parentIdx]<pRoot[currentIdx])//不冲突则循环结束
		{
			break;
		}
		//交换
		temp = pRoot[currentIdx];
		pRoot[parentIdx]; = pRoot[currentIdx];
		pRoot[currentIdx] = temp;
		//上移
		currentIdx = parentIdx;
	}
#else	//优化部分
	if (len==0)
	{
		pRoot[len++] = data;
		return;
	}

	int currentIdx = len;//插入数的下标
	int parentIdx = (currentIdx - 1) / 2;
	//数据先放进来
	pRoot[currentIdx] = data;

	while (1)
	{
		if (currentIdx <= 0)//没有父节点
		{
			break;
		}
		parentIdx = (currentIdx - 1) / 2;
		if (pRoot[parentIdx] < pRoot[currentIdx])//不冲突则循环结束
		{
			break;
		}
		//冲突,父节点覆盖子节点
		pRoot[currentIdx] = pRoot[parentIdx];
		currentIdx = parentIdx;
	}
	//新数据覆盖回来
	pRoot[currentIdx] = data;
	//个数的增加
	len++;
#endif // 0
}

//删除
template<class T>
void myHeap<T>::deleteNode(const T& data)
{

}

//删除堆顶 这个比较特殊
template<class T>
T myHeap<T>::pop()
{
	if (len==0)
	{
		cout << "堆是空的"<<endl;
		return (T)0;
	}
	if (len == 1)//只有一个
	{
		len--;
		return pRoot[0];
	}
	//临时保存堆顶元素
	T temp = pRoot[0];
	//最后一个覆盖堆顶
	pRoot[0] = pRoot[len - 1];
	
	int currentIdx = 0;//从堆顶开始
	int minChild;// 最小的孩子
	while (1)
	{
		if ((currentIdx * 2 + 1) > (len - 1)||(currentIdx * 2 + 2) > (len - 1))//数组结束
		{
			break;
		}
		// 找到最小的孩子 
		minChild = currentIdx * 2 + 1;//假定左孩子比较小
		if (pRoot[minChild]>pRoot[minChild+1])//如果左比右大,右小
		{
			minChild++;
		}
		if (pRoot[len-1]<pRoot[minChild])
		{
			break;
		}
		//  进行交换(覆盖)
		pRoot[currentIdx] = pRoot[minChild];
		currentIdx = minChild;
	}
	//临时保存的堆顶元素覆盖回来
	pRoot[currentIdx] = pRoot[len-1];

	//结束
	len--;
	return temp;


}

//遍历
template<class T>
void myHeap<T>::travel()
{
	cout << "heap:";
	for (int i = 0; i < len; i++)
	{
		cout << pRoot[i] << " ";
	}
	cout<< endl;
}

//直接用数组的方式来构建堆
template<class T>
void  myHeap<T>::initHeap(T* arr, int size)
{
	//开内存
	maxLen= size;
	len = 0;
	pRoot = new T[size];
	//数据进入
	pRoot[len++] = arr[0];
	int currentIdx = len;//插入数的下标
	int parentIdx = (currentIdx - 1) / 2;
	for (int i = 1; i < size; i++)
	{
		currentIdx = len;
		parentIdx = (currentIdx - 1) / 2;

		//数据先放进来
		pRoot[currentIdx] = arr[i];

		while (1)
		{
			if (currentIdx <= 0)//没有父节点
			{
				break;
			}
			parentIdx = (currentIdx - 1) / 2;
			if (pRoot[parentIdx] < pRoot[currentIdx])//不冲突则循环结束
			{
				break;
			}
			//冲突,父节点覆盖子节点
			pRoot[currentIdx] = pRoot[parentIdx];
			currentIdx = parentIdx;
		}
		//新数据覆盖回来
		pRoot[currentIdx] = arr[i];
		//个数的增加
		len++;
		travel();
	}
}

main file:

#include"SmallDui.h"
int main()
{
	int arr[9] = { 1992,636,54,87,542,88 ,77,8888,932};

	myHeap<int> h;
#if 0



	for (int i = 0; i < 9; i++)
	{
		h.insertNode(arr[i]);
		h.travel();
	}
#else

	h.initHeap(arr, 9);
	//堆排序,删除出来是有序的
	for (int i = 0; i < 9; i++)
	{
		cout<<h.pop() << endl;
		h.travel();
	}

#endif // 0
	while (1)
	{

	}
	return 0;
}

Guess you like

Origin blog.csdn.net/q244645787/article/details/128331393