數據結構之樹,二叉樹,二叉搜索樹

一.樹

1.形狀

2.?相關概念

節點的度:一個節點含有的子樹的個數稱為該節點的度; 如上圖:A的為6

葉節點或終端節點:度為0的節點稱為葉節點; 如上圖:B、C、H、I...等節點為葉節點

非終端節點或分支節點:度不為0的節點; 如上圖:D、E、F、G...等節點為分支節點

雙親節點或父節點:若一個節點含有子節點,則這個節點稱為其子節點的父節點; 如上圖:A是B的父節點

孩子節點或子節點:一個節點含有的子樹的根節點稱為該節點的子節點; 如上圖:B是A的孩子節點

兄弟節點:具有相同父節點的節點互稱為兄弟節點; 如上圖:B、C是兄弟節點

樹的度:一棵樹中,最大的節點的度稱為樹的度; 如上圖:樹的度為6

節點的層次:從根開始定義起,根為第1層,根的子節點為第2層,以此類推;

樹的高度或深度:樹中節點的最大層次; 如上圖:樹的高度為4

堂兄弟節點:雙親在同一層的節點互為堂兄弟;如上圖:H、I互為兄弟節點

節點的祖先:從根到該節點所經分支上的所有節點;如上圖:A是所有節點的祖先

子孫:以某節點為根的子樹中任一節點都稱為該節點的子孫。如上圖:所有節點都是A的子孫

森林:由m(m>0)棵互不相交的樹的集合稱為森林;

3.樹的實現

#include <iostream>
using namespace std;//鏈表
template <typename T>
struct ListNode
{T data;ListNode* next;ListNode(T d):data(d),next(NULL){}
};//樹的節點
template<typename T>
struct TreeNode
{T data;ListNode<TreeNode<T>*>* childHead;TreeNode() {data = T();childHead = NULL;}void addChild(TreeNode<T>* node){ListNode<TreeNode<T>*>* childNode = new ListNode<TreeNode<T>*>(node);if (childHead == NULL){childHead = childNode;}else{childNode->next = childHead;childHead = childNode;}}
};//創建樹的類
template <typename T>
class Tree{
private:TreeNode<T>* nodes;TreeNode<T>* root;
public:Tree();Tree(int maxNodes);~Tree();TreeNode<T>* getTreeNode(int id);void setRoot(int rootId);void addChild(int parent,int child);void assignData(int NodeId , T data);void print(TreeNode<T>* node = NULL);
};template <typename T>
Tree<T>::Tree(){nodes = new TreeNode<T>[10000];root = NULL;
}template <typename T>
Tree<T>::Tree(int maxNodes){nodes = new TreeNode<T>[maxNodes];root = NULL;
}template <typename T>
Tree<T>::~Tree(){delete[] nodes;
}template <typename T>
TreeNode<T>* Tree<T>::getTreeNode(int id){return &nodes[id];
}template <typename T>
void Tree<T>::setRoot(int rootId){root = getTreeNode(rootId);
}template <typename T>
void Tree<T>::addChild(int parent,int child){TreeNode<T>* Parat = getTreeNode(parent);TreeNode<T>* Child = getTreeNode(child);Parat->addChild(Child);
}template <typename T>
void Tree<T>::assignData(int NodeId , T data){getTreeNode(NodeId)->data = data;
}template <typename T>
void Tree<T>::print(TreeNode<T>* node){if (node == NULL){node = root;}cout<<node->data;ListNode<TreeNode<char>*>* temp = node->childHead;while (temp){print(temp->data);temp = temp->next;}
}int main(){Tree<char> p[9];p->setRoot(0);p->assignData(0,'a');p->assignData(1,'b');p->assignData(2,'c');p->assignData(3,'d');p->assignData(4,'e');p->assignData(5,'f');p->assignData(6,'g');p->assignData(7,'h');p->assignData(8,'i');p->addChild(0,1);p->addChild(0,2);p->addChild(1,3);p->addChild(2,4);p->addChild(2,5);p->addChild(3,6);p->addChild(3,7);p->addChild(3,8);p->print();return 0;
}

二.二叉樹

1.形狀(最多只有兩個度,也就是最多有兩個節點)

2.基本概念

1. 若規定根節點的層數為1,則一棵非空二叉樹的第i層上最多有2^(i-1)個結點.

2. 若規定根節點的層數為1,則深度為h的二叉樹的最大結點數是2^h-1

3. 對任何一棵二叉樹, 如果度為0其葉結點個數為y, 度為2的分支結點個數為x,則y=x+1

4. 若規定根節點的層數為1,具有n個結點的滿二叉樹的深度,h=log2(n+1)

3.二叉樹的存儲方式

1.順序存儲

????????就是使用數組來存儲,一般使用數組只適合表示完全二叉樹,因為不是完全二叉樹會有空間的浪費。

2.鏈式存儲

????????用鏈表來表示一棵二叉樹,即用鏈來指示元素的邏輯關系。

3.二叉樹的遍歷

  • 前序遍歷

  • 中序?

  • ?后續

  • 層序遍歷?

  • ?前,中,后序遍歷的實現
    #include <iostream>
    using namespace std;//樹的節點
    template<typename T>
    struct TreeNode 
    {T val;TreeNode* left;	//左子樹TreeNode* right;//右子樹TreeNode():val(0),left(NULL),right(NULL){};	//構造函數TreeNode(T d):val(d),left(NULL),right(NULL){};//構造函數
    };//樹的類集合
    template<typename T>
    class Tree{//內置參數
    private:TreeNode<T>* nodes;	//樹的節點數組	TreeNode<T>* root;	//根節點size_t nodeSize;	//節點個數TreeNode <T>* Creat(T a[],int size,int nodeId,T nullNode);	//創建樹void visit(TreeNode<T>* node);	//訪問節點void preOrder(TreeNode<T>* node);	//先序遍歷void inOrder(TreeNode<T>* node);	//中序遍歷void postOrder(TreeNode<T>* node);	//后序遍歷//用于外部函數調用
    public:Tree();Tree(int maxNodes);	~Tree();	TreeNode<T>* getTreeNode (int Id);	//獲取節點void CreatTree(T a[],int size,T nullNode);	//創建樹void preOrder();	//先序遍歷void inOrder();		//中序遍歷void postOrder();	//后序遍歷
    };//默認構造函數
    template<typename T>
    Tree<T>::Tree(){nodeSize = 10000;root = NULL;nodes = new TreeNode<T>[nodeSize];
    }//帶參數的構造函數
    template<typename T>
    Tree<T>::Tree(int maxNodes){nodeSize = maxNodes;root = NULL;nodes = new TreeNode<T>[nodeSize];
    }//析構函數,釋放內存
    template<typename T>
    Tree<T>::~Tree(){delete[] nodes;
    }//獲取樹節點
    template<typename T>	
    TreeNode<T>* Tree<T>::getTreeNode (int Id){return &nodes[Id];
    }//打印節點值
    template<typename T>
    void Tree<T>::visit(TreeNode<T>* node){cout<<node->val;
    }//內部創建樹,遞歸實現
    template<typename T>
    TreeNode <T>* Tree<T>::Creat(T a[],int size,int nodeId,T nullNode){if (nodeId >= size || a[nodeId] == nullNode){return NULL;}TreeNode <T>* nowNode = getTreeNode (nodeId);nowNode->val = a[nodeId];nowNode->left = Creat(a,size,nodeId * 2,nullNode);nowNode->right = Creat(a,size,nodeId * 2 + 1,nullNode);return nowNode;
    }//外部函數創建樹
    template<typename T>
    void  Tree<T>::CreatTree(T a[],int size,T nullNode){root = Creat(a,size,1,nullNode);//根節點從1開始
    }//內部實現前序遍歷
    template<typename T>
    void Tree<T>::preOrder(TreeNode<T>* node){if (node){visit(node);preOrder(node->left);preOrder(node->right);}
    }//外部實現前序遍歷
    template<typename T>
    void Tree<T>::preOrder(){preOrder(root);
    }//內部實現中序遍歷
    template<typename T>
    void Tree<T>::inOrder(TreeNode <T>* node){if (node) {inOrder(node->left);visit(node);inOrder(node->right);}
    }//外部實現中序遍歷
    template<typename T>
    void Tree<T>::inOrder(){inOrder(root);
    }//內部實現后序遍歷
    template<typename T>
    void Tree<T>::postOrder(TreeNode <T>* node){if (node) {postOrder(node->left);postOrder(node->right);visit(node);}
    }//外部實現后序遍歷
    template<typename T>
    void Tree<T>::postOrder(){postOrder(root);
    }int main(){const char nullNpde = '-';char a[15] = {nullNpde, 'a', 'b', 'c', 'd',nullNpde, 'e', 'f', 'g', 'h',nullNpde, nullNpde, nullNpde, nullNpde, 'i'};Tree<char> T(15);T.CreatTree(a, 15, nullNpde);T.preOrder(); cout << endl;T.inOrder(); cout << endl;T.postOrder(); cout << endl;return 0;
    }

三.二叉搜索樹

?1.形狀

2.概念

3.二叉樹代碼實現

#include <iostream>
using namespace std;//樹的節點
template<typename T>
struct TreeNode
{T data;TreeNode* left;TreeNode* right;TreeNode():data(0),left(NULL),right(NULL){}TreeNode(T d):data(d),left(NULL),right(NULL){}
};template<typename T>
class BinarySearchTree{
private:TreeNode<T>* root;TreeNode<T>* insertNode(TreeNode<T>* node,T value);TreeNode<T>* removeNode(TreeNode<T>* node,T value);bool searchNode(TreeNode<T>* node,T value);void inOrder(TreeNode<T>* node);public:BinarySearchTree():root(NULL){};~BinarySearchTree();void insert(T value){root = insertNode(root,value);}void remove(T value){root = removeNode(root,value);}bool search(T value){return searchNode(root,value);}void inOrderTree(){inOrder(root);cout<<endl;}
};//析構函數,刪除所有節點
template<typename T>
BinarySearchTree<T>::~BinarySearchTree(){while (root){remove(root->data);}
}//插入節點
template<typename T>
TreeNode<T>* BinarySearchTree<T>::insertNode(TreeNode<T>* node,T value){if (node == NULL){return new TreeNode<T>(value);}if (value < node->data){node->left = insertNode(node->left,value);//遞歸調用,直到找到合適的位置}else if(value > node->data){node->right = insertNode(node->right,value);//遞歸調用,直到找到合適的位置}return node;
}//刪除節點
template<typename T>
TreeNode<T>* BinarySearchTree<T>::removeNode(TreeNode<T>* node,T value){if (node == NULL){return NULL;}if (value < node->data)//如果要刪除的值小于當前節點的值,則遞歸調用左子樹{node->left = removeNode(node->left,value);}else if(value > node->data)//如果要刪除的值大于當前節點的值,則遞歸調用右子樹{node->right = removeNode(node->right,value);}else//如果要刪除的值等于當前節點的值{if (node->left == NULL && node->right == NULL)//如果當前節點沒有子節點,則直接刪除{delete node;node = NULL;return NULL;}else if(node->left == NULL)//如果當前節點沒有左子節點,則用右子節點替換當前節點{TreeNode<T>* rightChild = node->right;delete node;node = rightChild;return node;}else if(node->right == NULL)//如果當前節點沒有右子節點,則用左子節點替換當前節點{TreeNode<T>* leftChild = node->left;delete node;node = leftChild;return node;}else//如果當前節點有兩個子節點,則用右子樹中的最小節點替換當前節點{TreeNode<T>* replacement = node->right;while (replacement->left != NULL) {replacement = replacement->left;}node->data = replacement->data;node->right = removeNode(node->right, replacement->data);}}return node;
}//查找節點
template<typename T>
bool BinarySearchTree<T>::searchNode(TreeNode<T>* node,T value){if (node == NULL){return false;}if (value < node->data){return searchNode(node->left,value);}else if(value > node->data){return searchNode(node->right,value);}return true;
}//中序遍歷
template<typename T>
void BinarySearchTree<T>::inOrder(TreeNode<T>* node){if (node){inOrder(node->left);cout<<node->data<<",";inOrder(node->right);}	
}int main(){BinarySearchTree<int> bst;bst.insert(10);bst.insert(30);bst.insert(20);bst.insert(40);bst.insert(60);bst.insert(50);cout<<"中序遍歷"<<endl;bst.inOrderTree();cout<<"查找20:"<<bst.search(20)<<endl;cout<<"查找100:"<<bst.search(100)<<endl;bst.remove(30);bst.inOrderTree();return 0;
}

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/87911.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/87911.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/87911.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LLM微調隨記錄

【如何把領域文獻批量轉換為可供模型微調的數據集&#xff1f;】 https://www.bilibili.com/video/BV1y8QpYGE57/?share_sourcecopy_web&vd_source8f9078186b93d9eee26026fd26e8a6ed 幾個問題 首先要先搞清楚這幾個問題 LLM 訓練方法如何選擇合適的訓練方式如何判斷是否…

高效處理大體積Excel文件的Java技術方案解析

高效處理大體積Excel文件的Java技術方案解析 引言 在數據密集型應用中&#xff0c;處理數百MB甚至GB級的Excel文件已成為業務剛需。傳統基于DOM模型的Excel解析方式&#xff08;如Apache POI的XSSF&#xff09;在處理大規模數據時存在嚴重的內存瓶頸。本文將深入探討Java生態中…

JVM垃圾回收機制深度解析

&#x1f5d1;? JVM垃圾回收機制深度解析 文章目錄&#x1f5d1;? JVM垃圾回收機制深度解析&#x1f50d; 垃圾判定算法&#x1f522; 引用計數法&#x1f310; 可達性分析算法&#x1f504; 垃圾回收算法&#x1f3f7;? 標記-清除算法&#x1f4cb; 復制算法&#x1f527; …

Docker:容器化技術的基石與實踐指南

在現代軟件開發和部署中&#xff0c;Docker 作為一種領先的容器化平臺&#xff0c;已經成為了開發人員和運維工程師不可或缺的工具。它不僅簡化了應用的部署過程&#xff0c;還提高了應用的可移植性和可擴展性。本文將深入探討 Docker 的核心概念、基本操作以及如何在實際項目中…

java web7(黑馬)

Filter簡介概念: Filter 表示過濾器&#xff0c;是 JavaWeb 三大組件(Servlet、Filter、Listener)之一。過濾器可以把對資源的請求攔截下來&#xff0c;從而實現一些特殊的功能。過濾器一般完成一些通用的操作&#xff0c;比如:權限控制、統一編碼處理、敏感字符處理等等.快速入…

React-forwardRef-useImperativeHandle

forwardRef 暴露dom節點作用&#xff1a;使用ref暴露DOM節點給父組件案例例如在父組件中想要獲取子組件input的輸入值&#xff0c;和讓input獲取焦點父組件import { Button } from antd-mobile import Son from "./components/son"; import { useState,useRef } fro…

Unity 用AI自動開發游戲----Cursor研究(實現一套利用Cursor生成模板快速實現原型的框架)

Unity 快速原型開發框架&#xff08;基于 Cursor AI&#xff09; &#x1f9e9; 框架簡介 本框架結合了 AI 編程助手 Cursor 的代碼生成能力&#xff0c;構建出一套適用于 Unity 項目的模塊化原型開發架構。它旨在極大提升開發效率、降低試錯成本&#xff0c;特別適用于快速搭…

D觸發器實現2分頻verilog及電路

使用D觸發器完成2分頻電路即通過時鐘的上升沿或下降沿到來時進行翻轉得到&#xff0c;信號的兩個狀態所占時間長度相同&#xff0c;因此它的輸出時鐘的占空比為50%。 D觸發器實現2分頻的電路圖如下所示&#xff1a;通過將D觸發器2分頻電路級聯&#xff0c;可實現輸入時鐘的2N倍…

UniApp完美對接RuoYi框架開發企業級應用

UniApp完美對接RuoYi框架的完整方案及可開發系統類型&#xff0c;結合企業級實踐與開源項目經驗整理而成&#xff0c;涵蓋技術對接、系統設計及實戰案例。 &#x1f527; 一、UniApp與RuoYi對接全流程 1. 后端配置&#xff08;RuoYi-Vue/RuoYi-Cloud&#xff09; 跨域支持 在網…

【通識】深度學習理論基礎

1. 深度學習導論 導論和簡介的基礎知識和路徑。 深度學習的各項涵蓋范圍&#xff1a;深度學習MLPs&#xff0c;然后是機器學習、邏輯回歸&#xff0c;知識基礎等等 1&#xff09;連結神經網絡等等&#xff1a;Cybernetics控制論&#xff0c;Connectionism連結主義&#xff0…

sql-labs(11-12)-萬能密碼登錄

sql-labs(11-12)萬能密碼登錄 第十一關&#xff1a; 這關是一個登陸口&#xff0c;也是一個sql注入的漏洞&#xff0c;也就是常說的萬能密碼。 在輸入框賬號密碼種分別輸入 1’ 和1’ 頁面會報錯。后臺使用的單引符號進行的拼接。賬號輸入1’ or ‘1’‘1 密碼輸入 1’ or …

MsSql 其他(2)

???????????????Mysql中的MVCC 一、MVCC 的核心目標與設計背景 MVCC&#xff08;Multi-Version Concurrency Control&#xff0c;多版本并發控制&#xff09; 是 InnoDB 存儲引擎為實現高并發事務處理而設計的核心機制。其核心目標是&#xff1a;在不犧牲事務隔…

解決本地部署n8n,域名訪問為什么一直有connection lost的報錯

問題&#xff1a;本地部署的n8n服務用IP訪問一切都正常&#xff0c;但是使用域名后報錯connection lost思路&#xff1a;首先懷疑是ngnix配置問題或者是docker中的環境問題查看docker logsOrigin header does NOT match the expected origin. (Origin: "nxxx.online:1181&…

傳統架構開發VS PREEvision:一場效率與可靠性的降維打擊

當前&#xff0c;整車功能數量激增&#xff0c;意味著需要更龐大的整車數據庫、更復雜的硬件傳感器與執行器網絡、更密集的跨系統交互接口以及更難以預測的耦合效應。這樣一來&#xff0c;單一功能的微小改動&#xff0c;可能會因復雜的依賴關系而引發意想不到的連鎖反應&#…

深度學習基礎1

一、張量 張量其實就是數組&#xff0c;不過是在深度學習中是這樣的叫法 1.張量的創建 &#xff08;1&#xff09;基本創建方式 torch.tensor()&#xff1a;根據指定數據創建張量 import torch import numpy as np """創建張量標量""" data to…

力扣網編程274題:H指數之普通解法(中等)

一. 簡介 本文記錄力扣網上涉及數組&#xff0c;排序方面的編程題&#xff1a;H指數。 二. 力扣網編程274題&#xff1a;H指數&#xff08;中等&#xff09; 給你一個整數數組 citations &#xff0c;其中 citations[i] 表示研究者的第 i 篇論文被引用的次數。計算并返回該研…

iptables防火墻,多IP環境下, 指定某個目的IP地址通過某個本地IP訪問,策略路由!

需求在CentOS 7.9中&#xff0c;若需從特定源IP&#xff08;10.0.0.3&#xff09;訪問目標網段 1.1.1.0/24方法一&#xff1a;策略路由&#xff08;支持網段&#xff09;1. 創建自定義路由表# 添加名為custom_table的路由表&#xff08;ID200&#xff09; echo "200 custo…

數字孿生技術引領UI前端設計新趨勢:數據可視化與交互設計的深度融合

hello寶子們...我們是艾斯視覺擅長ui設計、前端開發、數字孿生、大數據、三維建模、三維動畫10年經驗!希望我的分享能幫助到您!如需幫助可以評論關注私信我們一起探討!致敬感謝感恩!一、引言&#xff1a;數字孿生驅動 UI 設計的范式革新在大數據與三維可視化技術爆發的今天&…

【機器學習筆記 Ⅱ】6 激活函數

激活函數是神經網絡的核心組件&#xff0c;其作用遠不止“引入非線性”。以下是系統化的解析&#xff1a;1. 核心作用 (1) 引入非線性沒有激活函數&#xff1a;多層神經網絡等價于單層線性變換&#xff08;矩陣連乘仍是線性&#xff09;。加入激活函數&#xff1a;每層通過非線…

AI無標記動捕如何結合VR大空間技術打造沉浸式游戲體驗

隨著數字科技的迅猛發展&#xff0c;VR大空間技術正逐步成為各行業探索沉浸式體驗的重要方向。在VR游戲領域&#xff0c;市場對于高度沉浸式體驗的需求日益增長&#xff0c;而傳統VR游戲主要依賴手柄和基礎體感進行交互&#xff0c;而在VR大空間中&#xff0c;用戶可以通過全身…