堆 续8

----------------------siwuxie095

索引从 0 开始

程序 1:最小索引堆的实现

MinIndexHeap.h:


#ifndef MININDEXHEAP_H

#define MININDEXHEAP_H

#include <iostream>

#include <string>

#include <cassert>

#include <algorithm>

using namespace std;

//最小索引堆:索引从0开始

template<typename Item>

class MinIndexHeap

{

private:

Item *data; //指向存储元素的数组

int *indexes; //指向存储索引的数组

int count;

int capacity;

//私有函数,用户不能调用

void shiftUp(int k)

{

//如果新添加的元素小于父节点的元素,则进行交换

while (k > 0 && data[indexes[(k - 1) / 2]] > data[indexes[k]])

{

swap(indexes[(k - 1) / 2], indexes[k]);

k = (k - 1) / 2;

}

}

//也是私有函数,用户不能调用

void shiftDown(int k)

{

//只要当前节点有孩子就进行循环

while (2 * k + 1 < count)

{

// 在此轮循环中,data[indexes[k]]和data[indexes[j]]交换位置

int j = 2 * k + 1;

// data[indexes[j]]是data[indexes[j]]和data[indexes[j+1]]中的最小值

if (j + 1 < count && data[indexes[j + 1]] < data[indexes[j]])

{

j += 1;

}

if (data[indexes[k]] <= data[indexes[j]])

{

break;

}

swap(indexes[k], indexes[j]);

k = j;

}

}

public:

MinIndexHeap(int capacity)

{

data = new Item[capacity];

indexes = new
int[capacity];

//计数器,这里索引等于计数器减一

count = 0;

this->capacity = capacity;

}

~MinIndexHeap()

{

delete []data;

delete []indexes;

}

int size()

{

return count;

}

bool isEmpty()

{

return count == 0;

}

void insert(int i, Item item)

{

//防止越界

assert(count <= capacity);

assert(i >= 0 && i <= capacity);

data[i] = item;

indexes[count] = i;

count++;

shiftUp(count - 1);

}

//取出最小的data

Item extractMin()

{

//首先要保证堆不为空

assert(count > 0);

Item ret = data[indexes[0]];

swap(indexes[0], indexes[count - 1]);

count--;

shiftDown(0);

return ret;

}

//取出最小的data对应的index

int extractMinIndex()

{

assert(count > 0);

int ret = indexes[0];

swap(indexes[0], indexes[count - 1]);

count--;

shiftDown(0);

return ret;

}

Item getMin()

{

assert(count > 0);

return data[indexes[0]];

}

int getMinIndex()

{

assert(count > 0);

return indexes[0];

}

Item getItem(int i)

{

return data[i];

}

//修改 index 对应的 data

void change(int i, Item newItem)

{

data[i] = newItem;

// 找到indexes[j] = i, j表示data[i]在堆中的位置

// 之后尝试着shiftUp(j)一下, 再shiftDown(j)一下

//即
看看能不能向上或向下移动以保持堆的性质

for (int j = 0; j < count; j++)

{

if (indexes[j] == i)

{

shiftUp(j);

shiftDown(j);

return;

}

}

//该函数的时间复杂度O(n)+O(lgn)级别的,也就是O(n)级别的函数

//其中:遍历是n,Shift Up和Shift Down是lgn

//

//之前的插入操作和删除操作,都能保证是lgn级别的,使得它的性

//能优势非常明显,现在修改一个元素,它的时间复杂度变成了O(n)

//级别,那么对用户来讲,在外部进行n个堆操作,在最坏的情况下,

//总的时间就有可能变成O(n^2)这个级别,这是非常不理想的一种情

//况,change()这个函数可以进行优化

}

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 = 0; 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 = 0;

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(indexes[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
"MinIndexHeap.h"

#include <ctime>

int main()

{

MinIndexHeap<int> minIndexHeap = MinIndexHeap<int>(100);

srand(time(NULL));

for (int i = 0; i < 15; i++)

{

minIndexHeap.insert(i, rand() % 100);

}

minIndexHeap.testPrint();

cout << endl;

while (!minIndexHeap.isEmpty())

{

cout << minIndexHeap.extractMin() << " ";

}

cout << endl;

system("pause");

return
0;

}

运行一览:

程序 2:最小索引堆的优化

MinIndexHeap.h:


#ifndef MININDEXHEAP_H

#define MININDEXHEAP_H

#include <iostream>

#include <string>

#include <cassert>

#include <algorithm>

using namespace std;

//最小索引堆:索引从0开始

template<typename Item>

class MinIndexHeap

{

private:

Item *data; //指向存储元素的数组

int *indexes; //指向存储索引的数组

int *reverse; //指向存储反向索引的数组

int count;

int capacity;

//私有函数,用户不能调用

void shiftUp(int k)

{

//如果新添加的元素小于父节点的元素,则进行交换

while (k > 0 && data[indexes[(k - 1) / 2]] > data[indexes[k]])

{

swap(indexes[(k - 1) / 2], indexes[k]);

reverse[indexes[(k - 1) / 2]] = (k - 1) / 2;

reverse[indexes[k]] = k;

k = (k - 1) / 2;

}

}

//也是私有函数,用户不能调用

void shiftDown(int k)

{

//只要当前节点有孩子就进行循环

while (2 * k + 1 < count)

{

// 在此轮循环中,data[indexes[k]]和data[indexes[j]]交换位置

int j = 2 * k + 1;

// data[indexes[j]]是data[indexes[j]]和data[indexes[j+1]]中的最小值

if (j + 1 < count && data[indexes[j + 1]] < data[indexes[j]])

{

j += 1;

}

if (data[indexes[k]] <= data[indexes[j]])

{

break;

}

swap(indexes[k], indexes[j]);

reverse[indexes[k]] = k;

reverse[indexes[j]] = j;

k = j;

}

}

public:

MinIndexHeap(int capacity)

{

data = new Item[capacity];

indexes = new
int[capacity];

reverse = new
int[capacity];

//初始化reverse数组

for (int i = 0; i < capacity; i++)

{

reverse[i] = -1;

}

//计数器,这里索引等于计数器减一

count = 0;

this->capacity = capacity;

}

~MinIndexHeap()

{

delete []data;

delete []indexes;

delete []reverse;

}

int size()

{

return count;

}

bool isEmpty()

{

return count == 0;

}

void insert(int i, Item item)

{

//防止越界

assert(count <= capacity);

assert(i >= 0 && i <= capacity);

data[i] = item;

indexes[count] = i;

reverse[i] = count;

count++;

shiftUp(count - 1);

}

//取出最小的data

Item extractMin()

{

//首先要保证堆不为空

assert(count > 0);

Item ret = data[indexes[0]];

swap(indexes[0], indexes[count - 1]);

reverse[indexes[count - 1]] = -1;

reverse[indexes[0]] = 0;

count--;

shiftDown(0);

return ret;

}

//取出最小的data对应的index

int extractMinIndex()

{

assert(count > 0);

//对于外部来说,索引从0开始,所以要减一

int ret = indexes[0];

swap(indexes[0], indexes[count - 1]);

reverse[indexes[count - 1]] = -1;

reverse[indexes[0]] = 0;

count--;

shiftDown(0);

return ret;

}

Item getMin()

{

assert(count > 0);

return data[indexes[0]];

}

int getMinIndex()

{

assert(count > 0);

return indexes[0];

}

bool contain(int i){

assert(i >= 0 && i <= capacity);

//reverse数组在构造函数中都初始化为-1,

//所以拿-1做比较

return reverse[i] != -1;

}

Item getItem(int i)

{

assert(contain(i));

//对于外部来说,索引从0开始,

//对于内部来说,索引从1开始,

//所以要加一

return data[i];

}

//修改 index 对应的 data

void change(int i, Item newItem)

{

//防止越界和检查i是否在堆中,

//因为有可能已经取出去了

assert(contain(i));

data[i] = newItem;

// 找到indexes[j] = i, j表示data[i]在堆中的位置

// 之后尝试着shiftUp(j)一下, 再shiftDown(j)一下

//即
看看能不能向上或向下移动以保持堆的性质

int j = reverse[i];

shiftUp(j);

shiftDown(j);

//先用O(1)的时间找到位置,再用O(lgn)的时间完成

//Shift Up和Shift Down,此时,该函数的时间复杂

//度就是O(lgn)级别的,如果有n个堆操作,总时间

//就是O(n*lgn)

//

//加入了反向查找后,性能得到了巨大的提升

}

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 = 0; 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 = 0;

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(indexes[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
"MinIndexHeap.h"

#include <ctime>

int main()

{

MinIndexHeap<int> minIndexHeap = MinIndexHeap<int>(100);

srand(time(NULL));

for (int i = 0; i < 15; i++)

{

minIndexHeap.insert(i, rand() % 100);

}

minIndexHeap.testPrint();

cout << endl;

while (!minIndexHeap.isEmpty())

{

cout << minIndexHeap.extractMin() << " ";

}

cout << endl;

system("pause");

return
0;

}

运行一览:

程序 3:最小索引堆的再优化

MinIndexHeap.h:


#ifndef MININDEXHEAP_H

#define MININDEXHEAP_H

#include <iostream>

#include <string>

#include <cassert>

#include <algorithm>

using namespace std;

//最小索引堆:索引从0开始

template<typename Item>

class MinIndexHeap

{

private:

Item *data; //指向存储元素的数组

int *indexes; //指向存储索引的数组

int *reverse; //指向存储反向索引的数组

int count;

int capacity;

//私有函数,用户不能调用

//使用插入排序的优化方式进行优化

void shiftUp(int k)

{

Item e = data[indexes[k]];

int i = indexes[k];

//如果新添加的元素小于父节点的元素,则进行交换

while (k > 0 && data[indexes[(k - 1) / 2]] > e)

{

indexes[k] = indexes[(k - 1) / 2];

reverse[indexes[k]] = k;

k = (k - 1) / 2;

}

indexes[k] = i;

reverse[indexes[k]] = k;

}

//也是私有函数,用户不能调用

//使用插入排序的优化方式进行优化

void shiftDown(int k)

{

Item e = data[indexes[k]];

int i = indexes[k];

//只要当前节点有孩子就进行循环

while (2 * k + 1 < count)

{

// 在此轮循环中,data[indexes[k]]和data[indexes[j]]交换位置

int j = 2 * k + 1;

// data[indexes[j]]是data[indexes[j]]和data[indexes[j+1]]中的最小值

if (j + 1 < count && data[indexes[j + 1]] < data[indexes[j]])

{

j += 1;

}

if (e <= data[indexes[j]])

{

break;

}

indexes[k] = indexes[j];

reverse[indexes[k]] = k;

k = j;

}

indexes[k] = i;

reverse[indexes[k]] = k;

}

public:

MinIndexHeap(int capacity)

{

data = new Item[capacity];

indexes = new
int[capacity];

reverse = new
int[capacity];

//初始化reverse数组

for (int i = 0; i < capacity; i++)

{

reverse[i] = -1;

}

//计数器,这里索引等于计数器减一

count = 0;

this->capacity = capacity;

}

~MinIndexHeap()

{

delete []data;

delete []indexes;

delete []reverse;

}

int size()

{

return count;

}

bool isEmpty()

{

return count == 0;

}

void insert(int i, Item item)

{

//防止越界

assert(count <= capacity);

assert(i >= 0 && i <= capacity);

data[i] = item;

indexes[count] = i;

reverse[i] = count;

count++;

shiftUp(count - 1);

}

//取出最小的data

Item extractMin()

{

//首先要保证堆不为空

assert(count > 0);

Item ret = data[indexes[0]];

swap(indexes[0], indexes[count - 1]);

reverse[indexes[count - 1]] = -1;

reverse[indexes[0]] = 0;

count--;

shiftDown(0);

return ret;

}

//取出最小的data对应的index

int extractMinIndex()

{

assert(count > 0);

//对于外部来说,索引从0开始,所以要减一

int ret = indexes[0];

swap(indexes[0], indexes[count - 1]);

reverse[indexes[count - 1]] = -1;

reverse[indexes[0]] = 0;

count--;

shiftDown(0);

return ret;

}

Item getMin()

{

assert(count > 0);

return data[indexes[0]];

}

int getMinIndex()

{

assert(count > 0);

return indexes[0];

}

bool contain(int i){

assert(i >= 0 && i <= capacity);

//reverse数组在构造函数中都初始化为-1,

//所以拿-1做比较

return reverse[i] != -1;

}

Item getItem(int i)

{

assert(contain(i));

//对于外部来说,索引从0开始,

//对于内部来说,索引从1开始,

//所以要加一

return data[i];

}

//修改 index 对应的 data

void change(int i, Item newItem)

{

//防止越界和检查i是否在堆中,

//因为有可能已经取出去了

assert(contain(i));

data[i] = newItem;

// 找到indexes[j] = i, j表示data[i]在堆中的位置

// 之后尝试着shiftUp(j)一下, 再shiftDown(j)一下

//即
看看能不能向上或向下移动以保持堆的性质

int j = reverse[i];

shiftUp(j);

shiftDown(j);

//先用O(1)的时间找到位置,再用O(lgn)的时间完成

//Shift Up和Shift Down,此时,该函数的时间复杂

//度就是O(lgn)级别的,如果有n个堆操作,总时间

//就是O(n*lgn)

//

//加入了反向查找后,性能得到了巨大的提升

}

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 = 0; 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 = 0;

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(indexes[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
"MinIndexHeap.h"

#include <ctime>

int main()

{

MinIndexHeap<int> minIndexHeap = MinIndexHeap<int>(100);

srand(time(NULL));

for (int i = 0; i < 15; i++)

{

minIndexHeap.insert(i, rand() % 100);

}

minIndexHeap.testPrint();

cout << endl;

while (!minIndexHeap.isEmpty())

{

cout << minIndexHeap.extractMin() << " ";

}

cout << endl;

system("pause");

return
0;

}

运行一览:

【made by siwuxie095】

时间: 2024-07-30 13:46:42

堆 续8的相关文章

堆 续4

--------------------siwuxie095 索引堆 这里介绍一个比普通堆更加高级的数据结构:索引堆(Index Heap) 首先来看一下普通堆有什么问题 或 缺点: 将一个数组通过 Heapify 构建成一个堆,对于这个数组而言, 在堆构建前和堆构建后,它的元素位置发生了改变,正是因为 元素位置的改变,才使得它被看做是一个堆 但在构建堆的过程中,改变元素的位置将会有一些局限性: (1)如果元素是非常复杂的结构,如:元素是字符串,那么交换这些元素 本身,消耗就是巨大的 比如说:如

堆 续2

---------------------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

--------------------siwuxie095 堆的基本存储 在堆中实现的插入操作和删除操作,都是 logN 级别的, 显然,堆一定相应的是一个树形结构,最为经典的一种 堆的实现叫做 二叉堆(Binary Heap) 二叉堆对应的是二叉树,所谓二叉树,就是每一个节点, 最多有两个子节点 那么这个二叉树有什么特点呢? 分为两种情况: (一)最大堆 1)它的任何一个节点都不大于它的父节点 2)它必须是一棵完全二叉树 满足上面两个性质的二叉树,称为 最大堆 也即 1)堆中某个节点的值总是

数据结构-各类排序算法总结[续]

各类排序算法总结 三.交换类排序[接上] 2.快速排序 快速排序是通过比较关键码.交换记录,以某个记录为界(该记录称为支点),将待排序列分成两部分.其中,一部分所有记录的关键码大于等于支点记录的关键码,另一部分所有记录的关键码小于支点记录的关键码.我们将待排序列按关键码以支点记录分成两部分的过程,称为一次划分.对各部分不断划分,直到整个序列按关键码有序. 如果每次划分对一个元素定位后,该元素的左侧子序列与右侧子序列的长度相同,则下一步将是对两个长度减半的子序列进行排序,这是最理想的情况! [算法

栈内存和堆内存的区别

总结: 1 栈:为编译器自动分配和释放,如函数参数.局部变量.临时变量等等 2 堆:为成员分配和释放,由程序员自己申请.自己释放.否则发生内存泄露.典型为使用new申请的堆内容. 除了这两部分,还有一部分是: 3 静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.它主要存放静态数据.全局数据和常量. 转自: 栈内存和堆内存的区别(一个笔试题的一部分)http://blog.csdn.net/richerg85/article/details/19175133 笔试

【裸单源最短路:Dijkstra算法两种版本】hdu 1874 畅通工程续

Source : hdu 1874 畅通工程续 http://acm.hdu.edu.cn/showproblem.php?pid=1874 Problem Description 某省自从实行了很多年的畅通工程计划后,终于修建了很多路.不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多.这让行人很困扰. 现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离. Input 本题目包含多组数据,请处理到文件结束.

浅谈数据结构-堆

在数据结构的世界中有一个叫堆的玩意,这玩意有什么用呢?无用,都去pq了 堆,其实就是一棵完全二叉树. “若设二叉树的深度为h,除第 h 层外,其它各层 (1-h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树”  by 谋财害命公司 百度 ↑清真的 完全二叉树 ↓ 啊那么为什么会闲的无聊出现这种奇怪的数据结构呢? 因为我们的某些算法可能需要堆来进行优化,如dj,prim. 堆可以在O(1)的时间取出最优值,但是需要O(logn)的时间修改和O(nlogn)

1续hdu1009

上网查了资料,看了其他人写的代码,学到了一下一些: c++头文件:algorithm.h 这个头文件可以对范围内的数据做任何处理 #include<algorithm> 里面包含的函数有:   非修改性序列操作(12个)   循环 对序列中的每个元素执行某操作 for_each()   查找 在序列中找出某个值的第一次出现的位置 find()   在序列中找出符合某谓词的第一个元素 find_if()   在序列中找出一子序列的最后一次出现的位置 find_end()   在序列中找出第一次出

设计模式一(续)

本篇是接着设计模一:观察者模式的续写. 为什么要写这一篇呢: java在main函数里new出的对象都是局部变量,而用C++ 在main函数里new出来的都是 动态分配到堆区的. 那么可不可以按照java的思路来写呢. 这就是写本篇的原因了:C++完全可以按照java的思路来实现(使用引用) 附上代码: #include "stdafx.h" #include<iostream> #include<string> #include<vector> u