樹
定義:
樹有n個節點,當n=0時,該樹是空樹,當n>=1時,除根結點的左右子樹節點各不相同,並且每一個子樹又可以當作一個樹,依次類推到最後。
存儲方式:
數組存儲:
存儲樹必須要存儲各個節點之間的關係,爲了存儲這種關係,需要定義一種結構體
struct Node
{
int value
int parent,firstchild; //此種定義方式方便節點尋找子節點,雙親節點
}
struct Node
{
int value
int parent,right; //此種定義方式方便尋找雙親還有兄弟
}
用一維數組將各個節點存儲在數組中。
鏈表存儲:
struct Node
{
int data;
Node *child1,.....child;//存儲子節點
}
這種方式存儲節點的方式較爲麻煩與浪費空間,並且每一個節點的子節點數量不同,選用最多的子節點數來設置子節點數目會導致空間的浪費,變換的方式會很複雜。
struct Node
{
int data;
Node *child,Node *right; //存儲第一個子節點與右兄弟節點
}
二叉樹
定義
二叉樹也是樹的一種,二叉樹中的兩個指針是左子節點與右子節點
struct Node
{
int data;
Node *rchild,*lchild; //存儲節點的右子節點與左子節點
}
遍歷方式
先序遍歷:
先遍歷根節點,在遍歷左子樹,最終遍歷右子樹
後序遍歷:
先遍歷左子樹,在遍歷右子樹,最終遍歷根節點
中序遍歷:
先遍歷左子樹,然後遍歷根節點,最終遍歷右子樹
通常實現二叉樹遍歷可以可以使用遞歸的思想,這種遍歷方式的好處是代碼簡潔,代碼數量少,但是缺點是需要佔用大量的內存,執行速度慢。
實現代碼:
void preprint(Node *t)
{
if (t)
{
return;
}
cout<<t->data;
preprint(t—>lchild);
preprint(t—>rchild);
}
上述代碼實現的是前序遍歷,而實現中序遍歷與後序遍歷僅僅是將cout<data;改變一下位置即可。
爲了減少遍歷的時間,還可以對二叉樹進行非遞歸的遍歷
前序遍歷代碼:
stack<Tree*> all;
all.push(first);
cout<<first->value;
while(1)
{
if(all.top()->l)
{
all.push(all.top()->l);
cout<<all.top()->value;
}
else{
break;
}
}
while(!all.empty())
{
if(all.top()->r)
{
all.push(all.top()->r);
cout<<all.top()->value;
break;
}
else{
all.pop();
}
}
中序遍歷,後序遍歷同樣也可以使用棧方式進行遍歷。
總結
樹的遍歷操作使用遞歸的方式遍歷代碼會相對簡單,但是佔用的內存比非遞歸要明顯增多,至於那種方式都可。