優先佇列儲存自定義型別物件的指標
阿新 • • 發佈:2022-05-28
一開始我想用優先佇列來實現構造哈夫曼樹,並以指標方式儲存每個結點的左右兒子的地址
很自然的想到如下的程式碼
#include <iostream> #include <algorithm> #include <queue> using namespace std; const int MAX_N = 500; struct node { int v; node *le, *ri; node(int _v) : v(_v) { le = NULL, ri = NULL; } node(const node& x) { v = x.v, le = x.le, ri = x.ri; } bool operator < (const node& x) const { return v > x.v; } }; priority_queue<node> q; void dfs(node *cur, int& ans, int lev) { if ((!cur->le) && (!cur->ri)) { ans += cur->v * lev; return; } if (cur->le) dfs(cur->le, ans, lev + 1); if (cur->ri) dfs(cur->ri, ans, lev + 1); } int main() { int n, ans = 0; cin >> n; node *root = NULL, *newnode = NULL; while (n--) { int tmp; cin >> tmp; newnode = new node(tmp); q.push(*newnode); } while (q.size() > 1) { node a = q.top(); q.pop(); node b = q.top(); q.pop(); newnode = new node(a.v + b.v); newnode->le = &a; newnode->ri = &b; q.push(*newnode); root = newnode; } q.pop(); dfs(root, ans, 0); cout << ans << endl; return 0; }
結果發現 \(RE\) 了,樹的父子關係根本沒有得到有效的儲存
除錯與思考了很久以後發現,這是因為STL 容器中存放的元素是拷貝而不是引用
對於內建型別(int float char等),容器的工作方式是純粹的位拷貝。
而當你向容器中新增一個自定義的物件(比如通過insert或push_back等),進入容器的是你指定的物件的拷貝。容器中存放的物件不是你給它們的那個物件,因為兩個物件在記憶體中的位置不一樣。
此外,當你從容器中獲取一個物件時,你所得到的物件也不是容器裡的那個物件。取而代之的是容器中物件的拷貝。
拷進去,拷出來。拷貝是STL的方式。
那麼為了解決這個問題,我們可以將物件的引用或者指標傳入容器。而容器是不支援容納物件的引用的
因此我們採用傳入物件的指標來解決這個問題,同時需要自定義優先佇列中的比較器
一般採取傳入函式物件的方式,可以參考這個部落格
那麼改正後的程式碼如下:
#include <iostream> #include <algorithm> #include <queue> using namespace std; const int MAX_N = 500; struct node { int v; node *le, *ri; node(int _v) : v(_v) { le = NULL, ri = NULL; } node(const node& x) { v = x.v, le = x.le, ri = x.ri; } }; struct cmp { // 函式指標型別比較器 bool operator()(const node* a, const node* b) const { return a->v > b->v; } }; priority_queue<node*, vector<node*>, cmp > q; void dfs(node *cur, int& ans, int lev) { if ((!cur->le) && (!cur->ri)) { ans += cur->v * lev; return; } if (cur->le) dfs(cur->le, ans, lev + 1); if (cur->ri) dfs(cur->ri, ans, lev + 1); } int main() { int n, ans = 0; cin >> n; node *root = NULL, *newnode = NULL; while (n--) { int tmp; cin >> tmp; newnode = new node(tmp); q.push(newnode); } while (q.size() > 1) { node* a = q.top(); q.pop(); node* b = q.top(); q.pop(); newnode = new node(a->v + b->v); newnode->le = a; newnode->ri = b; q.push(newnode); root = newnode; } q.pop(); dfs(root, ans, 0); cout << ans << endl; return 0; }