看看這樣說:
0 00 000 | (0,0) (0,1) (0,2)
001 | (1,2)
1 10 100 | (2,0) (2,1) (2,2)
101 | (3,2)
11 | (4,1)
我用同樣的語法可以命名節點(左側)和相應的位置「(行,列)」到網格(右側) 。這裏有兩個頂級部門,0和1. 您可以用「(x,y)」座標爲每個樹/頂級部門的深度首次訪問標記節點。每當你從父親到孩子下降,你必須增加1列號。 每次你訪問一個新的兄弟姐妹時,你的行索引必須指向一個新的空行(在這個例子中,10的兄弟姐妹是11,但是你(3,1)不能放入,因爲第3行已被101部門佔用)。
我會按照這些指南編寫算法。使用作爲遞歸深度優先訪問的參數傳遞的兩個變量以及要訪問的當前節點/部門來跟蹤當前(x,y)。確保函數根據需要編輯excel表示,但返回使用的最大行索引(以便您可以在訪問新的同級時使用它來知道下一行是哪一行 - 如前例所示)。 每次您進行遞歸調用時,都必須用coords(x,y + 1)調用它,因爲它是一個新列。以類似的方式,當你訪問一個新的兄弟姐妹時,你用(coords prev_call_retn + 1,y)調用它,因爲它是一個新行(其中coords_prev_call_retn是前一個兄弟上次遞歸調用的值)。 輔助函數將調用根節點上的遞歸函數,並將其用作基礎座標(0,0)或任何您喜歡的起點。
#include <iostream>
#include <list>
#include <string>
using namespace std;
class Dept {
public:
string id;
list<Dept*> *subDepts;
Dept(string id) {
this->id = id;
this->subDepts = new list<Dept*>();
}
Dept *addChild(Dept *d) {
this->subDepts->push_back(d);
return d;
}
Dept *addChild(string id) {
Dept *d = new Dept(id);
return this->addChild(d);
}
};
void visit(Dept *d, int row, int col) {
cout << "Dept " << d->id << ": (" << row << ", " << col << ")\n";
}
int label(Dept *d, int row, int col) {
if (d == 0) return row;
visit(d, row, col);
list<Dept*> *lst = d->subDepts;
for (list<Dept*>::iterator it = lst->begin() ; it != lst->end(); it++)
{
row = label(*it, row, col+1) + 1;
}
if (lst->size() > 0) row--;
return row;
}
int label(Dept *d) {
label(d, 0, 0);
}
在這個C++代碼,標籤()是你感興趣的函數。
參數ROW和COL都應該是部門* d的正確的座標,這樣我們就可以立即訪問該節點。
循環遞歸調用每個孩子(如果有的話)的label()。請注意,我使用變量行來跟蹤最後一次使用的行+1。
最後,我們必須返回函數上次使用的行,但要小心減去一個,如果d-> subDepts不是空的。這是因爲在上一次迭代中增加了1行的for循環。
下面是主要的一個例子:
int main(int argc, char **argv) {
Dept *d0 = new Dept("0");
Dept *d00 = d0->addChild("00");
Dept *d01 = d0->addChild("01");
Dept *d000 = d00->addChild("000");
Dept *d001 = d00->addChild("001");
Dept *d002 = d00->addChild("002");
Dept *d010 = d01->addChild("010");
Dept *d02 = d0->addChild("02");
label(d0);
return 0;
}
而這裏的結果:
bash-4.2$ g++ dept.cpp && ./a.out
Dept 0: (0, 0)
Dept 00: (0, 1)
Dept 000: (0, 2)
Dept 001: (1, 2)
Dept 002: (2, 2)
Dept 01: (3, 1)
Dept 010: (3, 2)
Dept 02: (4, 1)
我希望這有助於。
感謝您的良好回答,我嘗試編寫代碼,但我無法做到,我不擅長算法。你有空時可以抽出一些時間嗎? – hguser
不客氣。在這裏,我通過添加一個有效的C++示例來編輯我的答案。 –
,謝謝。它的工作原理,但是我不知道是否有任何可以計算每個單元格的行跨度和列跨度?在你的例子中,'Dep0'將取一列和兩行,'Dep11'取兩列和一行。 – hguser