大根数(2叉 总) / 内含完全k叉树的大堆根
#include<iostream>
#include<queue>
#include<string>
using namespace std;
class Empty{
private:
string message;
public:
Empty(string str="The number of elements is 0") : message{str} {}
string what(){return message;}
};
template<class T>
class maxHeap{//大根堆一定是一个完全二叉树 用数组表示
public:
maxHeap(int init=10);
// ~maxHeap(){delete heap;}
~maxHeap(){}
void push(const T& theElement);
void pop();
void initialize(T* theHeap,int theSize);//初始化一个非空大根堆 传进去一个没排序好的
void show();
///---
maxHeap(maxHeap<T> &x);//复制构造1
void changeMax(T newElement);//替换最大1
void remove(int i);//删除索引元素 1
void newPop();//0
private:
T* heap;
int heapSize;
int arrayLength;
};
template<class T>
maxHeap<T>::maxHeap(int init){
heap = new T[init+1];//从1开始
arrayLength=init+1;
heapSize=0;
}
template<class T>
void
maxHeap<T>::pop(){
if(heapSize==0)
throw Empty();
heap[1].~T();
T lastElement= heap[heapSize--];
int currentNode=1,child=2;//左子孩子是 2*
while(child<heapSize){
if(child<heapSize&&heap[child]<heap[child+1])
child++;//选择大的孩子移至父位
if(lastElement>=heap[child])
break;
heap[currentNode]=heap[child];//元素上移
currentNode=child;//搜索位置下移
child*=2;
}
heap[currentNode]=lastElement;
}
template<class T>
void
maxHeap<T>::push(const T& theElement){
if(heapSize==arrayLength-1){
T* temp = new T[arrayLength*2];
copy(heap+1,heap+arrayLength,temp+1);
// delete [] heap;
heap=temp;
arrayLength*=2;
}
int currentNode= ++heapSize;
while(currentNode!= 1 && heap[currentNode/2]<theElement){
heap[currentNode]=heap[currentNode/2];//元素下移
currentNode/=2;//搜索位置上移动
}
heap[currentNode]=theElement;
}
template<class T>
void
maxHeap<T>::initialize(T* theHeap,int theSize){
delete [] heap;
heap= theHeap;
heapSize=theSize;
//复制基本的
for(int root= heapSize/2;root>=1;root--){//从最后一个有孩子的节点开始遍历
T rootElement= heap[root];
int child=root*2;
while(child <= heapSize){//内while循环 把此root换到此子树的对应位置,使子树成为大堆跟
if(child<heapSize&&heap[child]<heap[child+1])
child++;
if(rootElement>= heap[child])
break;
heap[child/2]= heap[child];
child*=2;
}
heap[child/2]=rootElement;
}
}
template<class T>
void
maxHeap<T>::show(){
queue<int> q;
q.push(1);
int current=1;
while(!q.empty()){
current=q.front();
q.pop();
cout<<heap[current]<<" ";
if(current*2<=heapSize)
q.push(current*2);
if(current*2+1<=heapSize)
q.push(current*2+1);
}
cout<<endl;
}
template<class T>
maxHeap<T>:: maxHeap(maxHeap<T> &x){
heapSize=x.heapSize;
heap= new T[x.arrayLength];
copy(x.heap,x.heap+heapSize+1,heap);
arrayLength=x.arrayLength;
}
template<class T>
void
maxHeap<T>:: changeMax(T newElement){
if(heapSize==0)
throw Empty();
int currentNode=1;
int child=2;
while(currentNode<heapSize){
if(child<heapSize&&heap[child]<heap[child+1])
child++;
if(newElement>=heap[child])
break;
heap[currentNode]=heap[child];
currentNode=child;
child*=2;
}
heap[currentNode]=newElement;
}
template<class T>
void
maxHeap<T>::remove(int i){
T lastElement= heap[heapSize--];
int currentNode=i;
int child=i*2;
while(currentNode<heapSize){
if(child<heapSize&&heap[child]<heap[child+1])
child++;
if(lastElement>=heap[child])
break;
heap[currentNode]=heap[child];
currentNode=child;
child*=2;
}
cout<<currentNode<<" "<<lastElement<<endl;
heap[currentNode]=lastElement;
}
template<class T>
void
maxHeap<T>:: newPop(){
}
int main(){
maxHeap<int> a;
int heap[]={0,20,12,35,15,10,80,30,17,2,1};//从1 开始 统一
a.initialize(heap,10);
maxHeap<int> b(a);
a.pop();
a.pop();
a.push(666);
a.push(3);
b.changeMax(11);
b.show();
}
12.1
基类在第五章总
基类是模板类,您需要通过this
指针访问成员:
template<class T>
class maxPriorityQueue{
public:
virtual ~maxPriorityQueue(){}
virtual bool empty() const =0;
virtual int size()const =0;
virtual const T& top()=0;
virtual void pop() =0;
virtual void push(const T& theElement) =0;
};
template<class T>
class ArrayMaxPriorityQueue:public arrayList<T>,public maxPriorityQueue<T>{//无序线性表
public: //像我这样一个子类派生于 一个基类和一个纯虚函数 ,
//不行,纯虚函数必须在子类中全部实现
bool empty() const {return this->empty();}
int size()const {return this->size();}
const T& top();
void pop();
void push(const T& theElement);
};
template<class T>
const T&
ArrayMaxPriorityQueue<T>::top(){
T Max=0;
for(int i=1;i<this->listSize;i++){
if(this->element[i]>this->element[Max])
Max=i;
}
return this->element[Max];
}
template<class T>
void
ArrayMaxPriorityQueue<T>::pop(){
T temp = top();
int i;
for(i=0;i<this->listSize;i++){
if(temp==this->element[i])
break;
}
copy(this->element+i+1,this->element+this->listSize,this->element+i);
this->listSize--;
}
template<class T>
void
ArrayMaxPriorityQueue<T>::push(const T& theElement){
arrayList<T>:: push_back(theElement); //在派生类的普通成员函数中,使用基类作用域调用基类的静态成员函数和普通成员函数都可以
}
int main(){
ArrayMaxPriorityQueue<int> b;
b.push(55);
b.push(100);
cout<<b;
//
return 0;
}
12.2
思路一样的 ,具体实现换成 链表的操作
12.3-4
变为有序的
差别为:{
有序的:pop和pop都为O(1) ,push为O(n) ,因为要查找插入的位置
无序的:push为O(1),pop,push为O(n),因为要查找对应值
}
12.5
就是哈希表+ 优先级队列 ,数组元素类型可以是链表头指针,也可以是一维数组
maxPriority就是桶的个数
12.6-9
思路就是:
删除:因为是完全二叉树,最后一个位置肯定没了,空的是第一个位置{
元素上移,搜索位置下移
}
添加:多最后一个位置,空的是第一个位置 {
元素下移,搜索位置上移
}
图就不画了 ,书上也有
12.10
用错位相减
12.11
template<class T>
maxHeap<T>:: maxHeap(maxHeap<T> &x){
heapSize=x.heapSize;
heap= new T[x.arrayLength];
copy(x.heap,x.heap+heapSize+1,heap);
arrayLength=x.arrayLength;
}
12.12
template<class T>
void
maxHeap<T>:: changeMax(T newElement){
if(heapSize==0)
throw Empty();
int currentNode=1;
int child=2;
while(child<heapSize){
if(child<heapSize&&heap[child]<heap[child+1])
child++;
if(newElement>=heap[child])
break;
heap[currentNode]=heap[child];
currentNode=child;
child*=2;
}
heap[currentNode]=newElement;
}
12.13
template<class T>
void
maxHeap<T>::remove(int i){
T lastElement= heap[heapSize--];
int currentNode=i;
int child=i*2;
while(currentNode<heapSize){
if(child<heapSize&&heap[child]<heap[child+1])
child++;
if(lastElement>=heap[child])
break;
heap[currentNode]=heap[child];
currentNode=child;
child*=2;
}
cout<<currentNode<<" "<<lastElement<<endl;
heap[currentNode]=lastElement;
}
12.14
不会迭代器 ,代补
12.15
没看懂啥意思 。。。
12.16
Max设置为一个不可能的数,比如2^16-1
min设置为-1
好处: 相当于深度多1,不够时可以用后面的位置,判断条件可以简化(应该?)
12.17
完全d叉树(总)
⚠️:推论看第十一章
#include<iostream>
#include<queue>
#include<string>
using namespace std;
class Empty{
private:
string message;
public:
Empty(string str="The number of elements is 0") ;
string what(){return message;}
};
template<class T>
class maxDHeap{//大根堆一定是一个完全二叉树 用数组表示
public:
maxDHeap(int init=20,int D=2);
// ~maxDHeap(){delete [] heap;}
~maxDHeap(){;}//init初始化已有的数组不用释放
void push(const T& theElement);
void pop();
void initialize(T* theHeap,int theSize);//初始化一个非空大根堆 传进去一个没排序好的
void show();
int maxChild(int leaf);//传进去的是根序号,返回最大孩子序号
int findFather(int child);//返回父节点序号
void changeMax(const T& theElement);
private:
T* heap;
int heapSize;
int arrayLength;
int D;
};
template<class T>
maxDHeap<T>::maxDHeap(int init,int d){
arrayLength=init;
heap= new T[arrayLength];
heapSize=0;
D=d;
}
template<class T>
int
maxDHeap<T>::findFather(int child){
int Leaf=child/D;
if(Leaf*D+1<child)//定位到最后一个有孩子节点
Leaf++;
return Leaf;
}
template<class T>
int
maxDHeap<T>::maxChild(int leaf){
int MaxNumber=leaf*D;//定位到第d-1个孩子
int left=(leaf-1)*D+1;//左界限
if(MaxNumber>heapSize)
MaxNumber=heapSize;//没满
for(int i=1;MaxNumber-i>left;i++){
if(heap[MaxNumber]<heap[MaxNumber-i])
MaxNumber-=i;
}
if(leaf*D+1<=heapSize)
if(heap[MaxNumber]<heap[leaf*D+1])//若有 则与第D个孩子比较
return leaf*D+1;
return
MaxNumber;
}
template<class T>
void
maxDHeap<T>::changeMax(const T& newElement){
if(heapSize==0){
cout<<"error!";
exit(1);
}
int currentNode=1;
int child=D;
while(child<heapSize){
if(newElement>=heap[child])
break;
heap[currentNode]=heap[child];
currentNode=child;
child=maxChild(currentNode);
}
heap[currentNode]=newElement;
}
template<class T>
void
maxDHeap<T>::initialize(T* theDheap,int theSize){
delete [] heap;
heap= theDheap;
heapSize=theSize;
//
int lastLeaf;
int Max;
T temp;
lastLeaf=findFather(heapSize);
while(lastLeaf>=1){
Max=maxChild(lastLeaf);
cout<<Max<<" "<<endl;
if(heap[lastLeaf]<heap[Max])
swap(heap[lastLeaf],heap[Max]);//要解引用
lastLeaf--;
}
}
template<class T>
void
maxDHeap<T>::show(){//这个要改吗?
queue<int> q;
q.push(1);
int current=1;
while(!q.empty()){
current=q.front();
q.pop();
cout<<heap[current]<<" ";
if(current*2<=heapSize)//0
q.push(current*2);
if(current*2+1<=heapSize)
q.push(current*2+1);
}
cout<<endl;
}
template<class T>
void
maxDHeap<T>::pop(){
if(heapSize==0){
cout<<"error!";
exit(1);
}
heap[1].~T();
T lastElement= heap[heapSize--];
int currentNode=1;
int Max=maxChild(currentNode);//1*d
while(Max<heapSize){
//定位到最大的孩子
if(lastElement>=heap[Max])
break;
heap[currentNode]=heap[Max];
currentNode=Max;
Max=maxChild(currentNode);
}
heap[currentNode]=lastElement;
}
template<class T>
void
maxDHeap<T>::push(const T& theElement){
if(heapSize==arrayLength-1){
T* temp = new T[arrayLength*2];
copy(heap+1,heap+arrayLength,temp+1);
delete heap;
heap=temp;
arrayLength*=2;
}
int currentNode= ++heapSize;
int fatherNode;
while(currentNode!=1){
fatherNode=findFather(currentNode);
if(heap[fatherNode]>=theElement)
break;
heap[currentNode]=heap[fatherNode];
currentNode=fatherNode;
}
heap[currentNode]=theElement;
}
int main(){
maxDHeap<int> a(20,3);
int heap[20]={0,4,7,9,12,1,6};
a.initialize(heap,6);
a.show();
a.changeMax(5);
a.show();
return 0;
}
性能 : 分别进行两千次pop 和随机push操作
int main(){
maxDHeap<int> x1(20,4);
maxHeap<int> x2(20);
int heap[20]={0,20,12,35,15,10,80,30,17,2,1};//从1 开始 统一
x2.initialize(heap,10);
x1.initialize(heap,10);
srand(1);
long double clocksPerMillis = double(CLOCKS_PER_SEC) /1000; //CLOCKS 是滴答数的一秒 、除以1k 就是一毫秒的滴答数字
clock_t startTimeX1= clock();//返回目前为止的时间
for(int i=1;i<2000;i++)
x1.push(rand()%65536);
for(int i=1;i<2000;i++)
x1.pop();
long double elapsedMillisX1= (clock()-startTimeX1)/clocksPerMillis;
clock_t startTimeX2= clock();//返回目前为止的时间
for(int i=1;i<2000;i++)
x2.push(rand()%65536);
for(int i=1;i<2000;i++)
x2.pop();
long double elapsedMillisX2= (clock()-startTimeX2)/clocksPerMillis;
cout<<"maxDheap:"<< elapsedMillisX1<<" "<<"maxHeap:"<<elapsedMillisX2<<endl;
return 0;
}
结果当D分别为2,3,4时
可见随着度的增加效率并没有提高,反而降低了 ,并不是越多越好
虽然高度降低了,但查找,判断的成本增高了,还要反复调用函数
12.18
见chengeMax
12.19 -20
左高大根树(maxHblt)
#include<iostream>
#include<queue>// 队列
#include<stack>
using namespace std;
template<class T>
struct binaryTreeNode{
T element;
binaryTreeNode<T> *leftChild,*rightChild;//三个域
//三个构造
binaryTreeNode(){leftChild=rightChild=NULL;}
binaryTreeNode(const T& theElement){element=theElement;}
binaryTreeNode(const T& theElement,binaryTreeNode<T> *left,binaryTreeNode<T> *right){
element=theElement;
leftChild=left;
rightChild=right;
}
};
template<class T>
class maxHblt{
public:
void meld(maxHblt<T> & theMaxHblt);//都是以此为基础
void initialize(T* theElement,int theSize);
void push(const T& theElement);
void pop();
void show();
private:
binaryTreeNode< pair<int,T> > *Root;
int Size;
void meld(binaryTreeNode<pair<int,T> >* &x,binaryTreeNode<pair<int,T> >* &y);//pair第一个是s(x)
};
template<class T>
void
maxHblt<T>::show(){
queue< binaryTreeNode<pair<int,T> > * > q;
binaryTreeNode<pair<int,T> > * current;
q.push(Root);
while(!q.empty()){
current=q.front();
q.pop();
cout<<current->element.second<<" ";
if(current->leftChild!=NULL)//0
q.push(current->leftChild);
if(current->rightChild!=NULL)
q.push(current->rightChild);
}
cout<<endl;
}
template<class T>
void
maxHblt<T>::meld(binaryTreeNode<pair<int,T> >* &x,binaryTreeNode<pair<int,T> >* &y){
//默认以x为根 不行则交换
if(y==NULL)
return ;
if(x==NULL){
x=y; return ;
}
if(x->element.second< y->element.second)//保证大根
swap(x,y);
meld(x->rightChild,y);
//执行到此说明 已经递归到底了 x指向最右内部节点
if(x->leftChild==NULL){
x->leftChild=x->rightChild;
x->rightChild=NULL;
x->element.first=1;
}
else{
if(x->leftChild->element.first<x->rightChild->element.first)
swap(x->rightChild,x->leftChild);
x->element.first=x->rightChild->element.first+1;
}
}
template<class T>
void
maxHblt<T>::meld(maxHblt<T>& theHblt){
meld(Root,theHblt.Root);
Size+=theHblt.Size;
theHblt.Root=NULL;
theHblt.Size=0;
}
template<class T>
void
maxHblt<T>::push(const T& theElement){
binaryTreeNode<pair<int,T> > *q= new binaryTreeNode<pair<int,T> >(pair<int,T>(1,theElement));
meld(Root,q);
Size++;
}
template<class T>
void
maxHblt<T>::pop(){
if(Root==NULL){
cout<<"empty!"<<endl;
exit (1);
}
binaryTreeNode<pair<int,T> > * left=Root->leftChild, *right= Root->rightChild;
delete Root;
Root=left;
meld(left,right);
Size--;
}
template<class T>
void
maxHblt<T>::initialize(T* theElement,int theSize){
queue< binaryTreeNode<pair<int,T> > * > q;
binaryTreeNode<pair<int,T> > *a,*b;
//erase();
for( int i=1;i<=theSize;i++){
q.push( new binaryTreeNode<pair<int,T> >(pair<int,T>(1,theElement[i])) ) ;//全算单子树加入
}
for(int i=1;i<theSize;i++){
a=q.front();
q.pop();
b=q.front();
q.pop();
meld(a,b);
q.push(a);
}
Root=q.front();
Size=theSize;
}
int main(){
int heap[]={-1,3,5,6,7,20,8,2,9,12,15,30,17};
maxHblt<int> a;
a.initialize(heap,12);
a.show();
return 0;
}
12.21
判断改一下就行了
if(x->element.second> y->element.second)//保证大根
swap(x,y);
12.22
buhui
12.23
另外meld需要改 father指针也要
template<class T>
struct binaryTreeNode{
T element;
binaryTreeNode<T> *leftChild,*rightChild,*fatherNode;//三个域
//三个构造
binaryTreeNode(){fatherNode= leftChild=rightChild=NULL;}
binaryTreeNode(const T& theElement){element=theElement;}
binaryTreeNode(const T& theElement,binaryTreeNode<T> *left,binaryTreeNode<T> *right,binaryTreeNode<T> *father){
element=theElement;
leftChild=left;
rightChild=right;
fatherNode=father;
}
};
template<class T>
class maxWithRemoveNodeWithRemoveNode{
public:
void meld(maxWithRemoveNodeWithRemoveNode<T> & themaxWithRemoveNodeWithRemoveNode);//都是以此为基础
void initialize(T* theElement,int theSize);
void push(const T& theElement);
void pop();
void show();
//12.23
binaryTreeNode<pair<int,T> >* pushAndReturnNode(const T& theElement);
T removeElementInNode(binaryTreeNode<pair<int,T> >* theNode);
private:
binaryTreeNode< pair<int,T> > *Root;
int Size;
void meld(binaryTreeNode<pair<int,T> >* &x,binaryTreeNode<pair<int,T> >* &y);//pair第一个是s(x)
};
template<class T>
binaryTreeNode<pair<int,T> >*
maxWithRemoveNodeWithRemoveNode<T>::pushAndReturnNode(const T& theElement){
binaryTreeNode<pair<int,T> > *x= new binaryTreeNode<pair<int,T> >(pair<int,T>(1,theElement)),*result=NULL,*current=NULL,*temp=Root;
while(temp!=NULL){//定位
if(temp->element.second < theElement)
break;
current=temp;
temp=temp->rightChild;
}
result=current;
meld(current,x);
if(result->leftChild->element==theElement)//右边可能为空
return result->leftChild;
return result->rightChild;
}
template<class T>
T
maxWithRemoveNodeWithRemoveNode<T>::removeElementInNode(binaryTreeNode<pair<int,T> >* theNode){
// 有父节点就不用遍历
T result =theNode->element.second;
binaryTreeNode<pair<int,T> > *l=theNode->leftChild,*r=theNode->rightChild;
meld(l,r);
meld(theNode->fatherNode,l);
return result;
}
12.24.
1) 没有12.1呀?
2) 当w(x)= 1时显然成立
=2 时必然在左边
=3 时才是满树 此时 最右路径为2 成立
-->定义为左重 是颗完全树
看定理12-1 第二点 同证明
#include<iostream>
#include<queue>// 队列
#include<stack>
using namespace std;
template<class T>
struct binaryTreeNode{
T element;
binaryTreeNode<T> *leftChild,*rightChild;//三个域
//三个构造
binaryTreeNode(){leftChild=rightChild=NULL;}
binaryTreeNode(const T& theElement){element=theElement;}
binaryTreeNode(const T& theElement,binaryTreeNode<T> *left,binaryTreeNode<T> *right){
element=theElement;
leftChild=left;
rightChild=right;
}
};
template<class T>
class maxWblt{
public:
void meld(maxWblt<T> & themaxWblt);//都是以此为基础
void initialize(T* theElement,int theSize);
void push(const T& theElement);
void pop();
void show();
private:
binaryTreeNode< pair<int,T> > *Root;
int Size;
void meld(binaryTreeNode<pair<int,T> >* &x,binaryTreeNode<pair<int,T> >* &y);//pair第一个是s(x)
};
template<class T>
void
maxWblt<T>::show(){
queue< binaryTreeNode<pair<int,T> > * > q;
binaryTreeNode<pair<int,T> > * current;
q.push(Root);
while(!q.empty()){
current=q.front();
q.pop();
cout<<current->element.second<<" ";
if(current->leftChild!=NULL)//0
q.push(current->leftChild);
if(current->rightChild!=NULL)
q.push(current->rightChild);
}
cout<<endl;
}
template<class T>
void
maxWblt<T>::meld(binaryTreeNode<pair<int,T> >* &x,binaryTreeNode<pair<int,T> >* &y){
//默认以x为根 不行则交换
if(y==NULL)
return ;
if(x==NULL){
x=y; return ;
}
if(x->element.second< y->element.second)//保证大根
swap(x,y);
meld(x->rightChild,y);
//执行到此说明 已经递归到底了 x指向最右内部节点
if(x->leftChild==NULL){
x->leftChild=x->rightChild;
x->rightChild=NULL;
x->element.first=1;
}
else{
if(x->leftChild->element.first<x->rightChild->element.first)
swap(x->rightChild,x->leftChild);
x->element.first=x->rightChild->element.first+1+x->leftChild->element.first;//1这里改为加左右孩子
}
}
template<class T>
void
maxWblt<T>::meld(maxWblt<T>& theHblt){
meld(Root,theHblt.Root);
Size+=theHblt.Size;
theHblt.Root=NULL;
theHblt.Size=0;
}
template<class T>
void
maxWblt<T>::push(const T& theElement){
binaryTreeNode<pair<int,T> > *q= new binaryTreeNode<pair<int,T> >(pair<int,T>(1,theElement));
meld(Root,q);
Size++;
}
template<class T>
void
maxWblt<T>::pop(){
if(Root==NULL){
cout<<"empty!"<<endl;
exit (1);
}
binaryTreeNode<pair<int,T> > * left=Root->leftChild, *right= Root->rightChild;
delete Root;
Root=left;
meld(left,right);
Size--;
}
template<class T>
void
maxWblt<T>::initialize(T* theElement,int theSize){
queue< binaryTreeNode<pair<int,T> > * > q;
binaryTreeNode<pair<int,T> > *a,*b;
//erase();
for( int i=1;i<=theSize;i++){
q.push( new binaryTreeNode<pair<int,T> >(pair<int,T>(1,theElement[i])) ) ;//全算单子树加入
}
for(int i=1;i<theSize;i++){
a=q.front();
q.pop();
b=q.front();
q.pop();
meld(a,b);
q.push(a);
}
Root=q.front();
Size=theSize;
//cout<<Root->element.first<<endl;
}
int main(){
int heap[]={-1,3,5,6,7,20,8,2,9,12,15,30,17};
maxWblt<int> a;
a.initialize(heap,12);
a.show();
return 0;
}
非递归meld待写:
a. 调用后序遍历
b.怎么插入的位置往上都需要改w ,增加一个父节点指针?
(1条消息) C++(数据结构与算法):42---优先级队列的实现(扩充二叉树、高度优先左高树(HBLT)、重量优先左高树(WBLT))_董哥的黑板报-CSDN博客
4)
大根堆
用堆实现优先级队列的空间利用率很高,而且效率也很高,但是并不适用于所有优先级队列,尤 其当两个优先级队列或多个长度不同的队列需要合并的时候,这时就需要其他的数据结构了,左高 树就能满足这种需要
堆与左高树的异同:
WBLT、HBLT可以执行优先级队列的查找、插入、删除操作,时间复杂度与堆相同
WBLT、HBLT和堆一样,可以在线性时间内完成初始化
用WBLT、HBLT表示的两个优先级队列可以在对数时间内合并为一个,而桶堆表示的优先级队列却不行
总的来说 当需要特殊操作时,大根堆并不支持
12.25
感觉,只是判断条件变了
12.26-27
12.28
d不是越多越好 ,取二的时候应该最好
12.29
没写,没想到pop改进方法
12.30
堆排序不是稳定的 ,因为是靠节点层移动的
插入排序是稳定的,是一个一个比较移动插入
12.31-32
12.33
因为element+= 了 所以必然往下移动 ,上面就不用做多余的比较了 ,只需要从此位置往下比较插入 就行了 不用从root比较
12.34-35
如12题的
12.36
maxHeap 添加两个成员函数
void load(T size);//按worst fit rule 装入
maxHeap(int init,int c);//初始化 capacity
template<class T>
void
maxHeap<T>::load(T size){
if(size>capacity){
cout<<"Greater than capacity"<<endl;
exit(1);
}
int current =1,child=2;
if(heap==NULL){
heap[++heapSize]=capacity-size;
}
else
if( heap[1]>=size ){
int temp= heap[1]-size;
while(child<heapSize){
if(heap[child]<heap[child+1])
child++;
if(temp>heap[child])
break;
heap[current]=heap[child];
current=child;
child*=2;
}
heap[current]= temp;
}
else {
push(capacity-size);
}
}
template<class T>
maxHeap<T>::maxHeap(int init){
heap = new T[init+1];//从1开始
arrayLength=init+1;
heapSize=0;
}
template<class T>
maxHeap<T>::maxHeap(int init,int c){
heap=new T[init];
arrayLength=init;
heapSize=0;
capacity=c;
}
12.37-38
12.39
两个归并段就相当于合并两个有序数组,每一个归并段相当于一个节点,权值相当于长度
构建霍夫曼树
因为任意两个时间复杂度O(i+j)
用霍夫曼树总权值就最小,符合期望
12.40
权重越大编码越短
霍夫曼树总代码(0)
#include <iostream>
#define DefaultSize 10
template<class T>
class huffmanNode{
huffmanNode(){weight=0; element=0; left=right=NULL;}
huffmanNode<T> *left,*right;
T weight;//权值 ,频率
T element;//字符 外部节点为字符,内部为0
};
template<class T>
class huffmanTree{
public:
huffmanTree();
~huffmanTree(){;}
void initHuffmanTree(T *weight,int n);//输入权值,返回一颗霍夫曼树,利用小根堆
void OutputCodingTable();
private:
huffmanNode<T> * Root;
int TreeSize;
};
小根堆 初始化:
1)
2)
比率是1 因为都是频率大的路径短
3)
跟左偏树一样: n个内节点,有n+1个外节点-->可以创建一个有n-1个节点右偏数然后中序遍历插入
4)-6)
初始化都是O(n) 不推荐用右偏树,复杂还要写meld
12.41
证明: 假设一个棵树是最小WEP ,存在一颗子树,拥有两个最小频率
--> a. 两个最小频率一定是兄弟 ,所以到这两个外节点的路径长度L相同
所以删除这个两个外节点,子根(权F为两个最小频率之和)为单节点,WEP=L * F
只会L减少,F不会变 所以仍为最优树
12.42-44
0 赶时间 代补
用前序遍历输出编码
第十二章总结
本章主要讲了优先级队列
方法:
a 无序表/有序表:要么查找要时间,要么插入要时间
b 大根堆/小根堆(隐式的结构,数组代替指针):使最大最小的永远在root
但不容易实现其他操作(如合并)->
c 左高树/重高树: s(x) 内外节点
MaxHblt 和MaxWblt 主要靠meld
应用:
利用大根堆来排序: O(nlongn)
机器调度 NP问题: LPT算法
霍夫曼编码: 按照频率分配代码长短(不定长)利用小根队来初始化
是一种前缀不相同的编码 (0 左 1右)
OKOK-- 21/11/17