数据结构与算法学习笔记(九)

1.堆

堆是一种特殊的数据结构,可以用来维护一组元素,并支持快速的插入、删除和查找操作。堆通常被用来实现优先队列,也可以用来排序和实现图算法等。

这里我们用数组来实现大根堆,大根堆中父节点的值总是大于子节点。

数组中,(k为索引)

1.规定节点K的子节点为2*K和2*K+1

2.节点k的父节点为2/k

2.从数组的1索引处开始存储元素,便于操作。

实现堆类中的基本成员:

class Heap
{
private:
	int* items;
	int N;
public:
	Heap(int capacity)
	{
		this->items = new int[capacity+1];        //从1索引开始,长度+1

		this->N = 0;
	}

	void exch(int i, int j)
	{
		int temp;
		temp = items[i];
		items[i] = items[j];
		items[j] = temp;
	}

	void insert(int item)
	{
		items[++N] = item;

		swim(N);        //上浮法,后边有解析
	}

int delMax()
	{
		if (N == 0)
		{
			return -1;
		}
		int max = items[1];
		exch(1, N);
		items[N] = NULL;
		N--;
		sink(1);            //下沉法,后边有解析
		return max;
	}

bool less(int i, int j)                
	{
		if (items[i] < items[j])
		{
			return true;
		}
		return false;
	}

	void disAll()
	{
		for (int i = 1; i <= N; i++)
		{
			cout << items[i] << endl;
		}
	}

2.上浮法

insert()插入元素后,新的元素到来打乱了堆的规律——父节点总比子节点大。

于是,要针对这个新元素把它放到适合的索引下。

swim(),上浮法,新元素初始时是在树的顶端处,不断循环追踪它的位置,让它不断与父节点比较,如果大于就交换,直到小于父节点(等于是不是可以替换?),结束循环,新元素也就放到正确的位置上了,不用担心交换的后果,在最开始的几次添加时就已经为后面的添加奠定了基础,父节点总比子节点大。

swim():

	void swim(int k)
	{
		if (k / 2 < 1)
		{
			return;
		}
		if(less(k/2,  k))
		{
			exch(k, k / 2);
			k = k / 2;
		}
		else
		{
			return;
		}

		swim(k);
	}

3.下沉法

交换根节点与最新子节点(N)的元素值后,再让N处指向NULL,以此除去最大值,然后让最小值从根节点往下沉,几乎与上浮法一样,循环追踪其位置,如果小于当前两子节点中最大的节点,就交换位置,直到交换失败。

sink():

	void sink(int k)
	{
		while (2 * k <= N)
		{
			int max;
			if (2 * k + 1 <= N)
			{
				if (less(2 * k, 2 * k + 1))
				{
					max = 2 * k + 1;
				}
				else
				{
					max = 2 * k;
				}
			}
			else
			{
				max = 2 * k;
			}
			if (!less(k, max))
			{
				return;
			}

			exch(k, max);

			k = max;
		}
	}

函数验证:

int main()
{
	Heap heap(10);

	heap.insert(1);
	heap.insert(2);
	heap.insert(3);
	heap.insert(4);
	heap.insert(5);
	heap.insert(6);
	heap.insert(7);
	heap.insert(8);
	heap.insert(9);
	heap.insert(10);

	heap.disAll();

	int result = 0;
	while ((result = heap.delMax() )!= -1)
	{
		cout << "当前最大值为:" << result << endl;
	}
}

结果:
当前数组排序
10
9
6
7
8
2
5
1
4
3
当前最大值为:10
当前最大值为:9
当前最大值为:8
当前最大值为:7
当前最大值为:6
当前最大值为:5
当前最大值为:4
当前最大值为:3
当前最大值为:2
当前最大值为:1

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值