數據的基本單位是數據元素,在涉及到數據處理時數據元素之間的關係稱之爲結構,咱們依據數據元素之間關係的不一樣,將數據結構分爲線性結構和非線性結構 兩種。html
這上面所劃分的是數據結構的邏輯結構,而數據是如何在計算機中存儲的,這涉及到數據的物理結構,邏輯結構是從解決問題出發,涉及到功能的簡歷,物理結構設計到響應速度,處理、修改、存儲時間等問題。node
二叉樹遍歷是最基本的操做,分爲先序遍歷,中序遍歷、後序遍歷,以及層次遍歷。ios
void pre_order(BTree *root){ if (root != NULL){ visit(root); //cout<<root->value pre_order(root->leftchild); pre_order(root->rightchild); } }
void in_order(BTree* root){ if (root != NULL){ in_order(root->leftchild); visit(root); in_order(root->rightchild); } }
void post_order(BTree * root){ if (root != NULL){ post_order(root->leftchild); post_order(root->rightchild); visit(root); } }
#include<iostream> #include<string> #include<stack> using namesapce std; typedef struct node{ int data; struct node *leftchild, *rightchild; }BTree; void pre_order(BTree *root){ stack<BTree*> s; BTree *p = root; //當棧非空或者p指針非空時執行 while (p != NULL || !s.empty()){ while (p != NULL){ cout << p->data; s.push(p); p = p->leftchild; } if (!s.empty()){ p = s.top(); s.pop(); p->p->rightchild; } } }
void in_order(BTree * root){ stack<BTree *> s; BTree * p = root; while (p != NULL || !s.empty()){ while (P != NULL){ s.push(p); p = p->leftchild; } if (!s.empty()){ p = s.top; cout << p->data; s.pop(); p = p->rightchild; } } }
void post_order(BTree *root){ stack<BTree *> s; BTree *p = root, *r = NULL; while (p != NULL || !s.empty()){ if (p != NULL){ s.push(p); p = p->leftchild; // 最左邊 } else{ p = s.top(); //右子樹存在且沒有被訪問過 if (p->rightchild != NULL && p->rightchild != r){ p = p->rightchild; s.push(p); p = p->leftchild; } else{ p = s.top(); //彈出結點並訪問 s.pop(); cout << p->data; r = p; p = NULL; } } } }
方法二:
對於任一結點,線將其入棧,若是結點P不存在左孩子和右孩子,則能夠直接訪問它,若是P上存在左孩子或者右孩子,可是左孩子或者右孩子已經訪問過了,則直接訪問該結點,不然,將P的右孩子和左孩子依次入棧。
這種方法要簡單一些。算法
void post_order(BTree *root){ stack<BTree *> s; BTree *cur = NULL; //當前結點 BTree *pre = NULL; //前一次訪問的結點 s.push(root); while (!s.empty()){ cur = s.top(); if ((cur->leftchild == NULL && cur->rightchild == NULL) || (pre != NULL && (pre == cur->leftchild || pre == cur->rightchild))){ //若是當前結點沒有孩子結點或者孩子結點已經被訪問過 cout << cur->data; s.pop(); pre = cur; } else{ if (cur->rightchild != NULL) s.push(cur->rightchild); if (cur ->rightchild != NULL) s.push(cur->leftchild); } } }
// 輸出以root爲根結點的第level層中的全部結點(從左向右) // 成功返回 1 // 遞歸實現 int printNodeAtLevel(BinaryNode *root, int level){ if (!root || level < 0) return 0; if (level == 0){ // 根結點爲0深度 cout << root->data << " "; return 1; } return printNodeAtLevel(root->leftchild,level -1) + printNodeAtLevel(root->rightchild,level-1); }
void layer_order(BTree *tree){ if (tree == NULL) return; queue<BTree *> q; q.push(tree); BTree * p = NULL; while (!q.empty()){ p = que.front(); visit(p); que.pop(); if (p->leftchild != NULL) que.push(p->leftchild); if (p->rightchild != NULL) que.push(p->rightchild); } } // 本身實現隊列 # define max 1000; typedef struct sequeue{ BTree data[max]; int front; int rear; }sequeue; void enter(sequeue *q, BTree t){ if (q->rear == max){ cout << "the queue is full" << endl; } else{ q->data[q->rear] = t; q->rear++; } } BTree del(sequeue *q, BTree t){ if (q->front == q->rear){ return NULL; } else{ q->frot++; return q->data[q->front -1] } } void level_tree(bintree t){ sequeue q; Btree temp; q.front = q.rear = 0; if (!t){ printf("the tree is empty\n"); return; } enter(&q, t); while (q.front != q.rear){ t = del(&q); printf("%c ", t->data); if (t->lchild){ enter(&q, t->lchild); } if (t->rchild){ enter(&q, t->rchild); } } }
比較兩棵二叉樹是否相等,注意是否能夠旋轉的問題數組
bool isequal(BinaryNode *root1, BinaryNode *root2){ if (root1 == NULL && root2 == NULL) return true; if (!root1 || !root2) return false; if (root1->data == root2->data) return isequal(root1->leftchild, root2->leftchild) && isequal(root1->rightchild, root2->rightchild); else return false; } //若是左右節點能夠旋轉 return (isequal(root1->leftchild, root2->leftchild) && isequal(root1->rightchild, root2->rightchild)) || isequal(root1->leftchild, root2->rightchild) && isequal(root1->rightchild, root2->leftchild);
本質上是二叉樹的遍歷,先求出左右子樹的深度,才能求出根結點的深度網絡
int tree_height(BinaryNode *root){ int left, right; if (root == NULL) return -1; left = tree_height(root->leftchild); right = tree_height(root->rightchild); return (left > right) ? left : right; }
《編程之美: 求二叉樹中節點的最大距離》的另外一個解法數據結構
所以狀況A須要子樹的最大深度,B須要子樹的最大距離。函數
struct result{ int nMaxDistance; // 最大距離 int nMaxDepth; // 最大深度 }; result getMaximumDistance(BinaryNode *root){ if (!root){ result empty = { 0, -1 }; //最大深度初始化爲 -1,調用者要對它加1,而後變爲0 return empty; } result res; result lhs = getMaximumDistance(root->leftchild); result rhs = getMaximumDistance(root->rightchild); res.nMaxDepth = max(lhs.nMaxDepth + 1, rhs.nMaxDepth + 1); res.nMaxDistance = max(max(lhs.nMaxDistance, rhs.nMaxDistance), lhs.nMaxDepth + rhs.nMaxDepth + 2); return res; }
BinaryNode *Construct(int *preorder, int *inorder, int length){ if (preorder == NULL || inorder == NULL || length <= 0) return NULL; // 注意return NULL // 前序 - 首:尾 中序 - 首:尾 return ConstructCore(preorder, preorder + length - 1, inorder, inorder + length - 1); } BinaryNode *ConsturctCore(int *startPreorder, int *endPreorder, int * startInorder, int * endInorder){ //前序遍歷第一個數字是根結點的值 int rootvalue = startPreorder[0]; BinaryNode *root = new BinaryNode();//創建結點 root->data = rootvalue; root->leftchild = root->rightchild = NULL; if (startPreorder == endPreorder){ // 邊界條件 if (startInorder == endInorder && *startPreorder == *startInorder) return root; else throw std:exception("Invalid input");//非法輸入 } // 在中序遍歷中找到根結點的值 int *rootInorder = startInorder; while (rootInorder <= endInorder && *rootInorder != rootvalue) ++rootInorder; if (rootInorder == endInorder && *rootInorder != rootValue) throw std::exception("Invaild input"); int leftLength = rootInorder - startInorder; int *leftPreorderEnd = startPreorder + leftLength; if (leftLength > 0) //構建左子樹 遞歸 //中序遍歷後根據根節點獲取的 左子樹元素 rootinorder是中序遍歷中的根元素的位置 root->leftchild = ConstructCore(startPreorder + 1, leftPreorderEnd, startInorder, rootInorder - 1); if (leftLength < endPreorder - startPreorder) root->rightchild = ConstructCore(leftPreorderEnd + 1, endPreorder, rootInorder, endInorder); return root; }
bool findBTree(BinaryNode *root, ElemType &x){ if (root == NULL) return false; if (root->data == x){ x = root->data; return true; } else{ if (findBTree(root->leftchild, x)) return true; if (findBTree(root->rightchild, x)) return true; return false; } }
int Count(BinaryNode *root, ElemType &x){ if (root == NULL) return -1; if (root->data == x){ return Count(root->leftchild, x) + Count(root->rightchild, x) + 1; } else return Count(root->leftchild, x) + Count(root->rightchild, x); }
int findlevel(BinaryNode *root, int x){ if (root == NULL) return -1; if (root->data == x) // 根結點的層號爲1 return 1; else{ int leftlevel = findlevel(root->leftchild, x); if (leftlevel >= 1) return leftlevel + 1; int rightlevel = findlevel(root->rightchild, x); if (rightlevel >= 1) return rightlevel + 1; } else{ return -1; } }
int MaxValue(BinaryNode * root){ if (root == NULL) return 0; int leftmax, rightmax; leftmax = MaxValue(root->leftchild); rightmax = MaxValue(root->rightchild); int submax = (leftmax >= rightmax) ? leftmax : rightmax; return (submax >= root->data) ? submax : root->data; }
int TreeCount(BinaryNode *root){ if (root == NULL) return -1; else return Treecount(root->leftchild) + TreeCount(root->rightchild) + 1; }
int LeafCount(BinaryNode *root){ if (root == NULL) return -1; if (root->leftchild == NULL && root->rightchild == NULL) return 1; else return LeafCount(root->leftchild) + LeafCount(root->rightchild); }
一棵二叉樹每一個結點包含一個整數,請設計一個算法輸出全部知足條件的路徑,此路徑上全部結點的和等於定值,注意此類路徑不要求必須從根結點開始post
void printbuffer(vector<int> buffer, int level, int end){ for (int i = level, i <= end; i++) cout << buffer[i] << " "; cout << endl; } // 輸入:二叉樹 sum定值 存儲的vector<buffer> void findsum(BinaryNode *root, int sum, vector<int> buffer, int level){ if (root == NULL) return; int temp = sum; buffer.push_back(root->data); for (int i = level; i >= 0; i--){ temp -= buffer[i]; if (temp ==0) printbuffer(buffer,level,i) } findsum(root->leftchild, sum, buffer, level + 1); buffer.pop_back(); level -= 1; findsum(root->rightchild, sum, buffer, level + 1); }
// 二叉搜索樹的中序遍歷是遞增的 int prev = INT_MIN; int judgeBST(BinaryNode *root){ int b1, b2; if (root == NULL) return 1; else{ b1 = judgeBST(root->rightchild); if (b1 == 0 || prev >= root->data) return 0; prev = root->data; b2 = judgeBST(root->rightchild); return b2; } }
// 查找是否含有key值 // 這是迭代寫法 也能夠遞歸寫法 bool searchBST(BinarySortTree *root,int key){ if (root == NULL) return false; BinarySortTree *current = root; while (root != NULL){ if (key == current->data) return true; else if (key < current->data) current = current->leftchild; else current = current->rightchild; } return false; } // 插入結點 // 若是遇到重複的元素能夠根據本身的定義將它歸到左子樹或者右子樹 void insertBST(BinarySortTree *root,int key){ BinarySortTree *current = root; BinarySortTree *pre = NULL; while (current != NULL){ pre = current; if (key < current->data) current = current->leftchild; else if (key>current->data) current = current->rightchild; else return; } BinarySortTree newnode; newnode = (BinarySortTree)malloc(sizeof(BinarySortTreeNode)); newnode->data = key; newnode->leftchild = newnode->rightchild = NULL; // prev 是要安放的結點的父親結點 if (current == NULL) current->data = key; else if (key < pre->data) pre->leftchild = newnode; else pre->rightchild = newnode; }
//後序遍歷 bool isBalanced(BinaryNode* root, int *pDepth){ if (root == NULL){ *pDepth = 0; return true; } int left, right; if (isBalanced(root->leftchild, &left) && isBalanced(root->rightchild, &right)){ int diff = left - right; if (diff <= 1 && diff >= -1){ *pDepth = 1 + (left>right ? left : right); return true; } } return false; } //最大深度和最小深度的差 int maxDepth(BinaryNode *root){ if (root == NULL) return 0; return 1 + max(maxDepth(root->leftchild), maxDepth(root->rightchild)); } int minDepth(BinaryNode *root){ if (root == NULL) return 0; return 1 + min(minDepth(root->leftchild), minDepth(root->rightchild)); } bool isBalanced(BinaryNode *root){ return (maxDepth(root) - minDepth(root) <= 1); }