#数据结构与算法学习笔记#PTA14:最小堆与最大堆(C/C++)

2018.5.3

本题要求建立一个最小堆,并且能从某个指定结点开始依次打印其父节点直到根节点。这道题可以说是近期写的最简单的题目了。最小堆实际上是一棵元素逐层增大的完全二叉树,根节点为元素最小值。

利用vector进行存储,每一个新结点插入时,将当前index(注意不包含新加入结点)的父节点(index/2)与插入元素的元素值进行大小比较,从后往前依次循环比较,若当前结点比其父节点小,则交换位置,直到根节点位置。这里有个小技巧是在vector的第一个元素设置哨兵(元素值为min),方便后期进行循环。


题目要求:

将一系列给定数字插入一个初始为空的小顶堆H[]。随后对任意给定的下标i,打印从H[i]到根结点的路径。

输入格式:

每组测试第1行包含2个正整数N和M(≤1000),分别是插入元素的个数、以及需要打印的路径条数。下一行给出区间[-10000, 10000]内的N个要被插入一个初始为空的小顶堆的整数。最后一行给出M个下标。

输出格式:

对输入中给出的每个下标i,在一行中输出从H[i]到根结点的路径上的数据。数字间以1个空格分隔,行末不得有多余空格。



代码如下:

// Heap_Path.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <vector>
#include <iostream>

using namespace std;

void Insert(vector<int>& minHeap, int element);
void Read(vector<int>& minHeap, int dataNum);
void Print(vector<int>& minHeap, int routeNum);

int main()
{
	vector<int> minHeap;
	minHeap.push_back(-10001);

	int dataNum;
	int routeNum;
	cin >> dataNum >> routeNum;

	Read(minHeap, dataNum);
	Print(minHeap, routeNum);
	
	system("pause");
    return 0;
}

void Insert(vector<int>& minHeap, int element) {
	//检查最大值
	if (minHeap.size() >= 1001)return;
	
	//从后往前循环比较,每次比较当前结点与父节点的大小,若当前结点比父节点小,则交换;
	int index = minHeap.size();
	minHeap.push_back(element);
	while (minHeap[index/2] > element) {
		minHeap[index] = minHeap[index / 2];
		index /= 2;
	}
	minHeap[index] = element;
}

void Read(vector<int>& minHeap, int dataNum) {
	int element;
	for (int i = 0; i < dataNum; i++) {
		cin >> element;
		Insert(minHeap, element);
	}
}

void Print(vector<int>& minHeap, int routeNum) {
	int index;
	for (int i = 0; i < routeNum; i++) {
		cin >> index;
		cout << minHeap[index];
		while (index > 1) {
			index /= 2;
			cout << " " << minHeap[index];
		}
		cout << endl;
 	}
}


另外附上最大堆的课程C语言实现代码:

typedef struct HNode *Heap; /* 堆的类型定义 */
struct HNode {
    ElementType *Data; /* 存储元素的数组 */
    int Size;          /* 堆中当前元素个数 */
    int Capacity;      /* 堆的最大容量 */
};
typedef Heap MaxHeap; /* 最大堆 */
typedef Heap MinHeap; /* 最小堆 */
 
#define MAXDATA 1000  /* 该值应根据具体情况定义为大于堆中所有可能元素的值 */
 
MaxHeap CreateHeap( int MaxSize )
{ /* 创建容量为MaxSize的空的最大堆 */
 
    MaxHeap H = (MaxHeap)malloc(sizeof(struct HNode));
    H->Data = (ElementType *)malloc((MaxSize+1)*sizeof(ElementType));
    H->Size = 0;
    H->Capacity = MaxSize;
    H->Data[0] = MAXDATA; /* 定义"哨兵"为大于堆中所有可能元素的值*/
 
    return H;
}
 
bool IsFull( MaxHeap H )
{
    return (H->Size == H->Capacity);
}
 
bool Insert( MaxHeap H, ElementType X )
{ /* 将元素X插入最大堆H,其中H->Data[0]已经定义为哨兵 */
    int i;
  
    if ( IsFull(H) ) { 
        printf("最大堆已满");
        return false;
    }
    i = ++H->Size; /* i指向插入后堆中的最后一个元素的位置 */
    for ( ; H->Data[i/2] < X; i/=2 )
        H->Data[i] = H->Data[i/2]; /* 上滤X */
    H->Data[i] = X; /* 将X插入 */
    return true;
}
 
#define ERROR -1 /* 错误标识应根据具体情况定义为堆中不可能出现的元素值 */
 
bool IsEmpty( MaxHeap H )
{
    return (H->Size == 0);
}
 
ElementType DeleteMax( MaxHeap H )
{ /* 从最大堆H中取出键值为最大的元素,并删除一个结点 */
    int Parent, Child;
    ElementType MaxItem, X;
 
    if ( IsEmpty(H) ) {
        printf("最大堆已为空");
        return ERROR;
    }
 
    MaxItem = H->Data[1]; /* 取出根结点存放的最大值 */
    /* 用最大堆中最后一个元素从根结点开始向上过滤下层结点 */
    X = H->Data[H->Size--]; /* 注意当前堆的规模要减小 */
    for( Parent=1; Parent*2<=H->Size; Parent=Child ) {
        Child = Parent * 2;
        if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) )
            Child++;  /* Child指向左右子结点的较大者 */
        if( X >= H->Data[Child] ) break; /* 找到了合适位置 */
        else  /* 下滤X */
            H->Data[Parent] = H->Data[Child];
    }
    H->Data[Parent] = X;
 
    return MaxItem;
} 
 
/*----------- 建造最大堆 -----------*/
void PercDown( MaxHeap H, int p )
{ /* 下滤:将H中以H->Data[p]为根的子堆调整为最大堆 */
    int Parent, Child;
    ElementType X;
 
    X = H->Data[p]; /* 取出根结点存放的值 */
    for( Parent=p; Parent*2<=H->Size; Parent=Child ) {
        Child = Parent * 2;
        if( (Child!=H->Size) && (H->Data[Child]<H->Data[Child+1]) )
            Child++;  /* Child指向左右子结点的较大者 */
        if( X >= H->Data[Child] ) break; /* 找到了合适位置 */
        else  /* 下滤X */
            H->Data[Parent] = H->Data[Child];
    }
    H->Data[Parent] = X;
}
 
void BuildHeap( MaxHeap H )
{ /* 调整H->Data[]中的元素,使满足最大堆的有序性  */
  /* 这里假设所有H->Size个元素已经存在H->Data[]中 */
 
    int i;
 
    /* 从最后一个结点的父节点开始,到根结点1 */
    for( i = H->Size/2; i>0; i-- )
        PercDown( H, i );
}


猜你喜欢

转载自blog.csdn.net/qq_20304723/article/details/80188829