二叉树c++
原创、转载请注明出处
二叉树特点
对于完全二叉树,第n层结点的结点个数是2的n次方个,对于第k个结点,它的左子节点是2k,右子节点是2k+1。
前序遍历
中序遍历:
后序遍历:
一、结构
二叉树有2类表示方法:链式和数组模拟。
其中数组模拟有2种:1.一个数组,数组下标代表完全二叉树的编号,对于普通二叉树,没有结点的为空,有节点的地方数组值为二叉树权值。
2.2个数组l[id]、r[id],二叉树结点的权值是编号,数组下标是编号,r[i]的数组值是结点i的右结点编号。(权值各不相同且都为正整数才能用这种方式表示)
二、构造二叉树
1.最基础的输入方式(数组的只写了一种):
<1>根据层次遍历构造二叉树,例如:
●链表结构代码:
#include "stdafx.h" #include <iostream> #include<sstream> using namespace std; struct BinaryTree { char data; BinaryTree *lch; BinaryTree *rch; }; char a[1000]; void createTree(BinaryTree* &p, int pos) { if (a[pos] == '#') { p = nullptr; return; } p = new BinaryTree; p->data = a[pos]; createTree(p->lch, pos * 2); createTree(p->rch, pos * 2 + 1); } void preOrder(BinaryTree* p) { if (p == nullptr) { return; } //cout << p->data; preOrder(p->lch); cout << p->data; preOrder(p->rch); //cout << p->data; } int main() { string str; getline(cin, str); stringstream s(str); int i = 1; while (s >> a[i]) { i++; } BinaryTree* root = new BinaryTree; createTree(root, 1); preOrder(root); cout << endl; }
注意构建函数,一定是指针引用。如果是指针会发生如下情况:实参赋给形参,形参又指向了另一个块新开辟的地址,最后导致,我想创建树,但是创建函数并没有改变传入的根节点。
●链表结构代码(智能指针):
#include<iostream>
#include<string>
#include<sstream>
#include<memory>
using std::cin;
using std::cout;
using std::endl;
using std::make_shared;
using std::shared_ptr;
using std::string;
using std::stringstream;
char a[1000];
struct tree
{
char ele;
shared_ptr<tree> left;
shared_ptr<tree> right;
};
void build(shared_ptr<tree> &p,int pos)
{
if(a[pos] == '#')
{
p = nullptr;
return;
}
p = make_shared<tree>();
p->ele = a[pos];
build(p->left,pos*2);
build(p->right,pos*2 + 1);
}
void preOrder(shared_ptr<tree> p)
{
if(p == nullptr)
{
return;
}
cout << p->ele << ' ';
preOrder(p->left);
preOrder(p->right);
}
void inOrder(shared_ptr<tree> p)
{
if(p == nullptr)
{
return;
}
inOrder(p->left);
cout << p->ele << ' ';
inOrder(p->right);
}
int main()
{
string str;
getline(cin,str);
stringstream s(str);
int leng = 1;
while(s >> a[leng])
{
leng++;
}
shared_ptr<tree> root;
build(root,1);
cout << endl;
preOrder(root);
cout << endl;
inOrder(root);
cout << endl;
return 0;
}
●数组结构代码:
#include<iostream>
#include<string>
#include<sstream>
using std::stringstream;
using std::string;
using std::cin;
using std::cout;
using std::endl;
char a[1000];
void read_list(char *arr)
{
string str;
getline(cin,str);
stringstream s(str);
int leng = 1;
while(s >> arr[leng])
{
leng++;
}
}
void preOrder(int pos)
{
if(a[pos] == '#')
return ;
cout << a[pos] << ' ';
preOrder(pos * 2);
preOrder(pos * 2 + 1);
}
void inOrder(int pos)
{
if(a[pos] == '#')
return ;
inOrder(pos * 2);
cout << a[pos] << ' ';
inOrder(pos * 2 + 1);
}
int main()
{
read_list(a);
preOrder(1);
cout << endl;
inOrder(1);
cout << endl;
return 0;
}
<2>根据前序(没有中序和后序)遍历构造二叉树,例如:
●链表结构代码:
#include "stdafx.h" #include <iostream> using namespace std; struct Binarytree { char data; Binarytree* lch; Binarytree* rch; }; void createTree(Binarytree* &p) { char c; cin >> c; if (c == '#') { p = nullptr; return; } p = new Binarytree; p->data = c; createTree(p->lch); createTree(p->rch); } void preOrder(Binarytree *p) { if (p == nullptr) { return; } cout << p->data << ' '; preOrder(p->lch); preOrder(p->rch); } void inOrder(Binarytree *p) { if (p == nullptr) { return; } inOrder(p->lch); cout << p->data << ' '; inOrder(p->rch); } void postOrder(Binarytree *p) { if (p == nullptr) { return; } postOrder(p->lch); postOrder(p->rch); cout << p->data << ' '; } int main() { Binarytree* root = new Binarytree; createTree(root); preOrder(root); cout << endl; inOrder(root); cout << endl; postOrder(root); cout << endl; }
注意构建函数,一定是指针引用。如果是指针会发生如下情况:实参赋给形参,形参又指向了另一个块新开辟的地址,最后导致,我想创建树,但是创建函数并没有改变传入的根节点。
●链表结构代码(智能指针):
#include<iostream>
#include<memory>
using std::cin;
using std::cout;
using std::endl;
using std::make_shared;
using std::shared_ptr;
struct tree
{
char ele;
shared_ptr<tree> left;
shared_ptr<tree> right;
};
void build(shared_ptr<tree> &p)//输入前序遍历顺序确定结构
{
char a;
cin >> a;
if(a == '#')
{
p = nullptr;
return;
}
p = make_shared<tree>();
p->ele = a;
build(p->left);
build(p->right);
}
void preOrder(shared_ptr<tree> p)
{
if(p == nullptr)
{
return;
}
cout << p->ele << ' ';
preOrder(p->left);
preOrder(p->right);
}
void inOrder(shared_ptr<tree> p)
{
if(p == nullptr)
{
return;
}
inOrder(p->left);
cout << p->ele << ' ';
inOrder(p->right);
}
int main()
{
shared_ptr<tree> root;
build(root);
cout << endl;
preOrder(root);
cout << endl;
inOrder(root);
cout << endl;
return 0;
}
●数组结构代码:
#include<iostream>
using std::cin;
using std::cout;
using std::endl;
char a[1000];
void build(int pos)
{
cin >> a[pos];
if(a[pos] == '#')
{
return;
}
build(pos * 2);
build(pos * 2 + 1);
}
void preOrder(int pos)
{
if(a[pos] == '#')
return ;
cout << a[pos] << ' ';
preOrder(pos * 2);
preOrder(pos * 2 + 1);
}
void inOrder(int pos)
{
if(a[pos] == '#')
return ;
inOrder(pos * 2);
cout << a[pos] << ' ';
inOrder(pos * 2 + 1);
}
int main()
{
build(1);
preOrder(1);
cout << endl;
inOrder(1);
cout << endl;
return 0;
}
三、扩展
大概意思:
1.搜索树:节点权值从左到右递增,和用数组二分搜索的区别是,这种结构便于插入和删除(类似链表和数组的区别)
2.平衡树:每个节点的左右子树高度相差不超过1
3.红黑树:树的节点不是红色就是黑色,根和外部节点是黑色,没有2个相连的红节点