数据结构与算法分析-C++描述 第6章 左式堆ADT(LeftistHeap)

左式堆(leftist heap):

        由左结点形成的长路径构成的树(而且实际上更便于合并操作)称之为左式堆。

零路径长(null path length):

        npl(x)定义为从x到一个不具有两个儿子结点的最短路径的长。因此具有0个或一个儿子的结点的npl(x) = 0。

左式堆的性质:

       1)对于堆中的每一个结点X,左儿子的路径长至少和右儿子的路经长一样大;

       2)在右路径上有r个结点的左式堆必然至少有2^r - 1个结点【数学归纳法】;

左式堆的基本操作:

        合并(merge):插入只是合并的一种特殊情况;

                                   1. 如果两个堆有一个是空堆,可以直接返回非空堆;

                                    2.递归合并具有较大根节点的堆和较小根节点的右子堆;

                                    3.交换较小根节点的堆的左右孩子并更新零长路径;

合并过程如下图:

                       两个左式堆H_1H_2                                         将H_2H_1右子堆合并                                   将H_2拼接到H_1右子堆

 

                                                                              交换H_1根节点左右孩子后的结果

实例:建立左式堆,实现插入、删除最小值、查询最小值、打印输出等功能。【注:此处为最小堆方式】

1、heap.h

//heap.h
#ifndef HEAP_H_
#define HEAP_H_

#include<iostream>
#include<vector>
#include<algorithm>

using std::cout;
using std::endl;
using std::vector;

template<class T>
struct LeftistNode{
	T element;
	LeftistNode *left;
	LeftistNode *right;
	int npl;
	
	LeftistNode(const T &e, LeftistNode<T> *l = NULL, LeftistNode<T> *r = NULL, int n = 0):element(e), left(l), right(r), npl(n){
	};
};

template<class T>
class LeftistHeap{
public:
	//LeftistHeap constuctor
	LeftistHeap():root(NULL){
	
	};
	
	//LeftistHeap constuctor
	LeftistHeap(const LeftistHeap &heap){
		root = clone(heap -> root);
	};
	
	//LeftistHeap destructor
	~LeftistHeap(){
		makeEmpty();
	};
	
	//judge whether the heap is empty
	bool isEmpty() const{
		return root == NULL;
	};
	
	//find the minmum element in heap
	const T &findMin() const{
		if(root != NULL){
			return root -> element;
		}
		return (T)NULL;
	};
	
	//insert value
	void insert(const T &value){
		root = merge(new LeftistNode<T>(value), root);
	};
	
	//delete the minmum
	void deleteMin(){
		if(isEmpty()){
			cout << " the heap is already empty !" << endl;
		}
		LeftistNode<T> *node = root;
		root = merge(root -> left, root -> right);
		delete node;
	};
	
	//delete the minItem
	void deleteMin(T &minItem){
		minItem = findMin();
		deleteMin();
	}
	
	//make empty of the heap
	void makeEmpty(){
		reclaimMemory(root);
		root = NULL;
	};
	
	//excute merge operation
	void merge(LeftistHeap<T> &heap){
		if(this == &heap){
			return;
		}
		root = merge(root, heap.root);
		heap.root = NULL;
	};
	
	const LeftistHeap<T> & operator=(const LeftistHeap<T> &heap){
		if(this != &heap){
			makeEmpty();
			root = clone(heap.root);
		}
		return *this;
	};
	
	//print the heap
	void print(){
		LeftistHeap heap;
		vector<T> v;
		while(this -> root){
			v.push_back(this -> findMin());
			heap.insert(this -> findMin());
			this -> deleteMin();
		}
		for(int i = 0; i < v.size(); i++){
			cout << v[i] << " ";
		}
		cout << endl;
		*this = heap;
		
	};
	
private:
	LeftistNode<T>* merge(LeftistNode<T> *h1, LeftistNode<T> *h2);
	LeftistNode<T>* merge1(LeftistNode<T> *h1, LeftistNode<T> *h2);
	void swapChildren(LeftistNode<T> *heap);
	void reclaimMemory(LeftistNode<T> *heap);
	LeftistNode<T>* clone(const LeftistNode<T> *heap);
private:
	LeftistNode<T>* root;
};

//merge root
template<class T>
LeftistNode<T>* LeftistHeap<T>::merge(LeftistNode<T> *h1, LeftistNode<T> *h2){
	if(h1 == NULL){
		return h2;
	}
	if(h2 == NULL){
		return h1;
	}
	if(h1 -> element < h2 -> element){
		return merge1(h1, h2);
	}else{
		return merge1(h2, h1);
	}
}

template<class T>
LeftistNode<T>* LeftistHeap<T>::merge1(LeftistNode<T> *h1, LeftistNode<T> *h2){
	if(h1 -> left == NULL){
		h1 -> left = h2;
	}else{
		h1 -> right = merge(h1 -> right, h2);
		if(h1 -> left -> npl < h1 -> right -> npl){
			swapChildren(h1);
		}
		h1 -> npl = h1 -> right -> npl + 1;
	}
	return h1;
}

template<class T>
void LeftistHeap<T>::swapChildren(LeftistNode<T> *heap){
	if(heap != NULL){
		LeftistNode<T> *temp = heap -> left;
		heap -> left = heap -> right;
		heap -> right = temp;
	}
}

template<class T>
void LeftistHeap<T>::reclaimMemory(LeftistNode<T> *heap){
	if(heap != NULL){
		reclaimMemory(heap -> left);
		reclaimMemory(heap -> right);
		delete heap;
	}
}

template<class T>
LeftistNode<T>* LeftistHeap<T>::clone(const LeftistNode<T> *heap){
	if(heap == NULL){
		return NULL;
	}
	return new LeftistNode<T>(heap -> element, clone(heap -> left), clone(heap -> right), heap -> npl);
}

#endif

2、main.cpp

//main.cpp
#include<iostream>
#include"heap.h"

using namespace std;

int main(){
	int arr1[8] = {3, 10, 8, 21, 14, 17, 23, 26};
	int arr2[8] = {6, 12, 7, 18, 24, 37, 18, 33};
	LeftistHeap<int> *h1 = new LeftistHeap<int>();
	LeftistHeap<int> *h2 = new LeftistHeap<int>();
	
	cout << "********* insert ************" << endl;
	for(int i = 0; i < 8; i++){
		h1 -> insert(arr1[i]);
		h2 -> insert(arr2[i]);
	}
	
	cout << "********* print ************" << endl;
	cout << " the info in h1 as follows : " << endl;
	h1 -> print();
	cout << " the info in h2 as follows : " << endl;
	h2 -> print();
	
	cout << "********* merge ************" << endl;
	h1 -> merge(*h2);
	h1 -> print();
	
	cout << "********* deleteMin ************" << endl;
	int minItem;
	h1 -> deleteMin(minItem);
	cout << " the minmum value in h1 is " << minItem << endl;
	
	cout << " done ." << endl;
	return 0;
}

practice makes perfect !

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值