二叉樹的連結實現及基本操作(C++)
阿新 • • 發佈:2018-12-16
前言:
學習了棧和佇列後,我們接著在資料結構的海洋中遨遊。這時的我已經被各種棧和佇列折騰的快不行了,然而,當學習了樹之後,才發現自己還是太年輕,跟樹比起來,棧和佇列是那麼的和諧與友好。先來小試牛刀一把,看看最簡單的二叉樹是怎麼實現的:
二叉樹的實現:
二叉樹是節點的有限集合,他或者為空,或者有一個根節點及兩顆互不相交的左右子樹構成,而左右子樹有都是二叉樹。寫到這裡,是不是已經體會到了一點二叉樹與遞迴的曖昧關係。
若一棵樹的任意一層節點數都達到了最大值,則這棵二叉樹稱為滿二叉樹。
而如果將滿二叉樹自右向左依次刪掉幾個節點(注意不要跳過節點),那樣的樹就是完全二叉樹。
二叉樹的常用性質:
1. 一棵非空二叉樹的第i層上最多有個節點(i>=1)。
2. 一棵高度為k的二叉樹,最多有 - 1個節點。
3. 對於一棵非空二叉樹,如果葉子節點數為a,度為2的節點數為吧b,則a = b + 1。
4. 具有n個節點的完全二叉樹的高度為k = [log2(n)] + 1。(其中[ ]指不比裡面數大的最大整數)
說了這麼多,下面就來看看具體的C++實現:
#include <iostream> using namespace std; template<class elemType> class queue { public: virtual bool isEmpty() = 0; virtual void enQueue(const elemType &x) = 0; virtual elemType deQueue() = 0; virtual elemType getHead() = 0; virtual ~queue(){}; }; template<class elemType> class linkQueue: public queue<elemType> { private: struct node{ elemType data; node *next; node(const elemType &x, node *N = NULL){ data = x; next = N; } node():next(NULL){} ~node(){} }; node *front , *rear; public: linkQueue(){ front = rear = NULL; } ~linkQueue(){ node *tmp; while(front != NULL){ tmp = front; front = front -> next; delete tmp; } } bool isEmpty(){ return front == NULL; } void enQueue(const elemType &x){ if(rear == NULL){ front = rear = new node(x); } else{ rear -> next = new node(x); rear = rear -> next; } } elemType deQueue(){ node *tmp = front; elemType value = front -> data; front = front -> next; if(front == NULL){ rear = NULL; } delete tmp; return value; } elemType getHead() { return front-> data; } }; template<class T> class bTree{ public: virtual void clear() = 0; virtual bool isEmpty()const = 0; virtual T Root(T flag)const = 0; virtual T parent(T x, T flag)const =0; virtual T lchild(T x, T flag)const = 0; virtual T rchild(T x, T flag)const = 0; virtual void delLeft(T x) = 0; virtual void delRight(T x) = 0; virtual void preOrder() const = 0; virtual void midOrder() const = 0; virtual void postOrder() const = 0; virtual void levelOrder() const = 0; }; template<class T> class binaryTree:public bTree<T>{ friend void printTree(const binaryTree &t, T flag); private: struct Node{ Node *left, *right, *parent; T data; Node():left(NULL), right(NULL), parent(NULL){} Node(T item, Node *L = NULL, Node *R = NULL):data(item), left(L), right(R){} ~Node(){}; }; Node *root; public: binaryTree():root(NULL){} binaryTree(T x){ root = new Node(x); } ~binaryTree(){ clear(root); } void clear(Node *t){ if(t == NULL){ return; } clear(t -> left); clear(t -> right); delete t; t = NULL; } void clear(){ clear(root); } bool isEmpty()const{ return root == NULL; } T Root(T flag)const{ if(root == NULL){ return flag; } else{ return root->data; } } Node *find(T x, Node *t)const{ Node *tmp; if(t == NULL){ return t; } if(t -> data == x){ return t; } if(tmp = find(x, t -> left)){ return tmp; } else{ return (find(x, t -> right)); } } T lparent(T x, T flag)const{ } T lchild(T x, T flag)const{ Node *tmp = find(x, root); if(tmp == NULL || tmp -> left == NULL){ return flag; } return tmp -> left -> data; } T rchild(T x, T flag)const{ Node *tmp = find(x, root); if(tmp == NULL || tmp -> right == NULL){ return flag; } return tmp -> right -> data; } void delLeft(T x){ Node *tmp = find(x, root); if(tmp == NULL){ return; } clear(tmp -> left); } void delRight(T x){ Node *tmp = find(x, root); if(tmp == NULL){ return; } clear(tmp -> right); } //preorder traverse void preOrder(Node *t)const{ if(t == NULL){ return; } cout << t -> data << ' '; preOrder(t -> left); preOrder(t -> right); } void preOrder()const{ preOrder(root); } //midorder traverse void midOrder(Node *t)const{ if(t == NULL){ return; } midOrder(t -> left); cout << t -> data << ' '; midOrder(t -> right); } void midOrder()const{ midOrder(root); } //postorder traverse void postOrder(Node *t) const{ if(t == NULL){ return; } postOrder(t -> left); postOrder(t -> right); cout << t -> data << ' '; } void postOrder()const{ postOrder(root); } //levelorder traverse void levelOrder()const{ linkQueue<Node *>que; Node *tmp; que.enQueue(root); while(!que.isEmpty()){ tmp = que.deQueue(); cout << tmp -> data << ' '; if(tmp -> left){ que.enQueue(tmp -> left); } if(tmp -> right){ que.enQueue(tmp -> right); } } } //creat a binary tree void creatTree(T flag){ linkQueue<Node *>que; Node *tmp; T x, ldata, rdata; cout << "Please input the root:"; cin >> x; root = new Node(x); que.enQueue(root); while(!que.isEmpty()){ tmp = que.deQueue(); cout << "Input the left node and right node:"; cin >> ldata >> rdata; if(!ldata != flag){ que.enQueue(tmp -> left == new Node(ldata)); } if(!rdata != flag){ que.enQueue(tmp -> left == new Node(rdata)); } } } T parent(T x, T flag)const{ return flag; } //Judge if it is a complete binary tree void isCBT(){ linkQueue<Node *> que; int lastId = 1, nodeCount = 1; root -> data = 1; Node *tmpNode, *son; if(root == NULL){ cout << 'Y'; return; } que.enQueue(root); while(!que.isEmpty()){ tmpNode = que.deQueue(); if(tmpNode -> left != NULL){ nodeCount = nodeCount + 1; son = tmpNode -> left; son -> data = (tmpNode -> data) * 2; lastId = son -> data; que.enQueue(son); } if(tmpNode -> right != NULL){ nodeCount = nodeCount + 1; son = tmpNode -> right; son -> data = (tmpNode -> data) * 2 + 1; lastId = son -> data; que.enQueue(son); } } if(nodeCount == lastId){ cout << 'Y'; } else{ cout << 'N'; } } };
總結:
本節內容主要是介紹了樹的基本概念以及二叉樹的定義、特性和實現程式碼,包括構建樹,四種遍歷樹的操作,以及判斷數是否為完全二叉樹的方法,如果你已經覺得樹如此複雜,那隻能說“小朋友,這才是冰山一角中的一角”,想看看冰山的真面目,就鼓足幹勁接著學習吧。