樹的相關筆試面試題

1. 樹的創建

已知一個先序遍歷數的結果用數組表示, 其中空節點用 null_node 表示, 要求創建出這棵樹. 同樣采用遞歸的思想, 先定義一個指針, 指向數組中的第一個元素, 然后給數組的第一個結點創建相應的結點, 然后指針后移, 遞歸創建根節點的左子樹, 遞歸創建根節點的右子樹, 最后返回這個新結點就可以了

TreeNode* TreeCreate(TreeNodeType array[], int size, TreeNodeType null_node)
{if(array == NULL){return NULL;//非法輸入}if(size == 0){return NULL;//非法輸入}if(array[0] == null_node){return NULL;//空樹}int index = 0;return _TreeCreate(array, size, &index, null_node);
}TreeNode* TreeClone(TreeNode* root)
{if(root == NULL){return NULL;//空樹}TreeNode* new_root;TreeInit(&new_root);new_root = CreateTreeNode(root -> data);if(new_root == NULL){return NULL;}//遞歸創建左子樹new_root -> lchild = TreeClone(new_root -> lchild);//遞歸創建右子樹new_root -> rchild = TreeClone(new_root -> rchild);return new_root;
}

2. 克隆一棵樹

克隆一棵樹也采用遞歸的思想, 先創建一個根節點, 然后遞歸創建根節點的左子樹, 再遞歸創建根節點的右子樹

TreeNode* TreeClone(TreeNode* root)
{if(root == NULL){return NULL;//空樹}TreeNode* new_root;TreeInit(&new_root);new_root = CreateTreeNode(root -> data);if(new_root == NULL){return NULL;}//遞歸創建左子樹new_root -> lchild = TreeClone(new_root -> lchild);//遞歸創建右子樹new_root -> rchild = TreeClone(new_root -> rchild);return new_root;
}

3. 求二叉樹的葉子結點數

求二叉樹的所有結點數即就是求二叉樹的左子樹上的結點數加上二叉樹的右子樹上的結點數, 然后左右字數的結點數相加即就是二叉樹的所有葉子結點數

int TreeLeafSize(TreeNode* root)
{if(root == NULL){return 0;}if(root -> lchild == NULL && root -> rchild == NULL){return 1;}return TreeLeafSize(root -> lchild) + TreeLeafSize(root -> rchild);
}

4. 求二叉樹的節點數

求二叉樹的節點數即就是先判斷二叉樹是不是只有一個結點, 如果不是, 就遞歸求解出二叉樹的左子樹的結點數, 再遞歸求解二叉樹的有子樹的結點數, 最后根節點的左右子樹之和加1就是二叉樹的結點總數

int TreeSize(TreeNode* root)
{if(root == NULL){return 0;}return TreeSize(root -> lchild) + TreeSize(root -> rchild) + 1;
}

5. 求二叉樹的高度

如果只有一個根節點, 則二叉樹的高度為 1, 否則二叉樹的高度就是根節點的左子樹和右子樹的高度的最大值 加 1

int TreeHeight(TreeNode* root)
{if(root == NULL){return 0;}if(root -> lchild == NULL && root -> rchild == NULL){return 1;}int Lhight = TreeHeight(root -> lchild);int Rhight = TreeHeight(root -> rchild);return 1 + (Lhight > Rhight ? Lhight : Rhight);
}

6. 求某個節點的父節點

如果已知結點和根節點相等, 則直接返回根節點, 否則就遞歸的在根節點的左子樹中找, 如果沒有找的就在根節點的右子樹中遞歸的找

TreeNode* Parent(TreeNode* root, TreeNode* node)
{if(root == NULL || node == NULL){return NULL;}if(root -> lchild == node || root -> rchild == node){return root;}TreeNode* Lparent = Parent(root -> lchild, node);if(Lparent != NULL){return Lparent;}TreeNode* Rparent = Parent(root -> rchild, node);return Rparent;
}

7. 銷毀一個二叉樹

先遞歸銷毀二叉樹的左子樹, 再遞歸銷毀二叉樹的右子樹, 最后銷毀根節點

void TreeDestroy(TreeNode** root)
{if(root == NULL){return;}if(*root == NULL){return;//空樹}TreeDestroy(&(*root) -> lchild);TreeDestroy(&(*root) -> rchild);free(*root);*root = NULL;
}

8. 在二叉樹中找出給定指的結點

比較根節點的 data 和 to_find 是否相等, 相等就返回根節點, 不相等遞歸的和根節點的左子樹的 data 比較, 最后和根節點的右子樹的data比較

TreeNode* TreeFind(TreeNode* root, TreeNodeType to_find)
{if(root == NULL){return NULL;//空樹}if(root -> data == to_find){return root;}TreeNode* l_node = TreeFind(root -> lchild, to_find);if(l_node != NULL){return l_node;}TreeNode* r_node = TreeFind(root -> rchild, to_find);return r_node;
}

9. 非遞歸先序遍歷

先定義一個棧, 將根節點入棧, 取棧頂元素到 cur 中, 同時訪問當前結點, 將當前結點出棧, 如果當前結點的右子樹不為空, 就將當前結點的右子樹入棧, 如果當前結點的左子樹不為空, 入棧當前結點的左子樹, 循環取棧頂元素, 直到棧為空.

void TreePreOrderByLoop(TreeNode* root)
{if(root ==NULL){return;}SeqStack stack;SeqStackInit(&stack);SeqStackPush(&stack, root);SeqStackType cur;while(SeqStackGetFront(&stack, &cur)){printf("%c ", cur -> data);SeqStackPop(&stack);if(cur -> rchild != NULL){SeqStackPush(&stack, cur -> rchild);}if(cur -> lchild != NULL){SeqStackPush(&stack, cur -> lchild);}}
}

10. 非遞歸中序遍歷

先定義一個指針指向該節點, 如果當前結點不為空, 入棧當前結點, 同時讓當前結點一直往左走, 直到當前結點為空. 取棧頂結點, 訪問當前結點, 出棧. 讓當前結點指向它的右子樹

void TreeInOrderByLoop(TreeNode* root)
{if(root == NULL){return;}SeqStack stack;SeqStackInit(&stack);TreeNode* cur = root;while(1){while(cur != NULL){SeqStackPush(&stack, cur);cur = cur -> lchild;}int ret = SeqStackGetFront(&stack, &cur);if(ret == 0){return;}printf("%c ", cur -> data);SeqStackPop(&stack);cur = cur -> rchild;}
}

11. 非遞歸后序遍歷

定義一個指針prev初始化為 NULL來表示訪問的上一個結點, 同時定義一個指針 cur 指向該節點, 再定義一個指針 top 表示棧頂結點. 將 cur 入棧, 讓當前結點向左走, 直到當前結點為空, 此時取棧頂元素, 如果當前結點 cur -> rchild 和 訪問的上一個結點相等, 則訪問當前結點, 同時將prev的值賦為訪問結點的值, 然后讓 cur 等于 cur -> rchild, 一直循環, 直到取棧頂元素失敗

void TreePostByLoop(TreeNode* root)
{if(root == NULL){return;//空樹}TreeNode* prev = NULL;TreeNode* cur = root;SeqStackType top;SeqStack stack;SeqStackInit(&stack);while(1){while(cur != NULL){SeqStackPush(&stack, cur);cur = cur -> lchild;}int ret = SeqStackGetFront(&stack, &top);if(ret == 0){return;}if(top -> rchild == NULL || top -> rchild == prev){printf("%c ", top -> data);prev = top;SeqStackPop(&stack);}else{cur = top -> rchild;}}
}

12. 樹的鏡像

(1)非遞歸版本

定義一個指針 cur 指向根節點, 定義一個隊列, 將 cur 入隊列, 取隊首元素, 將當前隊首元素左右字數進行交換, 出隊列, 如果cur -> lchild != NULL, 就將 cur -> lchild 入隊列, 如果 cur -> rchild != NULL, cur -> rchild 入隊列, 循環上述過程, 直到取棧頂元素失敗退出循環就說明當前樹已經逆置

void TreeMirrorByLoop(TreeNode* root)
{if(root == NULL){return;}SeqQue q;SeqQueInit(&q);SeqQueType top = root;SeqQuePush(&q, root);int ret = 0;while(SeqQueGetFront(&q, &top)){TreeNodeSwap(&(top -> lchild), &(top -> rchild));SeqQuePop(&q);if(top -> lchild != NULL){SeqQuePush(&q, top -> lchild);}if(top -> rchild != NULL){SeqQuePush(&q, top -> rchild);}}printf("\n");
}

(2)非遞歸版本求樹的鏡像

如果當前樹是空樹則直接返回, 如果當前樹只有一個根節點, 就直接返回, 否則就逆置當前結點的左子樹, 逆置當前結點的右子樹

void TreeMirror(TreeNode* root)
{if(root == NULL){return;//空樹}if(root -> rchild == NULL && root -> rchild == NULL){return;}TreeMirror(root -> rchild);TreeMirror(root -> lchild);
}

13. 判斷二叉樹是否為完全二叉樹

分為兩個階段, 第一階段判斷當前結點是否具有左右子樹, 如果具有左右字數, 就將當前結點左右子樹入隊列, 如果當前結點只有右子樹, 沒有左子樹, 一定不是右子樹, 如果當前結點只有左子樹沒有右子樹, 進入階段2, 如果當前結點左右子樹都沒有, 進入第二階段, 第二階段就是當前結點的后面結點都沒有子樹, 一直循環, 如果循環結束, 并且滿足上述條件, 則說明這個樹是完全二叉樹, 否則不是

int IsComPletTree(TreeNode* root)
{if(root == NULL){return;}TreeNode* cur = root;int start_step_two = 0;SeqQue q;SeqQueInit(&q);SeqQuePush(&q, cur);while(SeqQueGetFront(&q, &cur)){if(start_step_two == 0){if(cur -> rchild != NULL && cur -> lchild != NULL){SeqQuePush(&q, cur -> rchild);SeqQuePush(&q, cur -> lchild);}if(cur -> lchild == NULL && cur -> rchild != NULL){return 0;}if(cur -> lchild != NULL && cur -> rchild == NULL){start_step_two = 1;}if(cur -> lchild == NULL && cur -> rchild == NULL){start_step_two = 1;}}else{if(cur -> lchild == NULL && cur -> rchild == NULL){;}else{return 0;}}}return 1;
}

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

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

相關文章

UVa202

[題目描述] 傳送門 [題目分析] 就是一個模擬,不過稍微有點小復雜,而且輸出格式有點小毒瘤. 不過只是RE了兩發,PE了一發就過了,還是很開心. 需要注意數組要開很大,可能循環節出現在很后. 每個輸出樣例應該輸出一個空行,最后面也應該有,不然會PE [AC代碼] #include<cst…

linux線程同步(5)-屏障

http://www.cnblogs.com/yuuyuu/p/5152560.html 一.概述 barrier(屏障)與互斥量&#xff0c;讀寫鎖&#xff0c;自旋鎖不同&#xff0c;它不是用來保護臨界區的。相反&#xff0c;它跟條件變量一樣&#xff0c;是用來協同多…

淺談軟件測試

一. 什么是軟件測試 軟件測試是一個過程或者一系列過程, 用來測試計算機代碼完成了其應該完成的功能, 不執行不該有的操作.或者說軟件測試是根據軟件開發各階段的功能和說明而精心設計的一批測試用例, 并根據測試用例運行程序, 以發現程序錯誤的過程. 二. 軟件測試的心理學和…

UVa10340

【題目描述】 傳送門 【題目分析】 求字串&#xff0c;最好還是處理母串&#xff0c;每次找到一個子串就加1&#xff0c;這樣處理不用處理細節 【AC代碼】 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include&l…

淺析linux下的條件變量

一.條件變量 條件變量是用來等待線程而不是上鎖的&#xff0c;條件變量通常和互斥鎖一起使用。條件變量之所以要和互斥鎖一起使用&#xff0c;主要是因為互斥鎖的一個明顯的特點就是它只有兩種狀態&#xff1a;鎖定和非鎖定&#xff0c;而條件變量可以通過允許線程阻塞和等待另…

UVa1587

【題目描述】 傳送門 【題目分析】 剛開始想簡單了&#xff0c;認為只要相對的面相等就可以了。然后發現三個不同方向的面的邊應該有相等的關系&#xff0c;即如果兩個面公用一條邊&#xff0c;那么這兩個面的另外兩條邊就是另一個面的兩條邊。而且這三個量里面肯定有一個最…

Linux多線程與同步

https://www.cnblogs.com/freedomabcd/p/7774743.html 典型的UNIX系統都支持一個進程創建多個線程(thread)。在Linux進程基礎中提到&#xff0c;Linux以進程為單位組織操作&#xff0c;Linux中的線程也都基于進程。盡管實現方式有異于其它的UNIX系統&#xff0c;但Linux的多線程…

內存管理(二)

頁面置換算法 當發生缺頁中斷的時候, 系統會在內存中選擇一個頁面將其換出內存, 而當換出內存的時候如果該頁面的內容在內存中發生修改,則必須將該新數據重新寫回到磁盤, 然后再將需要換進的數據覆蓋掉原來的數據, 而當該數據在內存中沒有被修改的時候, 此時就直接用需要換進的…

兩個棧實現一個隊列/兩個隊列實現一個棧

http://blog.csdn.net/sinat_30472685/article/details/70157227 1兩個棧實現一個隊列 1.原理分析&#xff1a; 隊列的主要操作有兩個&#xff1a;入隊操作和出隊操作&#xff0c;出隊時從隊頭出&#xff0c;入隊是從隊尾插入&#xff0c;入隊的操作和入棧的操作類似&#xff0…

UVa1588

【題目描述】 傳送門 【題目分析】 剛開始想了一會沒有想到什么很好的算法&#xff0c;看到了長度最多為100&#xff0c;就知道自己想的沒有什么意義了&#xff0c;直接暴力&#xff0c;把每一種填法都試一下就知道了。適當剪枝一下&#xff08;一個簡單的樂觀函數&#xff…

轉:C++中const、volatile、mutable的用法

const修飾普通變量和指針 const修飾變量&#xff0c;一般有兩種寫法&#xff1a; const TYPE value; TYPE const value; 這兩種寫法在本質上是一樣的。它的含義是&#xff1a;const修飾的類型為TYPE的變量value是不可變的。對于一個非指針的類型TYPE&#xff0c;無論怎么寫&…

數據鏈路

廣播信道的數據鏈路層 局域網的優點 網絡為一個單位所擁有, 地理范圍和站點數有限 局域網具有廣播特性, 可以從一個站點方便地訪問到整個網絡. 各個主機之間可以共享資源, 無論是局域網上的硬件資源還是局域網上的軟件資源 便于系統的擴展換和演化, 各個設備之間的位置可靈…

UVa11809

【題目描述】 傳送門 【題目分析】 終于把這道題做完了&#xff0c;之前一直連題意都看不懂。實在不行上網找了一下大佬的博客&#xff0c;看懂題意后自己寫&#xff0c;發現讀入很難處理&#xff0c;就又學習了一下大佬的讀入方法&#xff0c;用的是C里面的sstream&#xf…

數據鏈路層:基本概念

數據鏈路層的定義 對數據鏈路層有對上的網絡層接口. 對下提供物理層的接口. 定義合適的傳輸差錯率 對傳輸流進行管理, 以免快速的傳輸的數據被淹沒. 比如發送端發送信號太快, 接受方接受速度較慢, 此時數據鏈路層就需要提供一定的功能解決這個問題 物理層上傳輸的基本單元是…

C++的沉迷與愛戀

每年的 09/28 於我都是一個特殊的日子 -- 不只是因為教師節。今年很特殊地沒有普天同慶&#xff0c;那麼我就寫篇文章自己慶祝一下好了。我於今年七月發表了一本著作《多型與虛擬》和一本譯作《深度探索C物件模型》&#xff0c;獲得很大的回響。這些作品都不是針對 C 的完全初學…

Insertion Sort——打表找規律

【題目描述】 Insertion sort is a simple sorting algorithm that builds the final sorted array one item at an iteration.More precisely, insertion sort iterates, consuming one input element each repetition, and growing a sorted output list. At each iteration…

數據鏈路層: 可靠性傳輸 六個協議

可靠性傳輸 1. 差錯控制 發送方將數據幀發送, 但是當發送方發送的是一個 1的時候此時接受方卻接受的是一個 0. (1)校驗 接收方如果幀校驗接受到的幀沒有問題, 則對發送方發送一個肯定性的確認, 當對這個數據幀進行校驗發現這個幀有問題的時候, 此時接受方一種是將這個數據幀…

c語言實現配置文件的讀寫

配置文件的格式如下&#xff1a; key1 value1 key2 value2 . . . 名值對以一個鏈接&#xff0c;一條記錄以換行符分割 頭文件&#xff1a; #include<stdio.h> #include<stdlib.h> #include <string.h> 函數原型&#xff1a; void trim(char *strIn, char *…

Educational Codeforces Round 73 (Rated for Div. 2)

A 很簡單的一個模擬&#xff0c;只要前面的數字有兩個以上就能合成后面的&#xff0c;我們進行一遍合成看能不能出現2048就可以了。 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include&…

數據鏈路層: HDLC

一. 協議機 發送方和接收方. 同時有限狀態機把協議形式化為一個四元組 (S,M,I,T), 其中你S表示進程和信道可能進入的集合, M 表示數據幀的狀態, I 表示進程的初始狀態, T 表示兩兩狀態之間的轉化. 每個系統狀態可以分為發送狀態, 接受狀態和信道狀態. 把狀態用一個點進行表示,…