C++实现堆数据结构:给定数列建立大根堆、小根堆结构;插入和删除操作

20 篇文章 1 订阅
3 篇文章 1 订阅

首先说明堆数据结构和操作系统的堆区的结构是不同的,进行的操作也不同,详见操作系统内存管理的原理,基本原理是因为操作系统会维护一张空闲内存区的链表,对链表应用算法进行分配内存块

 

以大根堆为例:

建立大根堆:

       step①:容器标准化(使得与完全二叉树逻辑上有相同性质)

       step②:重构容器,建立堆结构:Bigheap_build

                        从最后一个非叶节点开始向整棵树的树根进行大根调整Bigheap_adjust

大根堆插入:

        step①:先在堆后push,

        step②:而后,新堆进行重构Bigheap_build

堆数据结构描述:

#pragma once
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;


void print(int a)
{
	cout << a << " ";
}

void swap(int& a, int& b)
{
	int temp = a;
	a = b;
	b = temp;
}



class Bigheap
{
public:
	Bigheap(vector<int>&a)
	{
        this->heap.resize(a.size());//需提前开辟空间
		this->heap = a;
	}
	vector<int>& getheap()
	{
		return this->heap;
	}
	
	//基于大根堆排序
	void standardize();
	void Bigheap_adjust(vector<int>::iterator k, vector<int>::iterator high);
	void Bigheap_build(vector<int>::iterator high);
	void Bigheap_sort();

	//插入
	void Bigheap_insert(int num);
	//删除
	void Bigheap_del(int bias);

private:
	vector<int> heap;
};

void Bigheap::Bigheap_adjust(vector<int>::iterator k, vector<int>::iterator high)
{

	*(this->heap.begin()) = *k;
	int bias = k - this->heap.begin();
	vector<int>::iterator i = this->heap.begin() + 2 * bias;//a.begin()相当于数组下标0
	while (i <= high)
	{
		//k和bias同时修改方可用迭代器实现

		//第一个判断的目的是找左右孩子中最大的孩子
		if (i != high && *i < *(i + 1))
		{	//若i==a,end()则一定没有右子树,故只有i!=a.end()-1才有可能有右子树,才有可能进行i++;
			//如果*i >= *(i + 1)即左孩子大于右孩子那么就不必再向右子树找了,用左孩子和哨兵比较即可
			i++;//左孩子小于根,考察右孩子或右子树
		}
		if (*(this->heap.begin()) >= *i)break;//i所指为k结点最大的孩子,左右孩子都小于根k(k==i/2),则该元素该放在k位置
		else//k的最大的一个孩子比根大
		{
			//这里不能简单的认为swap(a,b)
			*k = *i;//大的一个孩子i应该放在k位置
			k = i;//在原来k位置的大孩子为顶的子树中继续考察,i指向该子树顶也就是k的大孩子
		}
		bias = i - this->heap.begin();//i指针代数化
		if (2 * bias > this->heap.size() - 1)break;
		i = this->heap.begin() + 2 * bias;//形式化
	}
	*k = *this->heap.begin();
}
void Bigheap::Bigheap_build(vector<int>::iterator high)
{
	//a.begin()相当于数组下标0
	//大根堆建立
	vector<int>::iterator i = this->heap.begin() + (high - this->heap.begin()) / 2;
	for (; i > this->heap.begin(); i--)
		Bigheap_adjust(i, high);

}
void Bigheap::standardize()
{
	//首先应该调整,使得i从1开始
	this->heap.push_back(0);
	for (vector<int>::iterator it = this->heap.end() - 1; it > this->heap.begin(); it--)
	{
		(*it) = *(it - 1);
	}
	(*(this->heap.begin())) = 0;//哨兵位置
	
}
void Bigheap::Bigheap_sort()
{
	//每一趟将堆顶与待排序序列最后一个元素swap
	for (vector<int>::iterator high = this->heap.end() - 1; high >= this->heap.begin() + 2; high--)
	{
		swap(*(this->heap.begin() + 1), *high);
		Bigheap_build(high - 1);
	}
}

void Bigheap::Bigheap_insert(int num)
{
	this->heap.push_back(num);
	Bigheap_build(this->heap.end() - 1);
}
void Bigheap::Bigheap_del(int bias)
{
	//int bias;//输入i的编号
	//cin>>bias;
	//bias = 3;//比如输入位置i=3
	vector<int>::iterator i = this->heap.begin() + bias;
	swap(*i, *(this->heap.end() - 1));//将i位置和最后一个位置元素互换
	//而后删除最后一个位置,将剩下的元素进行建立大根堆
	this->heap.pop_back();
	Bigheap_build(this->heap.end() - 1);
}

class smallheap
{
public:
	smallheap(vector<int>&a)
	{
        this->heap.resize(a.size());//需提前开辟空间
		this->heap = a;
	}
	vector<int>& getheap()
	{
		return this->heap;
	}

	//基于小根堆排序
	void standardize();
	void smallheap_adjust(vector<int>::iterator k, vector<int>::iterator high);
	void smallheap_build(vector<int>::iterator high);
	void smallheap_sort();

	//插入
	void smallheap_insert(int num);
	//删除
	void smallheap_del(int bias);
private:
	vector<int> heap;
};
void smallheap::standardize()
{
	//首先应该调整,使得i从1开始
	this->heap.push_back(0);
	for (vector<int>::iterator it = this->heap.end() - 1; it > this->heap.begin(); it--)
	{
		(*it) = *(it - 1);
	}
	(*(this->heap.begin())) = 0;//哨兵位置

}

void smallheap::smallheap_adjust(vector<int>::iterator k, vector<int>::iterator high)
{
	*this->heap.begin() = *k;
	int bias = k - this->heap.begin();
	vector<int>::iterator i = this->heap.begin() + 2 * bias;//a.begin()相当于数组下标0
	while (i <= high)
	{
		//k和bias同时修改方可用迭代器实现

		//第一个判断的目的是找左右孩子中最小的孩子
		if (i != high && *i > *(i + 1))
		{	//若i==a,end()则一定没有右子树,故只有i!=a.end()-1才有可能有右子树,才有可能进行i++;
			//如果*i >= *(i + 1)即左孩子大于右孩子那么就不必再向右子树找了,用左孩子和哨兵比较即可
			i++;//左孩子小于根,考察右孩子或右子树
		}
		if (*this->heap.begin() <= *i)break;//i所指为k结点最小的孩子,左右孩子都大于根k(k==i/2),则该元素该放在k位置
		else//k的最小的一个孩子比根小
		{
			//这里不能简单的认为swap(a,b)
			*k = *i;//小的一个孩子i应该放在k位置
			k = i;//在原来k的小孩子为顶的子树中继续考察,i指向该子树顶也就是k的小孩子
		}
		bias = i - this->heap.begin();//i指针代数化
		if (2 * bias > this->heap.size() - 1)break;
		i = this->heap.begin() + 2 * bias;//形式化
	}
	*k = *this->heap.begin();
}
void smallheap::smallheap_build(vector<int>::iterator high)
{
	//a.begin()相当于数组下标0
	//小根堆建立
	vector<int>::iterator i = this->heap.begin() + this->heap.size() / 2;
	for (; i > this->heap.begin(); i--)
		smallheap_adjust( i, high);
}
void smallheap::smallheap_sort()
{
	//每一趟将堆顶与待排序序列最后一个元素swap
	for (vector<int>::iterator high = this->heap.end() - 1; high >= this->heap.begin() + 2; high--)
	{
		swap(*(this->heap.begin() + 1), *high);
		smallheap_build( high - 1);
	}
}
void smallheap::smallheap_insert(int num)
{
	this->heap.push_back(num);
	smallheap_build(this->heap.end() - 1);
}
void smallheap::smallheap_del(int bias)
{
	//int bias;//输入i的编号
	//cin>>bias;
	//bias = 3;//比如输入位置i=3
	vector<int>::iterator i = this->heap.begin() + bias;
	swap(*i, *(this->heap.end() - 1));//将i位置和最后一个位置元素互换
	//而后删除最后一个位置,将剩下的元素进行建立小根堆
	this->heap.pop_back();
	smallheap_build(this->heap.end() - 1);
	
}

        

main:

#define _CRT_SECURE_NO_WARNINGS
#include"class_heap.hpp"


int main()
{
	vector<int> a = { 53,17,78,9,45,65,87,32 };
	Bigheap big_heap1(a);
	cout << "原容器:";
	for_each(big_heap1.getheap().begin(), big_heap1.getheap().end(),print);
	cout << endl;
	
	big_heap1.standardize();//使得与完全二叉树结点号有对应关系
	cout << "标准化:";
	for_each(big_heap1.getheap().begin(), big_heap1.getheap().end(), print);//测试代码
	cout << endl;
	big_heap1.Bigheap_build(big_heap1.getheap().end() - 1);//传入的是逻辑上完全二叉树的最后一个结点的序号
	cout << "容器重构为大根堆:";
	for_each(big_heap1.getheap().begin()+1, big_heap1.getheap().end(), print);
	cout << endl;
	
	//在大根堆结构中插入与删除(原来是堆,插完后还是堆)
	big_heap1.Bigheap_insert(39);
	cout << "插入后:";
	for_each(big_heap1.getheap().begin() + 1, big_heap1.getheap().end(), print);
	cout << endl;

	big_heap1.Bigheap_del(5);
	cout << "删除后:";
	for_each(big_heap1.getheap().begin() + 1, big_heap1.getheap().end(), print);
	cout << endl;

	//基于大根堆的堆排序(不再是大根堆数据结构)
	big_heap1.Bigheap_sort();
	cout << "基于大根堆的排序:";
	for_each(big_heap1.getheap().begin() + 1, big_heap1.getheap().end(), print);
	cout << endl;

	




	//--------
	smallheap smallheap1(a);
	cout << "原容器:";
	for_each(smallheap1.getheap().begin(), smallheap1.getheap().end(), print);
	cout << endl;

	smallheap1.standardize();
	cout << "标准化:";
	for_each(smallheap1.getheap().begin(), smallheap1.getheap().end(), print);//测试代码
	cout << endl;
	smallheap1.smallheap_build(smallheap1.getheap().end()-1);//传入的是逻辑上完全二叉树的最后一个结点的序号
	cout << "容器重构为小根堆:";
	for_each(smallheap1.getheap().begin() + 1, smallheap1.getheap().end(), print);
	cout << endl;

	//在小根堆结构中插入与删除(原来是堆,插完后还是堆)
	smallheap1.smallheap_insert(39);
	cout << "插入后:";
	for_each(smallheap1.getheap().begin() + 1, smallheap1.getheap().end(), print);
	cout << endl;

	smallheap1.smallheap_del(5);
	cout << "删除后:";
	for_each(smallheap1.getheap().begin() + 1, smallheap1.getheap().end(), print);
	cout << endl;

	//基于小根堆的堆排序(不再是小根堆数据结构)
	smallheap1.smallheap_sort();
	cout << "基于小根堆的排序:";
	for_each(smallheap1.getheap().begin() + 1, smallheap1.getheap().end(), print);
	cout << endl;

	


	system("pause");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值