前端学习数据结构之【二叉树】
5.1 Binary Tree 二叉树
Binary Tree:each node can have at most 2 children
Strict/Proper binary tree: each node can have either 2 or 0 children
Complete Binary tree:all levels except possibly the last are completely filled and all nodes are as left as possible
5.1.1 height of tree
- min-height=[log2 n] O(log2 n);max-height=n-1 O(n);
5.1.2 binary search Tree
Array 数组已经满,复制的成本是O(n);Linked List BST
search(x) O(n); O(n); O(logn)
Insert(x) O(1); O(1); O(logn)
remove(x) O(n); O(n); O(logn)
5.1.3二分查找法 O(logn)
二叉搜索树 Olgn
平衡树:通过保持二叉搜索树来避免二叉搜索树搜索时间复杂度为O(n);
二叉完美树
二叉搜索树的实现 binary search tree- Implementation in c/c++
#include<iostream>
using namespace std;
struct BstNode{
int data;
BstNode* left;
BstNode* right;
};
BstNode* GetNewNode(int data){
BstNode* newNode = new BstNode();
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
}
//----------BstNode**方式start--------
//BstNode** rootPtr 传的是root的地址
void Insert(BstNode** root,int data){
//*root 获取root的值,使用*操作符来访问main中的root的值
if(*root == NULL)
{
*root = GetNewNode(data);
}
};
int main(){
//root 是局部变量
BstNode* root = NULL;
Insert(&root,15);
Insert(&root,10);
Insert(&root,20);
}
//----------------------end
//-------------BstNode*方式start
BstNode* Insert(BstNode* root,int data){
if(root == NULL)
{
root = GetNewNode(data);
}
else if(data <= root->data){
root->left = Insert(root->left,data);
}
else{
root->right = Insert(root->right,data);
}
return root;
};
bool Search(BstNode* root,int data){
if(root == NULL)return false;
else if(root->data == data)return true;
else if(data <= root->data)return Search(root->left,data);
else return Search(root->right,data);
}
int main(){
//root 是局部变量
BstNode* root = NULL;
root = Insert(&root,15);
root = Insert(&root,10);
root = Insert(&root,20);
int number;
cout<<"enter number be searched\n";
cin>>number;
if(Search(root,number)== true)cout<<"found\n";
else cout<<"not found\n";
}
//-------------BstNode*方式end
BST implementation in c/c++ - Part2
Cde(Text)代码段:存储程序指令
Static/Global:存放全局变量
Stack:栈,程序完成,自动释放
Heap:堆,动态内存,free store,可以控制堆内存的分配或者回收
Find min and max element in a BST
struct BsNode {
int data;
BsNode* left;
BsNode* right;
}
int FindMin(BsNode* root){
if(root == NULL){
cout<<"error: tree is empty";
return -1;
}
while(root->left != NULL){
root = root->left;
}
//search in left subtress
return FindMin(root->left);
}
find height of a binary tree
height of a node:
Number of edges in longest
path from the node to a leaf node
height of tree = Height of root
Depth of a node = 从根节点到该节点的边数
FindHeight(root){
if(root == NULL) return -1;
leftHeight<-FindHeight(root->left);
rightHeight<-FindHeight(root->right)
return max(leftHeight,rightHeight)+1
}
binary Tree Traversal 二叉树遍历,广度优先,深度优先
深度优先遍历-先序变量
先根次序遍历按照“根结点 > 左孩子 > 右孩子”的顺序进行访问。
// 递归实现-先根递归遍历。
void preOrderRecursion(BinaryTreeNode* root) {
if(root==NULL) return;
cout<< " " << root->data;
preOrderRecursion(root->m_pLeft);
preOrderRecursion(root->m_pRight);
}
// 先序非递归遍历,需要使用栈
void preOrderStack(BinaryTreeNode* root) {
if(root==NULL) return;
stack<BinaryTreeNode*> stack;
stack.push(root);
BinaryTreeNode* cur=NULL;
while(!stack.empty()) {
cur=stack.top();
cout<<" "<<cur->data; //visit
stack.pop();
if(cur->m_pRight!=NULL) {
stack.push(cur->m_pRight);
}
if(cur->m_pLeft!=NULL) {
stack.push(cur->m_pLeft);
}
}
}
深度优先遍历-中序遍历
中序遍历按照“左孩子 > 根结点 > 右孩子”的顺序进行访问。
// 中序递归遍历。
void midOrderRecursion(BinaryTreeNode* root){
if(root==NULL) return;
midOrderRecursion(root->m_pLeft);
cout<<" "<<root->data; //visit
midOrderRecursion(root->m_pRight);
}
// 中根非递归遍历,需要使用栈
void midOrderStack(BinaryTreeNode* root) {
if(root==NULL) return;
stack<BinaryTreeNode*> stack;
BinaryTreeNode* cur=root;
while(!stack.empty() || cur!=NULL) {
while(cur) {
stack.push(cur);
cur=cur->m_pLeft;
}
cur=stack.top();
cout<<" "<<cur->data; //visit
stack.pop();
cur=cur->m_pRight;
}
}
深度优先遍历-后序遍历
后序遍历按照“左孩子 > 右孩子 > 根结点”的顺序进行访问。
// 后根递归遍历
void postOrderRecursion(BinaryTreeNode* root) {
if(root==NULL) return;
postOrderRecursion(root->m_pLeft);
postOrderRecursion(root->m_pRight);
cout << " " << root->data;
}
// 非递归后序遍历,版本1
void postOrderStack1(BinaryTreeNode* root) {
if(root==NULL) return;
stack<pair<BinaryTreeNode*, bool>> s;
pair<BinaryTreeNode*,bool> cur=make_pair(root,true);
while(cur.first!=NULL||!s.empty()) {
//沿左子树一直往下搜索,直至出现没有左子树的结点
while(cur.first!=NULL) {
s.push(cur);
cur=make_pair(cur.first->m_pLeft,true);
}
if(!s.empty()) {
//表示是第一次出现在栈顶
if(s.top().second==true) {
s.top().second=false;
cur=make_pair(s.top().first->m_pRight,true); //将当前节点的右节点入栈
} else {
// 第二次出现在栈顶
cout << s.top().first->data << " ";
s.pop();
}
}
}
}
广度优先遍历
广度优先周游的方式是按层次从上到下,从左到右的逐层访问,不难想到,可以利用一个队列来实现。基本思想如下:
(1)首先把二叉树的根节点送入队列;
(2)队首的节点出队列并访问之,然后把它的右子节点和左子节点分别入队列;
(3)重复上面两步操作,直至队空。
// 广度优先遍历二叉树,使用队列实现
void breadthFirstOrder(BinaryTreeNode* root) {
if(root==NULL) return;
queue<BinaryTreeNode*> queue;
queue.push(root);
while(!queue.empty()) {
BinaryTreeNode* cur=queue.front();
cout<<" "<<cur->m_key;//visit
queue.pop();
if(cur->m_pLeft!=NULL) queue.push(cur->m_pLeft);
if(cur->m_pRight!=NULL) queue.push(cur->m_pRight);
}
}
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
// 二叉树节点结构体
struct BinaryTreeNode {
int m_key;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
/****************************************
func:根据前序序列和中序序列构建二叉树
para:preOrder:前序序列;midOrder:中序序列;len:节点数
****************************************/
BinaryTreeNode* construct(int* preOrder,int* midOrder,int len) {
if(preOrder==NULL||midOrder==NULL||len<=0) return NULL;
//先序遍历的第一个值是根结点的键值
int rootKey=preOrder[0];
BinaryTreeNode* root=new BinaryTreeNode;
root->m_key=rootKey;
root->m_pLeft=root->m_pRight=NULL;
//只有一个节点
if(len==1 && *preOrder == *midOrder) return root;
//在中序遍历中找到根节点的值
int* rootMidOrder=midOrder;
int leftLen=0; //左子树节点数
while(*rootMidOrder!=rootKey&&rootMidOrder<=(midOrder+len-1)) {
++rootMidOrder;
++leftLen;
}
//在中序序列未找到根结点,输入错误
if(*rootMidOrder!=rootKey) return NULL;
//构建左子树
if(leftLen>0) {
root->m_pLeft=construct(preOrder+1,midOrder,leftLen);
}
//构建右子树
if(len-leftLen-1>0) {
root->m_pRight=construct(preOrder+leftLen+1,rootMidOrder+1,len-leftLen-1);
}
return root;
}
int main() {
// 先序序列
int preOrder[8]={1,2,4,7,3,5,6,8};
// 中序序列
int midOrder[8]={4,7,2,1,5,3,8,6};
// 建树
BinaryTreeNode* root=construct(preOrder, midOrder, 8);
cout<<"---preOrder---"<<endl;
cout<<"recursion version: ";
preOrderRecursion(root);
cout<<endl<<"stack version: ";
preOrderStack(root);
cout<<endl<<endl<<"---midOrder---"<<endl;
cout<<"recursion version: ";
midOrderRecursion(root);
cout<<endl<<"stack version1: ";
postOrderStack1(root);
cout<<endl<<"stack version2: ";
postOrderStack2(root);
cout<<endl<<endl<<"---postOrder---"<<endl;
cout<<"recursion version: ";
postOrderRecursion(root);
cout<<endl<<"stack version: ";
postOrderStack1(root);
cout<<endl<<endl<<"---Breadth First Order---"<<endl;
breadthFirstOrder(root);
}