相比前面的內容,樹的學習難度加大了。樹包括孩子結點、兄弟結點、雙親結點,樹的遍歷順序有先序遍歷、中序遍歷、後序遍歷、層次遍歷。能夠根據先序遍歷和中序遍歷或中序遍歷和後序遍從來還原樹,轉換成代碼就須要找一下其中的規律。 樹中哈夫曼樹的帶權路徑長度達到最小,也叫最優二叉樹。哈夫曼樹的創建要把權值較小的結點放較下層,權值較大的結點要越靠近根結點。 樹的應用與遞歸密切相關,因此咱們要捋清遞歸的規則,知道它的執行原理,才能應用遞歸來解決問題。一級級調用,再一級級返回。
void InitExpTree(BTree &T,string str) //建表達式的二叉樹 定義棧s存放數字 定義棧op存放運算符 先將‘#’進op棧 while(str[i]) { if str[i]是數字 T=new BiTNode; T->data=str[i++]; T的左右孩子置爲NULL T進棧s else 調用Precede函數比較op棧頂元素與str[i]大小 若是函數值爲'<' str[i]進op棧 若是函數值爲'=' op棧出棧 若是函數值爲'>' str[i]進op棧 T=new BiTNode; op棧頂元素賦值給T->data T->rchild=s.top(); s棧出棧 T->lchild=s.top(); s棧出棧 s.push(T); op棧出棧 } while(op棧頂元素不是'#') //把樹結點的關係連起來 { T=new BiTNode; op棧頂元素賦值給T->data op棧出棧 T->rchild=s.top(); s棧出棧 T->lchild=s.top(); s棧出棧 s.push(T); }
double EvaluateExTree(BTree T)計算表達式樹 定義a,b if 樹T不空 if 左右孩子都爲空 return T->data-'0'; a=EvaluateExTree(T->lchild) b=EvaluateExTree(T->rchild) 判斷T->data 若是是'+' return a+b 若是是'-' rerurn a-b 若是是'*' return a*b 若是是'/' if b==0 輸出divide 0 error! 退出程序 不然 return a/b
Q1:把表達式建成樹比較有難度 A1:葉子結點都是表達式中的數字,首先遇到數字就賦值給樹結點,而後把結點進s棧。遇到運算符就比較複雜了,先要判斷運算符和op棧頂元素的大小。若該運算符大於op棧頂元素,就要先把op棧頂元素和s棧裏元素關係先建起了。小於則把運算符進op棧。等於則棧頂元素出棧。最後再把棧s、op的關係建起來,op裏面的元素爲根結點,s棧裏面的元素爲根的左右孩子。再把新建成的分支進s棧,重複操做,直到op棧頂元素不是'#'。
定義樹的結構體 主函數作建樹函數的調用和計算帶權路徑長度和 BinTree CreateBtree(string str,int i) 定義BinTree樹BT if i>str.size()-1 return NULL; if str[i]=='#' return NULL; 生成新結點BT BT->Data=str[i]; BT->Left=CreateBtree(str,2*i); BT->Right=CreateBtree(str,2*i+1); return BT;
void GetWpl(BinTree BT,int &wpl,int h) if BT==NULL return ; else if BT的左右孩子都爲空 wpl+=h*(BT->Data-48); //字符轉數字(減去'0'=48) h開始從新記錄置爲0 h++; GetWpl(BT->Left,wpl,h); GetWpl(BT->Right,wpl,h);
Q1:剛開始在編譯器上運行的結果不是題目中的72 A1:計算wpl時,直接這麼寫wpl+=h*BT->Data,忘記BT->Data是字符,不是數字,因此計算出來的固然不是72。應該改爲wpl+=h*(BT->Data-48),要再減去字符'0'便可,還有就是計算wpl後,h要置爲0,用於其餘葉子結點計算wpl。
先按題目遞歸法建樹 void LevelOrder(BinTree BT) //層次遍歷 定義BinTree型隊列qt; 定義int型level,flag; 定義BinTree型curNode,lastNode; curNode=lastNode=BT; if BT==NULL 輸出NULL return ; else BT進隊 while(!qt.empty()) { if curNode==lastNode { level++; 用flag來控制輸出level:前是否要換行 lastNode=qt.back(); } curNode=qt.front(); 輸出curNode->Data if curNode->Left非空 curNode->Left進隊 if curNode->Right非空 curNode->Right進隊 出隊 }
Q1:怎麼知道每層結點有哪幾個 A1:將根結點進棧,先將curNode,lastNode都置爲BT。只有當curNode,lastNode相等時,即curNode到達每層最後一個元素,再輸出層次。用curNode記錄隊頭,把隊頭的左右孩子進隊,用lastNode記錄隊尾。重複操做,直到隊列爲空。
二叉樹剪枝
給定二叉樹根結點 root ,此外樹的每一個結點的值要麼是 0,要麼是 1。返回移除了全部不包含 1 的子樹的原二叉樹。
ide
該題採用後序遍歷的方法,若樹爲空,則返回null。接着遞歸左子樹和右子樹。如有結點左、右孩子都爲空,且該結點的值爲0,則返回努力了,不然返回root
這題雖然作法是遞歸,但先序遍歷和後序遍歷有差異,採用先序遍歷則行不通。由於前序只能刪除葉子結點爲0的,但非葉子爲0而且左右結點爲0的狀況卻不行。而採用後序遍歷,效果就不一樣了,後序遍歷從葉子結點開始判斷刪除,如有上述狀況,則那個結點也能成爲葉子結點,從而被刪掉。 因此咱們要全面看待問題,不一樣順序遍歷效果多是不一樣的,這種遍歷順序行不通,其餘種遍歷順序也許就別有洞天,這道題就是一個很好的案例。