數據結構—無序樹


 


 

基本術語:

節點的度:書中某一節點擁有的子節點數量。

數的度:該樹中所有節點的度的最大值。

葉節點(終端節點):度為零的節點。

分支節點(非終端節點):度不為零的節點。

根節點(開始節點):樹中的第一個節點。

內部節點:樹中除了根節點之外的節點。

節點的層數:若根節點層數為1,根節點的第n代子節點的層數為n。

樹的高度:書中的節點的最大層數。

有序樹和無序樹:若樹中某一節點的子節點無序,則該樹為無序樹,否則為有序樹。

森林:去掉一棵樹的根節點后得到的n棵樹。

樹的特點:

1.樹是一種很基礎很重要的非線性結構。

2.除表頭(樹根)和表尾(葉節點)外,任何一個節點只有一個直接前驅,但有多個直接后繼。

3.樹是數據的有限集,樹分為空樹和非空樹。 

  非空樹:有且只有一個根節點。若根節點的子節點大於1,可以理解為這棵非空樹有m棵相互獨立的非空樹組成。

4.樹的遞歸特性(★★★):一顆非空樹有若干子樹組成,每一棵子樹又由更小的子組成。


 

C++實現:

[MyTree.h]:無序樹類模板頭文件

#pragma once template<class T>
class MyTree { private: struct TreeNode  //定義私有,不讓用戶使用
 { T data; //數據域,可以多個數據 //指針域
        TreeNode *parent;   //節點的父指針
        TreeNode *child;    //子指針
        TreeNode *brother;    //兄弟指針 兄弟之間逐級管理
 }; TreeNode *pRoot;   //根節點

public: MyTree(); ~MyTree(); void clear(); void insertNode(const T& parentData, const T& insertData, bool insertChild = true); //默認插入為子節點 //bool isFind(const T& findData);
    void preOrderPrint(TreeNode *root /*= pRoot*/);  //前序(前根)遍歷
    void posOrderPrint(TreeNode *root /*= pRoot*/);  //前序(后根)遍歷
    void inOrderPrint(TreeNode *root  /*= pRoot*/);   //中序(中根)遍歷 
    TreeNode* getTreeRoot(); private: void _clear(TreeNode *root);        //用於clear()函數的實現,不提供接口
    TreeNode* _find(TreeNode *root, const T& findData); }; template<class T> typename MyTree<T>::TreeNode* MyTree<T>::getTreeRoot() { return pRoot; } template<class T>
void MyTree<T>::inOrderPrint(TreeNode *root /*= pRoot*/) { if (!root) return; inOrderPrint(root->child); std::cout << root->data << " "; inOrderPrint(root->brother); } template<class T>
void MyTree<T>::posOrderPrint(TreeNode *root /*= pRoot*/) { if (!root) return; posOrderPrint(root->child); posOrderPrint(root->brother); std::cout << root->data << " "; } template<class T>
void MyTree<T>::preOrderPrint(TreeNode *root /*= pRoot*/) { if (!root) return; std::cout << root->data << " "; preOrderPrint(root->child); preOrderPrint(root->brother); } template<class T>
void MyTree<T>::insertNode(const T& parentData, const T& insertData, bool insertChild /*= true*/) { TreeNode *tempInsertNode = new TreeNode;    //生成一個待插入的節點
    tempInsertNode->data = insertData; tempInsertNode->parent = NULL; tempInsertNode->child = NULL; tempInsertNode->brother = NULL; if (pRoot)  //判斷樹是否為空
 { TreeNode *findNode = _find(pRoot, parentData);    //找到插入位置
        if (findNode) {//找到了插入位置
            if (insertChild) {//在子節點插入
                TreeNode *temp = findNode->child; if (temp) { while (temp->brother) temp = temp->brother; temp->brother = tempInsertNode; tempInsertNode->parent = findNode; } else { findNode->child = tempInsertNode; tempInsertNode->parent = findNode; } } else {//在兄弟節點插入
                if (findNode->brother) { TreeNode *tempNode = findNode->brother; while (tempNode->brother) tempNode = tempNode->brother; tempNode->brother = tempInsertNode; tempInsertNode->parent = tempNode->parent; } else { //沒有兄弟節點
                    findNode->brother = tempInsertNode; tempInsertNode->parent = findNode->parent; } } } else {//如果沒有找到插入位置 設計為插入在末尾
            std::cout << "can not find the parent,insert the data in the end" << std::endl; TreeNode *temp = pRoot; while (temp->child) temp = temp->child; temp->child = tempInsertNode; tempInsertNode->parent = temp; } } else {//樹為空的情況 // TreeNode *temp = new TreeNode; // temp->data = insertData; // temp->parent = NULL; // inNode->child = inNode->brother = NULL;
        pRoot = tempInsertNode; } } template<class T> typename MyTree<T>::TreeNode * MyTree<T>::_find(TreeNode *root, const T& findData) { if (root)    /*遞歸結束條件 傳入的的指針為空 例如判斷葉節點是 將葉子節點的子節點傳入遞歸函數, 不滿足條件直接返回空*/ { //先判斷本節點 在判斷子節點 最后判斷兄弟節點 找到直接返回 不繼續找
        if (root->data == findData)        //判斷當前節點是否為 需要找的節點
            return root; TreeNode * temp = _find(root->child, findData); if (temp) return temp; if (temp = _find(root->brother, findData)) return temp; } return NULL;    //若沒有找到 返回為空
} template<class T>
void MyTree<T>::_clear(TreeNode *root) { //用遞歸刪除所有節點 樹的遞歸特性
    if (root) { _clear(root->child); _clear(root->brother);  //先刪除兄弟和先刪除兒子一樣
        delete[]root;        //必須先刪除兄弟和兒子后才能刪除自己
        root = nullptr;        //所有內存被釋放后 指針置空
 } } template<class T>
void MyTree<T>::clear() { _clear(pRoot); //不需要再進行判空 ,_clear()中會判斷
} template<class T> MyTree<T>::~MyTree() { clear(); } template<class T> MyTree<T>::MyTree() { pRoot = nullptr; }

代碼測試:

 

// 無序樹.cpp : 定義控制台應用程序的入口點。 // #include "stdafx.h" #include "MyTree.h" #include<iostream>
using namespace std; int _tmain(int argc, _TCHAR* argv[]) { MyTree<int> tree; std::cout << "tree:" << endl;; tree.insertNode(1, 1); cout << 1 << '\n' << '|' << endl;; tree.insertNode(1, 2, 1); tree.insertNode(2, 5, 0); tree.insertNode(2, 9, 0); cout << 2 << "" << 5<<"— —"<<9<<endl; cout << '|' << "  " << "|" <<"     "<<"|"<< endl; tree.insertNode(2, 3, 1); tree.insertNode(5, 6, 1); tree.insertNode(6, 7, 0); tree.insertNode(9, 10, 1); cout << 3 << "  " << 6 << "" << 7 <<" "<< 10 << endl; cout << "|" << "     " << "|" << endl; tree.insertNode(3, 4, 1); tree.insertNode(7, 8, 1); cout << 4 << "     " << 8 << "\n\n"<<endl; std::cout << "前序遍歷:"; tree.preOrderPrint(tree.getTreeRoot()); std::cout << std::endl; std::cout << "后序遍歷:"; tree.posOrderPrint(tree.getTreeRoot()); std::cout << std::endl; std::cout << "中序遍歷:"; tree.inOrderPrint(tree.getTreeRoot()); std::cout << std::endl; std::cin.get(); return 0; }

 

測試結果:

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM