線性結構、樹型結構、圖狀結構和純集合結構做爲數據的四種結構,樹型結構是一類重要的非線性結構。node
以二叉樹爲例瞭解一下樹型結構的基本性質及用法:ios
二叉樹:數組
每一個節點至多有兩棵子樹,左子樹和右子樹,次序不可顛倒post
非空二叉樹的第n層至多有2^(n-1)個結點spa
深度爲h的二叉樹至多有2^h - 1 個結點.net
完美二叉樹(滿二叉樹)的結點個數爲2^h - 1 code
徹底二叉樹的第h層的結點都集中在左邊blog
完美二叉樹自己也是徹底二叉樹遞歸
對於徹底二叉樹,設一個結點(非根結點)編號爲 i ,則其父親結點編號爲 i / 2 , 其左子結點編號爲 2 * i , 右子結點編號爲 2 * i + 1ci
葉子結點的個數等於度爲2的結點個數 + 1
同理:
m叉樹的葉子結點個數n0,有一個兒子的結點個數n1,有兩個兒子的結點個數n2,有三個兒子的結點個數n3……有m個兒子的結點個nm之間存在什麼關係?
n0 + n1 + n2 + …… nm - 1 = 0 * n0 + 1 * n1 + 2 * n2 + 3 * n3 + 4 * n4 + …… m * nm
因此: n0 - 1 = n2 + 2 * n3 + 3 * n4 + …… + (m-1) * nm
存儲結構:
順序存儲:
徹底二叉樹能夠用數組來實現,通常二叉樹若是採用這種存儲方式,空間代價較高
數組實現二叉樹的順序存儲代碼:
typedef struct Node { int data ; int lchild , rchild ; int father ; }Node ; Node btree[1000] ;
鏈式存儲:
typedef struct Node { int data ; struct Node * lchild ; struct Node * rchild ; }Node ; Node *new_Node() { Node * newnode = new Node ; newnode->data = 0 ; newnode->lchild = NULL ; newnode->rchild = NULL ; return newnode ; }
二叉樹的遍歷:
遍歷即二叉樹的全部結點訪問一遍,根據訪問根結點的順序分爲:先序遍歷、中序遍歷和後續遍歷:
先序遍歷: 根結點 -> 左子樹 -> 右子樹
中序遍歷: 左子樹 -> 根結點 -> 右子樹
後序遍歷: 左子樹 -> 右子樹 -> 根結點
先序遍歷:1 -> 2 -> 4 -> 5 -> 7 -> 3 -> 6 -> 8
中序遍歷:4 -> 2 -> 5 -> 7 -> 1 -> 3 -> 8 -> 6
後序遍歷:4 -> 7 -> 5 -> 2 -> 8 -> 6 -> 3 -> 1
遍歷的遞歸實現:
#include<iostream> #include<stdio.h> using namespace std ; typedef struct Node { int data ; struct Node * lchild ; struct Node * rchild ; }Node ; Node *new_Node() { Node * newnode = new Node ; newnode->data = 0 ; newnode->lchild = NULL ; newnode->rchild = NULL ; return newnode ; } typedef Node *node ; Node *CreatebinTree() { int a ; Node *T ; cin >> a ; if(a == 0) return NULL ; else { T = new_Node() ; T->data = a ; T->lchild = CreatebinTree() ; T->rchild = CreatebinTree() ; } return T ; } void preorder(node T) { if(T) { if(T->data != 0) cout << T->data << " " ; preorder(T->lchild) ; preorder(T->rchild) ; } } int main() { freopen("in.txt","r",stdin) ; Node * root = CreatebinTree() ; preorder(root) ; return 0 ; } // 輸入數據: // 1 2 4 0 0 5 0 7 0 0 3 0 6 8 0 0 0
非遞歸遍歷:
#include<iostream> #include<stdio.h> using namespace std ; typedef struct Node { int data ; struct Node *lchild ; struct Node *rchild ; }Node; Node *New_Node() { Node *T = new Node ; T->data = 0 ; T->lchild = NULL ; T->rchild = NULL ; return T ; } Node *CreateBinTree() { Node *T ; int a ; cin >> a ; if(a == 0) return NULL ; else { T = New_Node() ; T->data = a ; T->lchild = CreateBinTree() ; T->rchild = CreateBinTree() ; } return T ; } /*void preorder(Node *T) { if(T != NULL) { cout << T->data << " " ; preorder(T->lchild) ; preorder(T->rchild) ; } } */ typedef struct stackk { Node *node[1000] ; int top ; }stackk; void push(stackk &s , Node *n) { if(s.top == 999) printf("stack is full\n") ; else { s.node[++(s.top)] = n ; } } Node* pop(stackk &s) { if(s.top == -1) return NULL ; else return s.node[(s.top)--] ; } void preorder(Node *root) { stackk s ; s.top = -1 ; if(root == NULL) printf("tree is empty\n") ; else { while(root != NULL || s.top != -1) { while(root != NULL) { printf("%d ",root->data) ; push(s,root) ; root = root->lchild ; } root = pop(s) ; root = root->rchild ; } } } int main() { freopen("in.txt","r",stdin) ; Node *root ; root = CreateBinTree() ; preorder(root) ; return 0 ; }
非遞歸實現後續遍歷:
#include<iostream> #include<stdio.h> using namespace std ; typedef struct Node { int data ; struct Node *lchild ; struct Node *rchild ; }Node; Node *New_Node() { Node *T = new Node ; T->data = 0 ; T->lchild = NULL ; T->rchild = NULL ; return T ; } Node *CreateBinTree() { Node *T ; int a ; cin >> a ; if(a == 0) return NULL ; else { T = New_Node() ; T->data = a ; T->lchild = CreateBinTree() ; T->rchild = CreateBinTree() ; } return T ; } /*void preorder(Node *T) { if(T != NULL) { cout << T->data << " " ; preorder(T->lchild) ; preorder(T->rchild) ; } } */ typedef struct stackk { Node *node[1000] ; int top ; int flag[1000] ; }stackk; void push(stackk &s , Node *n) { if(s.top == 999) printf("stack is full\n") ; else { s.node[++(s.top)] = n ; } } Node* pop(stackk &s) { if(s.top == -1) return NULL ; else return s.node[(s.top)--] ; } void postorder(Node *root) { stackk s ; s.top = -1 ; if(root == NULL) printf("tree is empty\n") ; else { while(root != NULL || s.top != -1) { while(root != NULL) { push(s,root) ; s.flag[s.top] = 0 ; root = root->lchild ; } if(s.flag[s.top] == 0) { s.flag[s.top] = 1 ; root = s.node[s.top] ; root = root->rchild ; } else { while(s.flag[s.top] == 1) { root = pop(s) ; printf("%d ",root->data) ; root = NULL ; } } } } } int main() { freopen("in.txt","r",stdin) ; Node *root ; root = CreateBinTree() ; preorder(root) ; return 0 ; }
層次遍歷:
#include<iostream> #include<stdio.h> using namespace std ; typedef struct Node { int data ; struct Node *lchild ; struct Node *rchild ; }Node; Node *New_Node() { Node *T = new Node ; T->data = 0 ; T->lchild = NULL ; T->rchild = NULL ; return T ; } Node *CreateBinTree() { Node *T ; int a ; cin >> a ; if(a == 0) return NULL ; else { T = New_Node() ; T->data = a ; T->lchild = CreateBinTree() ; T->rchild = CreateBinTree() ; } return T ; } /*void preorder(Node *T) { if(T != NULL) { cout << T->data << " " ; preorder(T->lchild) ; preorder(T->rchild) ; } } */ typedef struct queuee { Node *node[1000] ; int front ; int rear ; }queuee; void push(queuee &q , Node *T) { if(q.rear == 999) printf("queue is full\n") ; else q.node[(q.rear)++] = T ; } Node *pop(queuee &q) { if(q.front == q.rear) return NULL ; else return q.node[q.front++] ; } void ccbl(Node *root) { queuee q ; q.front = q.rear = 0 ; if(root != NULL) push(q,root) ; while(q.front < q.rear) { Node *T = pop(q) ; cout << T->data << " " ; if(T->lchild != NULL) push(q,T->lchild) ; if(T->rchild != NULL) push(q,T->rchild) ; } } int main() { freopen("in.txt","r",stdin) ; Node *root ; root = CreateBinTree() ; ccbl(root) ; return 0 ; }
二叉樹查找:
#include<iostream> #include<stdio.h> using namespace std ; typedef struct Node { int data ; struct Node *lchild ; struct Node *rchild ; }Node; Node *New_Node() { Node *T = new Node ; T->data = 0 ; T->lchild = NULL ; T->rchild = NULL ; return T ; } Node *CreateBinTree() { Node *T ; int a ; cin >> a ; if(a == 0) return NULL ; else { T = New_Node() ; T->data = a ; T->lchild = CreateBinTree() ; T->rchild = CreateBinTree() ; } return T ; } /*void preorder(Node *T) { if(T != NULL) { cout << T->data << " " ; preorder(T->lchild) ; preorder(T->rchild) ; } } */ Node *search(Node *T , int x) { if(T == NULL) return NULL ; if(T->data == x) { return T ; } if(search(T->lchild,x) != NULL) return search(T->lchild,x) ; else return search(T->rchild,x) ; } int main() { freopen("in.txt","r",stdin) ; Node *root ; root = CreateBinTree() ; root = search(root,5) ; cout << root->rchild->data << endl ; return 0 ; }
遞歸太強大啦