【數據結構】------C語言實現二叉樹

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 作者主頁:作者主頁

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 數據結構專欄:數據結構

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?創作時間 :2024年5月20日

一、二叉樹的定義

二叉樹(Binary Tree) 是由n個結點構成的有限集(n≥0),n=0時為空樹,n>0時為非空樹。

對于非空樹:

  • 有且僅有一個根節點
  • 除根結點外其他可分為兩個不相交的子集Tl和Tr,分別稱為T TT的左子樹和右子樹,從定義也可以看出二叉樹與一般樹的區別主要是兩點,一是每個結點的度最多為2;二是結點的子樹有左右之分,不能隨意調換,調換后又是一棵新的二叉樹。

二、二叉樹的形態

五種基本形態:

三種特殊形態:

三、二叉樹的性質

  1. 任意二叉樹第 i ii 層最大結點數為2^(i-1)。(i>=1)
  2. 深度為 k ?的二叉樹最大結點總數為2^k-1個(滿二叉樹)

  3. 對于任意二叉樹:

?

四、二叉樹的存儲

存的目的是為了取,而取的關鍵在于如何通過父結點拿到它的左右子結點,不同存儲方式圍繞的核心也就是這。

順序存儲:

使用一組地址連續的存儲單元存儲,例如數組。為了在存儲結構中能得到父子結點之間的映射關系,二叉樹中的結點必須按層次遍歷的順序存放。具體是:

  • 對于完全二叉樹,只需要自根結點起從上往下、從左往右依次存儲。
  • 對于非完全二叉樹,首先將它變換為完全二叉樹,空缺位置用某個特殊字符代替(比如#),然后仍按完全二叉樹的存儲方式存儲。

假設將一棵二叉樹按此方式存儲到數組后,左子結點下標=2倍的父結點下標+1,右子節點下標=2倍的父結點下標+2(這里父子結點間的關系是基于根結點從0開始計算的)。若數組某個位置處值為#,代表此處對應的結點為空。

可以看出順序存儲非常適合存儲接近完全二叉樹類型的二叉樹,對于一般二叉樹有很大的空間浪費,所以對于一般二叉樹,一般用下面這種鏈式存儲。

鏈式存儲:

對每個結點,除數據域外再多增加左右兩個指針域,分別指向該結點的左孩子和右孩子結點,再用一個頭指針指向根結點。對應的存儲結構:

二叉樹代碼的實現:

首先我們要得到相應的自定義函數,然后再去一一實現他們

typedef int BTDataType;typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;}BTNode;//創建一顆樹
BTNode* creatBT();//創建一個新節點
BTNode* BuyNode(int x);//前序遍歷
void PrevOrder(BTNode* root);//計算節點個數
int TreeSize(BTNode* root);

由于我們接下來的前序、中序、后序遍歷都需要一個二叉樹,所以我們這里要先創建一顆二叉樹才可以。

創建一個簡易二叉樹:

//創建一個新節點
BTNode* BuyNode(int x)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));if (newnode == NULL){perror("malloc failed");exit(0);}newnode->data = x;newnode->left = newnode->right =NULL;return newnode;
}BTNode* creatBT()
{BTNode* node1 = BuyNode(1);BTNode* node2 = BuyNode(2);BTNode* node3 = BuyNode(3);BTNode* node4 = BuyNode(4);BTNode* node5 = BuyNode(5);BTNode* node6 = BuyNode(6);node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;return node1;
}

前序遍歷:

//前序遍歷
void PrevOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}printf("%d ", root->data);//輸出當前數值PrevOrder(root->left);//然后遞歸進行PrevOrder(root->right);
}

中序遍歷:

//中序遍歷
void InOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}InOrder(root->left);//先遞歸,等到最后一個之后再進行輸出printf("%d ", root->data);InOrder(root->right);
}

后序遍歷:

//后序遍歷
void BackOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}BackOrder(root->left);BackOrder(root->right);printf("%d ", root->data);
}

節點個數:

//節點個數
int treesize(BTNode* root)
{if (root == NULL)return 0;else return treesize(root->left) + treesize(root->right) + 1 ;
}

另一種方式:

int TreeSize(BTNode* root)
{static int size = 0;//用局部靜態變量,只初始化一次。if (root == NULL){return 0;}else{++size;}TreeSize(root->left);TreeSize(root->right);return size;
}

求葉子節點個數:

//求葉子節點個數
int TreeLeafSize(BTNode* root)
{if (root == NULL){return 0;}if (root->left == NULL && root->right == NULL){return 1;}return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}

樹的高度:

int TreeHeigh(BTNode* root)
{if (root == NULL){return 0;}int leftheight = TreeHeigh(root->left);int rightheight = TreeHeigh(root->right);return leftheight > rightheight ?leftheight + 1 : rightheight + 1;
}

總代碼:

Tree.h:

#pragma once
#include<iostream>
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>typedef int BTDataType;typedef struct BinaryTreeNode
{BTDataType data;struct BinaryTreeNode* left;struct BinaryTreeNode* right;}BTNode;//創建一顆樹
BTNode* creatBT();//創建一個新節點
BTNode* BuyNode(int x);//前序遍歷
void PrevOrder(BTNode* root);//計算節點個數
int TreeSize(BTNode* root);

test.c:

#include"Tree.h"//創建一個新節點
BTNode* BuyNode(int x)
{BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));if (newnode == NULL){perror("malloc failed");exit(0);}newnode->data = x;newnode->left = newnode->right =NULL;return newnode;
}BTNode* creatBT()
{BTNode* node1 = BuyNode(1);BTNode* node2 = BuyNode(2);BTNode* node3 = BuyNode(3);BTNode* node4 = BuyNode(4);BTNode* node5 = BuyNode(5);BTNode* node6 = BuyNode(6);node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;return node1;
}//前序遍歷
void PrevOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}printf("%d ", root->data);//輸出當前數值PrevOrder(root->left);//然后遞歸進行PrevOrder(root->right);
}//中序遍歷
void InOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}InOrder(root->left);//先遞歸,等到最后一個之后再進行輸出printf("%d ", root->data);InOrder(root->right);
}//后序遍歷
void BackOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}BackOrder(root->left);BackOrder(root->right);printf("%d ", root->data);
}//節點個數
int treesize(BTNode* root)
{if (root == NULL)return 0;else return treesize(root->left) + treesize(root->right) + 1 ;
}int TreeSize(BTNode* root)
{static int size = 0;//用局部靜態變量,只初始化一次。if (root == NULL){return 0;}else{++size;}TreeSize(root->left);TreeSize(root->right);return size;
}//求葉子節點個數
int TreeLeafSize(BTNode* root)
{if (root == NULL){return 0;}if (root->left == NULL && root->right == NULL){return 1;}return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}int TreeHeigh(BTNode* root)
{if (root == NULL){return 0;}int leftheight = TreeHeigh(root->left);int rightheight = TreeHeigh(root->right);return leftheight > rightheight ?leftheight + 1 : rightheight + 1;
}int main()
{BTNode* root = creatBT();InOrder(root);printf("\n");int ret = TreeSize(root);std::cout << "TreeSize:" << ret << std::endl;ret = treesize(root);std::cout << "TreeSize:" << ret << std::endl;ret = TreeLeafSize(root);std::cout << "TreeLeafSize:" << ret << std::endl;int heigh = TreeHeigh(root);std::cout << "TreeHeigh:" << heigh << std::endl;return 0;
}

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

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

相關文章

接口自動化核心模塊Requests詳解(一)

一、Requests簡介 Python的Requests庫是一個功能強大且簡潔的庫&#xff0c;提供了簡單易用的接口來處理HTTP請求。 二、Requests的使用步驟 2.1 安裝Requests庫 在終端命令行&#xff0c;使用pip命令進行安裝&#xff0c; pip install requests 2.2 Requests庫常用方法…

騰訊Java社招面試題真題,最新面試題

Java中synchronized和ReentrantLock有什么區別&#xff1f; 1、鎖的實現方式不同&#xff1a; synchronized是JVM層面的鎖&#xff0c;主要依賴于監視器對象&#xff08;monitor&#xff09;實現。ReentrantLock是JDK層面的鎖&#xff0c;通過Java代碼實現&#xff0c;提供了更…

語雀——云知識庫/筆記

對于日常進行學習/創作或是記錄學習、工作內容與心得的群體來說&#xff0c;能夠及時同步的云筆記應用有著廣泛的應用場景。近期&#xff0c;我也探索了許多款不同的軟件應用&#xff0c;今天來分享一款很有特點的應用——語雀。 語雀&#xff0c;為每一個人提供優秀的文檔和知…

1.6 什么是程序-編譯與調試

目錄 1 程序的作用 2 新建項目及編譯運行 2.1 新建項目 2.2 HelloWorld 程序說明 2.3 printf 打印輸出 2.4 注釋 3 程序的編譯過程及項目位置 4 斷點及調試窗口設置 5 學習C語言后的境界 1 程序的作用 如下圖所示&#xff0c;我們編寫了一個可以做加法的程序&#xf…

vue3 vite項目配置了proxy代理情況下查看真實的接口調用地址

vite配置了proxy代理情況下如何查看真實的接口調用地址? 使用vite進行代理 在vite.config.ts配置了代理 在瀏覽器查看請求頭和響應頭發現只有代理前的url&#xff0c;沒有顯示代理后的路徑 然后發現一個bypass函數&#xff0c;但是此函數只能修改res響應頭的數據&#xff0…

C語言基礎-鏈表和數組的區別

在C語言中&#xff0c;鏈表&#xff08;Linked List&#xff09;和數組&#xff08;Array&#xff09;是兩種常用的數據結構&#xff0c;它們在數據存儲和訪問上各有其獨特的作用和優勢。以下是對這兩種數據結構的作用以及它們之間的不同點的詳細說明&#xff1a; 數組&#x…

Dockerfile文件詳細介紹

前言 Dockerfile是一個文本文件&#xff0c;包含了用于構建Docker鏡像的所有命令和說明。它定義了容器的運行環境、依賴以及啟動方式&#xff0c;是創建Docker鏡像的核心部分。 由于制作鏡像的過程中&#xff0c;需要逐層處理和打包&#xff0c;比較復雜&#xff0c;所以Docke…

實戰復盤:內網環境滲透ms-SQL數據庫

滲透環境&#xff1a;如下圖所示&#xff0c;web服務器、ms-SQL服務器、PC客戶端在同一個網絡中&#xff0c;彼此之間&#xff0c;沒有路由器或防火墻的隔離&#xff0c;這是一種危險的網絡結構&#xff0c;入侵ms-SQL服務器&#xff0c;非常容易。&#xff08;實戰中&#xff…

整理了10個靠譜且熱門的賺錢軟件,適合普通人長期做的賺錢副業

作為一名普通的上班族&#xff0c;我們每天都在辛勤工作&#xff0c;但工資的增長速度卻如同蝸牛般緩慢。不過&#xff0c;別擔心&#xff0c;信息時代總是帶給我們無盡的驚喜&#xff01;今天&#xff0c;我將為大家推薦一些賺錢的寶藏軟件&#xff0c;讓你在閑暇之余輕松實現…

Java-Zookeeper

zookeeper是什么 一個分布式、開源的分布式應用程序協調服務&#xff0c;具有配置維護、域名服務、分布式同步、組服務等 zookeeper有哪些功能 功能簡介集群管理監控節點狀態、運行請求等主節點選舉主節點掛掉之后會執行新主選舉分布式鎖zookeeper提供兩種鎖&#xff1a;獨占…

IEDA常用快捷鍵(后續更新ing)

1. 快速生成語句 1.快速生成main()方法 psvm或者main回車 2.快速生成輸出語句 sout,回車 3.快速生成for循環 fori或者itar,回車 2.快捷鍵 含義操作查找文本CtrlF替換文本CtrlR單行注釋Ctrl/多行注釋CtrlShift/格式化CtrlAltL復制當前內容至下一行CtrlD補全代碼Alt/快速生成…

RAGs:自動化評估 RAG 示例代碼

文章目錄 原理忠實度&#xff08;Faithfulness&#xff09;答案相關性&#xff08;Answer Relevance&#xff09;上下文相關性&#xff08;Context Relevance&#xff09;上下文召回率&#xff08;Context Recall&#xff09;答案正確性&#xff08;Answer Correctness&#xf…

C# 機構仿真實例

1、實現連桿帶動滑塊運動 一個連桿旋轉帶動另一個連桿&#xff0c;另一個連桿拖動滑塊&#xff0c;點擊“開始”按鈕開始運動&#xff0c;再點擊按鈕&#xff0c;則停止運動。 2、實現程序 #region 機構仿真Image image null;Timer timer new Timer();int width 0;int heig…

一千題,No.0027(Phone Desktop)

描述 Little Rosie has a phone with a desktop (or launcher, as it is also called). The desktop can consist of several screens. Each screen is represented as a grid of size 53, i.e., five rows and three columns. There are x applications with an icon size o…

【網絡安全】社會工程學攻擊與防范

一、社會工程學概述 1、社會工程學的定義 通過利用人們的心理弱點、本能反應、好奇心、信任、貪婪等一些心理陷阱進行的諸如欺騙、傷害、信息盜取、利益謀取等對社會及人類帶來危害的行為或方法。 當網絡惡意攻擊者無法通過純粹的計算機技術達到目的時&#xff0c;高超的情商…

9.Redis之list類型

list相當于鏈表、數據表 1.list類型基本介紹 列表中的元素是有序的"有序"的含義,要根據上下文區分~~有的時候,談到有序,指的是"升序","降序”有的時候,談到的有序,指的是, 順序很關鍵~~如果把元素位置顛倒,順序調換.此時得到的新的 List 和之前的 Li…

js簡單綜合案例之簡易ATM取款機、渲染表格案例、封裝時間函數

這里寫目錄標題 簡易ATM取款機要求代碼實現 渲染表格案例要求代碼實現 封裝時間函數要求代碼實現 簡易ATM取款機 要求 1.彈出彈窗&#xff0c;讓用戶輸入數字選擇操作 2.初始值金額為100&#xff0c;計算每次操作后的剩余金額變化 3.一直彈出彈窗直到用戶輸入4&#xff0c;跳…

OpenCV SIFT特征描述子(GPU版本)

文章目錄 一、簡介二、測試過程三、實現效果參考資料一、簡介 這里主要測試一下SIFT圖像描述子的GPU版本。SIFT圖像描述子,全稱Scale-Invariant Feature Transform(尺度不變特征變換),是計算機視覺和圖像處理領域中一種非常重要的局部特征描述子。它主要用于圖像的特征點檢…

新聞稿海外媒體投稿,除了美聯社發稿(AP)和彭博社宣發(Bloomberg),還有哪些優質的國外媒體平臺可以選擇

發布高質量的新聞稿到海外媒體&#xff0c;除了美聯社發稿&#xff08;AP&#xff09;和彭博社發稿&#xff08;Bloomberg&#xff09;&#xff0c;還有許多其他優質的媒體平臺可以選擇。以下是一些受歡迎和高效的海外媒體發布平臺&#xff1a; 路透社 (Reuters) 路透社是全球最…

Webpack Bundle Analyzer:深入分析與優化你的包

Webpack Bundle Analyzer是一個用于可視化的工具&#xff0c;它可以幫助你分析Webpack打包后的輸出文件&#xff0c;查看哪些模塊占用了最多的空間&#xff0c;從而進行優化。 2500G計算機入門到高級架構師開發資料超級大禮包免費送&#xff01; 首先&#xff0c;你需要安裝W…