堆 续2
来源:互联网 发布:java权限框架有几种 编辑:程序博客网 时间:2024/06/07 01:58
---------------------siwuxie095
索引从 1 开始
程序 1:最大堆的实现
MaxHeap.h:
#ifndef MAXHEAP_H
#define MAXHEAP_H
#include <iostream>
#include <algorithm>
#include <string>
#include <cmath>
#include <cassert>
using namespace std;
//最大堆:索引从1开始
template<typename Item>
class MaxHeap
{
private:
Item *data;
int count;
int capacity;
//私有函数,用户不能调用
void shiftUp(int k)
{
//如果新添加的元素大于父节点的元素,则进行交换
while (k >1 && data[k / 2] < data[k])
{
swap(data[k /2], data[k]);
k /=2;
}
}
//也是私有函数,用户不能调用
void shiftDown(int k)
{
//只要当前节点有孩子就进行循环
while (2 * k <= count)
{
//在此轮循环中,data[k]和data[j]交换位置
int j =2 * k;
// data[j]是data[2*k]和data[2*k+1]中的最大值
if (j +1 <= count && data[j + 1] > data[j])
{
j++;
}
if (data[k] >= data[j])
{
break;
}
swap(data[k], data[j]);
k = j;
}
}
public:
MaxHeap(int capacity)
{
//因为存储时是从索引1开始的,所以要加1
//即多开辟一个空间
data =new Item[capacity + 1];
//计数器,这里索引等于计数器
count =0;
this->capacity = capacity;
}
~MaxHeap()
{
delete []data;
}
int size()
{
return count;
}
bool isEmpty()
{
return count ==0;
}
//向最大堆中添加新元素,新元素放在数组末尾
void insert(Item item)
{
//防止越界
assert(count +1 <= capacity);
//索引从1开始
data[count +1] = item;
count++;
//新加入的元素有可能破坏最大堆的定义,需要通过
//Shift Up操作,把索引为count的元素尝试着向上
//移动来保持最大堆的定义
shiftUp(count);
}
//取出最大堆中根节点的元素(最大值)
Item extractMax()
{
//首先要保证堆不为空
assert(count >0);
//取出根节点的元素(最大值)
Item ret = data[1];
//将第一个元素(最大值)和最后一个元素进行交换
swap(data[1], data[count]);
//count--后,被取出的根节点就不用再考虑了
count--;
//调用Shift Down操作,想办法将此时的根节点(索引为1)
//向下移动,来保持最大堆的定义
shiftDown(1);
return ret;
}
public:
//在控制台打印测试用例
void testPrint()
{
//限制:只能打印100个元素以内的堆,因为控制台一行的字符数量有限
if (size() >=100)
{
cout <<"Fancy print can only work for less than 100 int";
return;
}
//限制:只能打印类型是int的堆
if (typeid(Item) !=typeid(int))
{
cout <<"Fancy print can only work for int item";
return;
}
cout <<"The Heap size is: " << size() << endl;
cout <<"data in heap: ";
for (int i =1; i <= size(); i++)
{
cout << data[i] <<" ";
}
cout << endl;
cout << endl;
int n = size();
int max_level =0;
int number_per_level =1;
while (n >0)
{
max_level +=1;
n -= number_per_level;
number_per_level *=2;
}
int max_level_number =int(pow(2, max_level -1));
int cur_tree_max_level_number = max_level_number;
int index =1;
for (int level =0; level < max_level; level++)
{
string line1 = string(max_level_number *3 - 1,' ');
int cur_level_number = min(count -int(pow(2, level)) +1,
int(pow(2, level)));
bool isLeft =true;
for (int index_cur_level =0; index_cur_level < cur_level_number;
index++, index_cur_level++)
{
putNumberInLine(data[index], line1, index_cur_level,
cur_tree_max_level_number *3 - 1, isLeft);
isLeft = !isLeft;
}
cout << line1 << endl;
if (level == max_level -1)
{
break;
}
string line2 = string(max_level_number *3 - 1,' ');
for (int index_cur_level =0; index_cur_level < cur_level_number;
index_cur_level++)
{
putBranchInLine(line2, index_cur_level, cur_tree_max_level_number *3 - 1);
}
cout << line2 << endl;
cur_tree_max_level_number /=2;
}
}
private:
void putNumberInLine(int num, string &line,int index_cur_level,
int cur_tree_width,bool isLeft)
{
int sub_tree_width = (cur_tree_width -1) / 2;
int offset = index_cur_level * (cur_tree_width +1) + sub_tree_width;
assert(offset +1 < line.size());
if (num >=10)
{
line[offset +0] = '0' + num /10;
line[offset +1] = '0' + num %10;
}
else
{
if (isLeft)
line[offset +0] = '0' + num;
else
line[offset +1] = '0' + num;
}
}
void putBranchInLine(string &line,int index_cur_level, int cur_tree_width)
{
int sub_tree_width = (cur_tree_width -1) / 2;
int sub_sub_tree_width = (sub_tree_width -1) / 2;
int offset_left = index_cur_level * (cur_tree_width +1) + sub_sub_tree_width;
assert(offset_left +1 < line.size());
int offset_right = index_cur_level * (cur_tree_width +1) + sub_tree_width
+1 + sub_sub_tree_width;
assert(offset_right < line.size());
line[offset_left +1] = '/';
line[offset_right +0] = '\\';
}
};
#endif
main.cpp:
#include"MaxHeap.h"
#include <ctime>
int main()
{
MaxHeap<int> maxheap = MaxHeap<int>(100);
srand(time(NULL));
for (int i =0; i < 15; i++)
{
maxheap.insert(rand() %100);
}
maxheap.testPrint();
cout << endl;
while (!maxheap.isEmpty())
{
cout << maxheap.extractMax() <<" ";
}
cout << endl;
system("pause");
return0;
}
运行一览:
程序 2:最大堆的优化
MaxHeap.h:
#ifndef MAXHEAP_H
#define MAXHEAP_H
#include <iostream>
#include <algorithm>
#include <string>
#include <cmath>
#include <cassert>
using namespace std;
//最大堆:索引从1开始
template<typename Item>
class MaxHeap
{
private:
Item *data;
int count;
int capacity;
//私有函数,用户不能调用
//使用插入排序的优化方式进行优化
void shiftUp(int k)
{
//如果新添加的元素大于父节点的元素,则进行交换
Item e = data[k];
while (k >1 && data[k / 2] < e)
{
data[k] = data[k /2];
k /=2;
}
data[k] = e;
}
//也是私有函数,用户不能调用
//使用插入排序的优化方式进行优化
void shiftDown(int k)
{
Item e = data[k];
//只要当前节点有孩子就进行循环
while (2 * k <= count)
{
//在此轮循环中,data[k]和data[j]交换位置
int j =2 * k;
// data[j]是data[2*k]和data[2*k+1]中的最大值
if (j +1 <= count && data[j + 1] > data[j])
{
j++;
}
if (e >= data[j])
{
break;
}
data[k] = data[j];
k = j;
}
data[k] = e;
}
public:
MaxHeap(int capacity)
{
//因为存储时是从索引1开始的,所以要加1
//即多开辟一个空间
data =new Item[capacity + 1];
//计数器,这里索引等于计数器
count =0;
this->capacity = capacity;
}
MaxHeap(Item arr[],int n)
{
data =new Item[n + 1];
capacity = n;
for (int i =0; i < n; i++)
{
data[i +1] = arr[i];
}
count = n;
//从最后一个非叶子节点的位置开始
for (int i = count /2; i >=1; i--)
{
//每次对索引为i的元素进行Shift Down操作
shiftDown(i);
}
}
~MaxHeap()
{
delete []data;
}
int size()
{
return count;
}
bool isEmpty()
{
return count ==0;
}
//向最大堆中添加新元素,新元素放在数组末尾
void insert(Item item)
{
//防止越界
assert(count +1 <= capacity);
//索引从1开始
data[count +1] = item;
count++;
//新加入的元素有可能破坏最大堆的定义,需要通过
//Shift Up操作,把索引为count的元素尝试着向上
//移动来保持最大堆的定义
shiftUp(count);
}
//取出最大堆中根节点的元素(最大值)
Item extractMax()
{
//首先要保证堆不为空
assert(count >0);
//取出根节点的元素(最大值)
Item ret = data[1];
//将第一个元素(最大值)和最后一个元素进行交换
swap(data[1], data[count]);
//count--后,被取出的根节点就不用再考虑了
count--;
//调用Shift Down操作,想办法将此时的根节点(索引为1)
//向下移动,来保持最大堆的定义
shiftDown(1);
return ret;
}
public:
//在控制台打印测试用例
void testPrint()
{
//限制:只能打印100个元素以内的堆,因为控制台一行的字符数量有限
if (size() >=100)
{
cout <<"Fancy print can only work for less than 100 int";
return;
}
//限制:只能打印类型是int的堆
if (typeid(Item) !=typeid(int))
{
cout <<"Fancy print can only work for int item";
return;
}
cout <<"The Heap size is: " << size() << endl;
cout <<"data in heap: ";
for (int i =1; i <= size(); i++)
{
cout << data[i] <<" ";
}
cout << endl;
cout << endl;
int n = size();
int max_level =0;
int number_per_level =1;
while (n >0)
{
max_level +=1;
n -= number_per_level;
number_per_level *=2;
}
int max_level_number =int(pow(2, max_level -1));
int cur_tree_max_level_number = max_level_number;
int index =1;
for (int level =0; level < max_level; level++)
{
string line1 = string(max_level_number *3 - 1,' ');
int cur_level_number = min(count -int(pow(2, level)) +1,
int(pow(2, level)));
bool isLeft =true;
for (int index_cur_level =0; index_cur_level < cur_level_number;
index++, index_cur_level++)
{
putNumberInLine(data[index], line1, index_cur_level,
cur_tree_max_level_number *3 - 1, isLeft);
isLeft = !isLeft;
}
cout << line1 << endl;
if (level == max_level -1)
{
break;
}
string line2 = string(max_level_number *3 - 1,' ');
for (int index_cur_level =0; index_cur_level < cur_level_number;
index_cur_level++)
{
putBranchInLine(line2, index_cur_level, cur_tree_max_level_number *3 - 1);
}
cout << line2 << endl;
cur_tree_max_level_number /=2;
}
}
private:
void putNumberInLine(int num, string &line,int index_cur_level,
int cur_tree_width,bool isLeft)
{
int sub_tree_width = (cur_tree_width -1) / 2;
int offset = index_cur_level * (cur_tree_width +1) + sub_tree_width;
assert(offset +1 < line.size());
if (num >=10)
{
line[offset +0] = '0' + num /10;
line[offset +1] = '0' + num %10;
}
else
{
if (isLeft)
line[offset +0] = '0' + num;
else
line[offset +1] = '0' + num;
}
}
void putBranchInLine(string &line,int index_cur_level, int cur_tree_width)
{
int sub_tree_width = (cur_tree_width -1) / 2;
int sub_sub_tree_width = (sub_tree_width -1) / 2;
int offset_left = index_cur_level * (cur_tree_width +1) + sub_sub_tree_width;
assert(offset_left +1 < line.size());
int offset_right = index_cur_level * (cur_tree_width +1) + sub_tree_width
+1 + sub_sub_tree_width;
assert(offset_right < line.size());
line[offset_left +1] = '/';
line[offset_right +0] = '\\';
}
};
#endif
main.cpp:
#include"MaxHeap.h"
#include <ctime>
int main()
{
MaxHeap<int> maxheap = MaxHeap<int>(100);
srand(time(NULL));
for (int i =0; i < 15; i++)
{
maxheap.insert(rand() %100);
}
maxheap.testPrint();
cout << endl;
while (!maxheap.isEmpty())
{
cout << maxheap.extractMax() <<" ";
}
cout << endl;
/*cout << endl;
int arr[15];
for (int i = 0; i < 15; i++)
{
arr[i] = rand() % 100;
}
MaxHeap<int> maxheapx = MaxHeap<int>(arr, 15);
maxheapx.testPrint();
cout << endl;
while (!maxheapx.isEmpty())
{
cout << maxheapx.extractMax() << " ";
}
cout << endl;*/
system("pause");
return0;
}
运行一览:
程序 3:最小堆的实现
MinHeap.h:
#ifndef MINHEAP_H
#define MINHEAP_H
#include <iostream>
#include <algorithm>
#include <string>
#include <cmath>
#include <cassert>
using namespace std;
//最小堆:索引从1开始
template<typename Item>
class MinHeap
{
private:
Item *data;
int count;
int capacity;
//私有函数,用户不能调用
void shiftUp(int k)
{
//如果新添加的元素小于父节点的元素,则进行交换
while (k >1 && data[k / 2] > data[k])
{
swap(data[k /2], data[k]);
k /=2;
}
}
//也是私有函数,用户不能调用
void shiftDown(int k)
{
//只要当前节点有孩子就进行循环
while (2 * k <= count)
{
//在此轮循环中,data[k]和data[j]交换位置
int j =2 * k;
// data[j]是data[2*k]和data[2*k+1]中的最小值
if (j +1 <= count && data[j + 1] < data[j])
{
j++;
}
if (data[k] <= data[j])
{
break;
}
swap(data[k], data[j]);
k = j;
}
}
public:
MinHeap(int capacity)
{
//因为存储时是从索引1开始的,所以要加1
//即多开辟一个空间
data =new Item[capacity + 1];
//计数器,这里索引等于计数器
count =0;
this->capacity = capacity;
}
~MinHeap()
{
delete []data;
}
int size()
{
return count;
}
bool isEmpty()
{
return count ==0;
}
//向最小堆中添加新元素,新元素放在数组末尾
void insert(Item item)
{
//防止越界
assert(count +1 <= capacity);
//索引从1开始
data[count +1] = item;
count++;
//新加入的元素有可能破坏最小堆的定义,需要通过
//Shift Up操作,把索引为count的元素尝试着向上
//移动来保持最小堆的定义
shiftUp(count);
}
//取出最小堆中根节点的元素(最小值)
Item extractMin()
{
//首先要保证堆不为空
assert(count >0);
//取出根节点的元素(最小值)
Item ret = data[1];
//将第一个元素(最小值)和最后一个元素进行交换
swap(data[1], data[count]);
//count--后,被取出的根节点就不用再考虑了
count--;
//调用Shift Down操作,想办法将此时的根节点(索引为1)
//向下移动,来保持最小堆的定义
shiftDown(1);
return ret;
}
public:
//在控制台打印测试用例
void testPrint()
{
//限制:只能打印100个元素以内的堆,因为控制台一行的字符数量有限
if (size() >=100)
{
cout <<"Fancy print can only work for less than 100 int";
return;
}
//限制:只能打印类型是int的堆
if (typeid(Item) !=typeid(int))
{
cout <<"Fancy print can only work for int item";
return;
}
cout <<"The Heap size is: " << size() << endl;
cout <<"data in heap: ";
for (int i =1; i <= size(); i++)
{
cout << data[i] <<" ";
}
cout << endl;
cout << endl;
int n = size();
int max_level =0;
int number_per_level =1;
while (n >0)
{
max_level +=1;
n -= number_per_level;
number_per_level *=2;
}
int max_level_number =int(pow(2, max_level -1));
int cur_tree_max_level_number = max_level_number;
int index =1;
for (int level =0; level < max_level; level++)
{
string line1 = string(max_level_number *3 - 1,' ');
int cur_level_number = min(count -int(pow(2, level)) +1,
int(pow(2, level)));
bool isLeft =true;
for (int index_cur_level =0; index_cur_level < cur_level_number;
index++, index_cur_level++)
{
putNumberInLine(data[index], line1, index_cur_level,
cur_tree_max_level_number *3 - 1, isLeft);
isLeft = !isLeft;
}
cout << line1 << endl;
if (level == max_level -1)
{
break;
}
string line2 = string(max_level_number *3 - 1,' ');
for (int index_cur_level =0; index_cur_level < cur_level_number;
index_cur_level++)
{
putBranchInLine(line2, index_cur_level, cur_tree_max_level_number *3 - 1);
}
cout << line2 << endl;
cur_tree_max_level_number /=2;
}
}
private:
void putNumberInLine(int num, string &line,int index_cur_level,
int cur_tree_width,bool isLeft)
{
int sub_tree_width = (cur_tree_width -1) / 2;
int offset = index_cur_level * (cur_tree_width +1) + sub_tree_width;
assert(offset +1 < line.size());
if (num >=10)
{
line[offset +0] = '0' + num /10;
line[offset +1] = '0' + num %10;
}
else
{
if (isLeft)
line[offset +0] = '0' + num;
else
line[offset +1] = '0' + num;
}
}
void putBranchInLine(string &line,int index_cur_level, int cur_tree_width)
{
int sub_tree_width = (cur_tree_width -1) / 2;
int sub_sub_tree_width = (sub_tree_width -1) / 2;
int offset_left = index_cur_level * (cur_tree_width +1) + sub_sub_tree_width;
assert(offset_left +1 < line.size());
int offset_right = index_cur_level * (cur_tree_width +1) + sub_tree_width
+1 + sub_sub_tree_width;
assert(offset_right < line.size());
line[offset_left +1] = '/';
line[offset_right +0] = '\\';
}
};
#endif
main.cpp:
#include"MinHeap.h"
#include <ctime>
int main()
{
MinHeap<int> minheap = MinHeap<int>(100);
srand(time(NULL));
for (int i =0; i < 15; i++)
{
minheap.insert(rand() %100);
}
minheap.testPrint();
cout << endl;
while (!minheap.isEmpty())
{
cout << minheap.extractMin() <<" ";
}
cout << endl;
system("pause");
return0;
}
运行一览:
程序 4:最小堆的优化
MinHeap.h:
#ifndef MINHEAP_H
#define MINHEAP_H
#include <iostream>
#include <algorithm>
#include <string>
#include <cmath>
#include <cassert>
using namespace std;
//最小堆:索引从1开始
template<typename Item>
class MinHeap
{
private:
Item *data;
int count;
int capacity;
//私有函数,用户不能调用
//使用插入排序的优化方式进行优化
void shiftUp(int k)
{
Item e = data[k];
//如果新添加的元素小于父节点的值,
//则和父节点的值进行交换,即上升
while (k >1 && data[k / 2] > e)
{
data[k] = data[k /2];
k /=2;
}
data[k] = e;
}
//也是私有函数,用户不能调用
//使用插入排序的优化方式进行优化
void shiftDown(int k)
{
Item e = data[k];
//只要当前节点有孩子就进行循环
while (2 * k <= count)
{
//在此轮循环中,data[k]和data[j]交换位置
int j =2 * k;
// data[j]是data[2*k]和data[2*k+1]中的最小值
if (j +1 <= count && data[j + 1] < data[j])
{
j++;
}
if (e <= data[j])
{
break;
}
data[k] = data[j];
k = j;
}
data[k] = e;
}
public:
MinHeap(int capacity)
{
//因为存储时是从索引1开始的,所以要加1
//即多开辟一个空间
data =new Item[capacity + 1];
//计数器,这里索引等于计数器
count =0;
this->capacity = capacity;
}
MinHeap(Item arr[],int n)
{
data =new Item[n + 1];
capacity = n;
for (int i =0; i < n; i++)
{
data[i +1] = arr[i];
}
count = n;
//从最后一个非叶子节点的位置开始
for (int i = count /2; i >=1; i--)
{
//每次对索引为i的元素进行Shift Down操作
shiftDown(i);
}
}
~MinHeap()
{
delete []data;
}
int size()
{
return count;
}
bool isEmpty()
{
return count ==0;
}
//向最小堆中添加新元素,新元素放在数组末尾
void insert(Item item)
{
assert(count +1 <= capacity);
//索引从1开始
data[count +1] = item;
count++;
//新加入的元素有可能破坏最小堆的定义,需要通过
//Shift Up操作,把索引为count的元素尝试着向上
//移动来保持最小堆的定义
shiftUp(count);
}
//取出最小堆中根节点的元素(最小值)
Item extractMin()
{
//首先要保证堆不为空
assert(count >0);
//取出根节点的元素(最小值)
Item ret = data[1];
//将第一个元素(最小值)和最后一个元素进行交换
swap(data[1], data[count]);
//count--后,被取出的根节点就不用再考虑了
count--;
//调用Shift Down操作,想办法将此时的根节点(索引为1)
//向下移动,来保持最小堆的定义
shiftDown(1);
return ret;
}
public:
//在控制台打印测试用例
void testPrint()
{
//限制:只能打印100个元素以内的堆,因为控制台一行的字符数量有限
if (size() >=100)
{
cout <<"Fancy print can only work for less than 100 int";
return;
}
//限制:只能打印类型是int的堆
if (typeid(Item) !=typeid(int))
{
cout <<"Fancy print can only work for int item";
return;
}
cout <<"The Heap size is: " << size() << endl;
cout <<"data in heap: ";
for (int i =1; i <= size(); i++)
{
cout << data[i] <<" ";
}
cout << endl;
cout << endl;
int n = size();
int max_level =0;
int number_per_level =1;
while (n >0)
{
max_level +=1;
n -= number_per_level;
number_per_level *=2;
}
int max_level_number =int(pow(2, max_level -1));
int cur_tree_max_level_number = max_level_number;
int index =1;
for (int level =0; level < max_level; level++)
{
string line1 = string(max_level_number *3 - 1,' ');
int cur_level_number = min(count -int(pow(2, level)) +1,
int(pow(2, level)));
bool isLeft =true;
for (int index_cur_level =0; index_cur_level < cur_level_number;
index++, index_cur_level++)
{
putNumberInLine(data[index], line1, index_cur_level,
cur_tree_max_level_number *3 - 1, isLeft);
isLeft = !isLeft;
}
cout << line1 << endl;
if (level == max_level -1)
{
break;
}
string line2 = string(max_level_number *3 - 1,' ');
for (int index_cur_level =0; index_cur_level < cur_level_number;
index_cur_level++)
{
putBranchInLine(line2, index_cur_level, cur_tree_max_level_number *3 - 1);
}
cout << line2 << endl;
cur_tree_max_level_number /=2;
}
}
private:
void putNumberInLine(int num, string &line,int index_cur_level,
int cur_tree_width,bool isLeft)
{
int sub_tree_width = (cur_tree_width -1) / 2;
int offset = index_cur_level * (cur_tree_width +1) + sub_tree_width;
assert(offset +1 < line.size());
if (num >=10)
{
line[offset +0] = '0' + num /10;
line[offset +1] = '0' + num %10;
}
else
{
if (isLeft)
line[offset +0] = '0' + num;
else
line[offset +1] = '0' + num;
}
}
void putBranchInLine(string &line,int index_cur_level, int cur_tree_width)
{
int sub_tree_width = (cur_tree_width -1) / 2;
int sub_sub_tree_width = (sub_tree_width -1) / 2;
int offset_left = index_cur_level * (cur_tree_width +1) + sub_sub_tree_width;
assert(offset_left +1 < line.size());
int offset_right = index_cur_level * (cur_tree_width +1) + sub_tree_width
+1 + sub_sub_tree_width;
assert(offset_right < line.size());
line[offset_left +1] = '/';
line[offset_right +0] = '\\';
}
};
#endif
main.cpp:
#include"MinHeap.h"
#include <ctime>
int main()
{
MinHeap<int> minheap = MinHeap<int>(100);
srand(time(NULL));
for (int i =0; i < 15; i++)
{
minheap.insert(rand() %100);
}
minheap.testPrint();
cout << endl;
while (!minheap.isEmpty())
{
cout << minheap.extractMin() <<" ";
}
cout << endl;
/*cout << endl;
int arr[15];
for (int i = 0; i < 15; i++)
{
arr[i] = rand() % 100;
}
MinHeap<int> minheapx = MinHeap<int>(arr, 15);
minheapx.testPrint();
cout << endl;
while (!minheapx.isEmpty())
{
cout << minheapx.extractMin() << " ";
}
cout << endl;*/
system("pause");
return0;
}
运行一览:
【made by siwuxie095】
- 堆 续2
- 堆 续1
- 堆 续3
- 堆 续4
- 堆 续5
- 堆 续6
- 堆 续7
- 堆 续8
- 堆 续9
- 堆(2)
- 堆和栈2
- 堆和栈(2)
- 堆排序(2)
- 堆
- 堆
- 堆
- 堆
- 堆
- LeetCode Min Stack
- 使用gdb调试多进程多线程程序
- OJ系统之题目列表界面
- MySQL入门--显示指定数据表的字段结构、插入指定字段的值(记录)、查看指定表中指定字段的所有记录
- 公钥密码学、数字签名与数字证书
- 堆 续2
- ionic第三方QQ,微博,微信的登录,分享功能的实现和注意事项
- [ssh]关于ssh中查询并分页方法的记录
- 解决IllegalStateException: Can not perform this action after onSaveInstanceState
- Mac 升级python2.7 到 3.5
- java的GC机制--java的内存分配机制
- gulp搭建的项目完美编译sass
- 网络状态码含义
- Java学习笔记---自动拆装箱