大家好,又见面了,我是你们的朋友全栈君。
1、完全二叉树
2、满二叉树
3、扩充二叉树
4、平衡二叉树
0、遍历方式
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
struct BTreeNode{
int data = 0;
BTreeNode *left;
BTreeNode *right;
};
class BTree{
public:
BTree(){
}
//传参需要注意,二叉树是指针类型的,节点本身就是一个指针:*node。所以需要二级指针才能改变二叉树的内容
void create(BTreeNode* &Node){
int data;
cin >> data;
if(data){
Node = new BTreeNode;
Node->data = data;
//cout<<"data:"<<data<<endl;
create(Node->left);
create(Node->right);
} else{
Node=NULL;
}
}
//按层创建二叉树
void levelCreate(BTreeNode* &Node){
queue <BTreeNode*> que;
int data;
cin>>data;
if(data){
Node = new BTreeNode;
Node->data = data;
que.push(Node);
} else{
Node = NULL;
return;
}
while(!que.empty()){
BTreeNode *node = que.front();
que.pop();
//输入左边数据
cin>>data;
if(data){
node->left = new BTreeNode;
node->left->data = data;
que.push(node->left);
} else{
node->left = NULL;
}
//输入右边数据
cin >>data;
if(data){
node->right = new BTreeNode;
node->right->data = data;
que.push(node->right);
} else{
node->right = NULL;
}
}
}
//1 2 3 4 5 6 0 0 0 7 8 0 9 0 0 0 0 0 0
void clear(BTreeNode*& Node){
BTreeNode *p = Node;
if(p != NULL){
clear(Node->left);
clear(Node->right);
delete p;
}
}
//前序遍历(根左右)
void preorderTree(BTreeNode* Node){
if(Node!=NULL){
cout<<Node->data<<" ,";
preorderTree(Node->left);
preorderTree(Node->right);
}
}
//前序遍历非递归写法
void NnredursionPreorder(BTreeNode* Node){
stack<BTreeNode*> node;
node.push(Node);
BTreeNode *pNode = Node;
while(pNode != NULL || !node.empty()){
//1、先把节点打印,并且入栈,将节点的左孩子作为当前的节点
//2、当节点不为空或者栈不为空,就取出栈顶,
if(pNode != NULL){
cout<<pNode->data<<" ";
node.push(pNode);
pNode = pNode->left;
} else{
BTreeNode *treeNode = node.top();
node.pop();
pNode = pNode->right;
}
}
}
//中序遍历(左中右)
void inorderTree(BTreeNode* Node){
if(Node != NULL){
inorderTree(Node->left);
cout<<Node->data<<" ,";
inorderTree(Node->right);
}
}
//后序遍历(左右中)
void postorderTree(BTreeNode* Node){
if(Node != NULL){
postorderTree(Node->left);
postorderTree(Node->right);
cout<<Node->data<<" ,";
}
}
//层序遍历
void levelTree(BTreeNode *Node){
queue<BTreeNode*> que;
if(Node == NULL) return;
else{
que.push(Node);
while(!que.empty()){
BTreeNode *node = que.front();
cout<<node->data<<" ";
que.pop();
if(node->left != NULL){
que.push(node->left);
}
if(node->right!=NULL){
que.push(node->right);
}
}
}
}
//二叉树深度
int depthOfTree(BTreeNode* Node){
if(Node){
return max(depthOfTree(Node->left),depthOfTree(Node->right))+1;
} else{
return 0;
}
}
//返回节点总数目
int getNodeNum(BTreeNode* Node){
if(Node){
return 1+getNodeNum(Node->left)+getNodeNum(Node->right);
} else{
return 0;
}
}
//返回叶子节点
int getLeafNum(BTreeNode* Node){
if(!Node){
return 0;
} else if(Node->left == NULL && Node->right == NULL){
return 1;
} else{
return getLeafNum(Node->left)+getLeafNum(Node->right);
}
}
};
int main(){
BTree tree;
BTreeNode *root;
//tree.create(root);
tree.levelCreate(root);
cout<<"pre :";
tree.preorderTree(root);
cout<<endl;
cout<<"in :";
tree.inorderTree(root);
cout<<endl;
cout<<"post:";
tree.postorderTree(root);
cout<<endl;
cout<<"level:";
tree.levelTree(root);
cout<<endl;
cout<<"NodeNum:"<<tree.getNodeNum(root)<<",depth:"<<tree.depthOfTree(root)<<",leaf:"<<tree.getLeafNum(root)<<endl;
tree.clear(root);
return 0;
}
public class RebuildBinaryTree {
//假设输入的前序遍历和中序遍历的结果中都不含重复的数字
/*
前序遍历第一位是根节点;
中序遍历中,根节点左边的是根节点的左子树,右边是根节点的右子树。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}。
首先,根节点 是{ 1 };
左子树是:前序{ 2,4,7 } ,中序{ 4,7,2 };
右子树是:前序{ 3,5,6,8 } ,中序{ 5,3,8,6 };
这时,如果我们把左子树和右子树分别作为新的二叉树,则可以求出其根节点,左子树和右子树。
*/
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if(pre==null||in==null){
return null;
}
TreeNode treeNode=reConstructBinaryTree(pre, in,0,pre.length-1,0,in.length-1);
return treeNode;
}
public TreeNode reConstructBinaryTree(int [] pre,int [] in,int preStart,int preEnd,int inStart,int inEnd) {
TreeNode tree=new TreeNode(pre[preStart]); //前序遍历的第一个是根节点,递归时把左子树和右子树分别作为新的二叉树
tree.left=null;
tree.right=null;
if(preStart==preEnd&&inStart==inEnd){ //说明已经是树叶节点
return tree;
}
int root;
for(root=inStart;root<inEnd;root++){ //寻找根节点在中序遍历中的下标
if(pre[preStart]==in[root]){
break;
}
}
int leftLength=root-inStart; //左子树的长度
int rightLength=inEnd-root; //右子树的长度
//把左子树和右子树分别作为新的二叉树,则可以求出其根节点,左子树和右子树。
if(leftLength>0){
tree.left=reConstructBinaryTree(pre,in,preStart+1,preStart+leftLength,inStart,root-1);
}
if(rightLength>0){
tree.right=reConstructBinaryTree(pre,in,preStart+1+leftLength,preEnd,root+1,inEnd);
}
return tree;
}
}
//建立二叉搜索树,左小右大
bool insertBST(BTreeNode* &Node,int element){
int data;
data =element;
if(Node){
if(element == Node->data){
return false;
} else{
//与Node的数据比较
if(element >Node->data){
return insertBST(Node->left,element);
} else{
return insertBST(Node->right,element);
}
}
} else{
Node = new BTreeNode;
Node->data = data;
return true;
}
}
//二叉搜索树查找
BTreeNode* BSTSearch(BTreeNode *Node,int data){
if(Node == NULL || Node->data == data){
return Node;
} else{
if(data > Node->data){
BSTSearch(Node->right,data);
} else{
BSTSearch(Node->left,data);
}
}
}
//二叉搜索树删除元素
bool deleteBST(BTreeNode* &Node,int data){
if(!Node){
return false;
}
if(data == Node->data){
//找到元素,删除元素,找到子树替换当前位置
deleteBSTNode(Node);
return true;
} else if(data > Node->data){
//元素在右子树
deleteBST(Node->right,data);
} else{
//元素在左子树
deleteBST(Node->left,data);
}
}
void deleteBSTNode(BTreeNode*& Node){
BTreeNode *node = Node;
//若有左子树,找左子树中最大的,或者右子树中最小的,替换当前节点
if(Node->left){
BTreeNode *left = Node->left;
//左子树的最右边子树的父节点
BTreeNode *Preer = Node->left;
while(left->right){
Preer = left;
left = left->right;
}
if(Preer != left){
//删除pererd的右叶子
left->left =Node->left;
Preer->right = NULL;
}
Node = left;
} else{
Node = Node->right;
}
delete node;
}
红黑树的旋转
#include<bits/stdc++.h>
using namespace std;
const int N = 1000;
int a[] = {1, 3, 5, 7, 9, 11};
int size = 6;
int tree[N] = {0};
//建立范围为a[start]~a[end]
void build(int a[], int tree[], int node/*当前节点*/, int start, int end){
//递归边界(即遇到叶子节点时)
if (start == end) {
//直接存储a数组中的值
tree[node] = a[start];
}
else {
//将建立的区间分成两半
int mid = (start + end) / 2;
int left = 2 * node + 1;//左子节点的下标
int right = 2 * node + 2;//右子节点的下标
//求出左子节点的值(即从节点left开始,建立范围为a[start]~a[mid])
build(a, tree, left, start, mid);
//求出右子节点的值(即从节点right开始,建立范围为a[start]~a[mid])
build(a, tree, right, mid+1, end);
//当前节点的职位左子节点的值加上右子节点的值
tree[node] = tree[left] + tree[right];
}
}
void update(int a[], int tree[], int node, int start, int end, int x, int val){
//找到a[x],修改值
if (start == end){
a[x] = val;
tree[node] = val;
}
else {
int mid = (start + end) / 2;
int left = 2 * node + 1;
int right = 2 * node + 2;
if (x >= start && x <= mid) {//如果x在左分支
update(a, tree, left, start, mid, x, val);
}
else {//如果x在右分支
update(a, tree, right, mid+1, end, x, val);
}
//向上更新值
tree[node] = tree[left] + tree[right];
}
}
//求a[L]~a[R]的区间和
int query(int a[], int tree[], int node, int start, int end, int L,int R){
//若目标区间与当时区间没有重叠,结束递归返回0
if (start > R || end < L){
return 0;
}
//若目标区间包含当时区间,直接返回节点值
else if (L <=start && end <= R){
return tree[node];
}
else {
int mid = (start + end) / 2;
int left = 2 * node + 1;
int right = 2 * node + 2;
//计算左边区间的值
int sum_left = query(a, tree, left, start, mid, L, R);
//计算右边区间的值
int sum_right = query(a, tree, right, mid+1, end, L, R);
//相加即为答案
return sum_left + sum_right;
}
}
int main(){
//从根节点(即节点0)开始建树,建树范围为a[0]~a[size-1]
build(a, tree, 0, 0, size-1);
for(int i = 0; i <= 14; i ++)
printf("tree[%d] = %d\n", i, tree[i]);
printf("\n");
//把a[x]改成6
update(a, tree, 0, 0, size-1, 4, 6);
for(int i = 0; i <= 14; i ++)
printf("tree[%d] = %d\n", i, tree[i]);
printf("\n");
//求区间[2,5]的和
int ans = query(a, tree, 0, 0, size-1, 2, 5);
printf("ans = %d", ans);
return 0;
}
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/138337.html原文链接:https://javaforall.cn