蓝桥杯常用树模板(C/C++)

目录

1  二叉树

2  二叉搜索树

3  最小生成树

3.1  Prim算法

3.2  Kruskal算法

4  AVL树(难) 

5  线段树(难)


1  二叉树

1:二叉树初始化

2:二叉树的创建

3:先序遍历

4:中序遍历

5:后序遍历

6:打印

#include <bits/stdc++.h>
using namespace std;

class BinaryTree//二叉树的初始化 
{
	public:
		char data;
		BinaryTree* left;
		BinaryTree* right;
};

void CreatBinaryTree(BinaryTree* &root)//二叉树的创建 
{
	char c;
	cin>>c;
	if(c=='#')  root=NULL;
	else
	{
		root=new BinaryTree;
		root->data=c;
		CreatBinaryTree(root->left);
		CreatBinaryTree(root->right);
	}
}

void Preorder(BinaryTree* root,vector<char> &path)//先序遍历 
{
	if(root!=NULL)
	{
		path.push_back(root->data);
		Preorder(root->left,path);
		Preorder(root->right,path);
	}
}

void Inorder(BinaryTree* root,vector<char> &path)//中序遍历 
{
	if(root!=NULL)
	{
		Preorder(root->left,path);
		path.push_back(root->data);
		Preorder(root->right,path);
	}
}

void Postorder(BinaryTree* root,vector<char> &path)//后序遍历 
{
	if(root!=NULL)
	{
		Preorder(root->left,path);
		Preorder(root->right,path);
		path.push_back(root->data);
	}
}

void PrintBinaryTree(vector<char> path)
{
	int n=path.size();
	for(int i=0;i<n;i++)
	{
		cout<<path[i]<<' '; 
	}
	cout<<endl;
}

int main()
{
	vector<char> path1,path2,path3;
	BinaryTree* root=NULL;
	CreatBinaryTree(root);
	Preorder(root,path1);
	PrintBinaryTree(path2);
	Inorder(root,path2);
	PrintBinaryTree(path2);
	Postorder(root,path3);
	PrintBinaryTree(path3);
	return 0;
}

2  二叉搜索树

1:创建结点

2:创建树

3:中序遍历

#include <bits/stdc++.h>
using namespace std;

struct Node
{
	int data;
	struct Node* left;
	struct Node* right;
};
typedef struct Node Node;

Node *CreatBSTree(Node* root,int num)
{
	if(root==NULL)
	{
		root=(Node*)malloc(sizeof(Node));
		if(root==NULL)
		{
			return NULL;
		}
		root->data=num;
		root->left=NULL;
		root->right=NULL;
	}
	else
	{
		if(root->data>num)  root->left=CreatBSTree(root->left,num);
		else  root->right=CreatBSTree(root->right,num);
	}
	return root;
}

void Inorder(Node *root)
{
	if(root==NULL) return;
	Inorder(root->left);
	cout<<root->data<<' ';
	Inorder(root->right);
}

int main()
{
	int i,num;
	Node* root=NULL;
	for(i=0;i<10;i++)
	{
		cin>>num;
		root=CreatBSTree(root,num);
	}
	Inorder(root);
	return 0; 
}
 

3  最小生成树

3.1  Prim算法

#include <bits/stdc++.h>
using namespace std;
int main()
{
	int points,edges,xiao;//points结点数   edges道路总数  xiao最小值 
	int edge[7][7];//欧氏距离
	int dist[7]; 
	bool flag[7];//记忆化 
	cin>>points>>edges;
	for(int i=1;i<=points;i++)//edge[][]的初始化及存储 
	{
		for(int j=1;j<=points;j++)
		{
			if(i==j) edge[i][j]=0;
			else  edge[i][j]=INT_MAX; 
		}
	}
	int p1,p2,w;
	for(int i=1;i<=edges;i++)
	{
		cin>>p1>>p2>>w;
		edge[p1][p2]=w;
		edge[p2][p1]=w;
	}
	for(int i=1;i<=points;i++)//初始化一号顶点到其他顶点的距离 
	{
		dist[i]=edge[1][i];
	}
	flag[1]=true;
	int cnt=1,j,sum;
	while(cnt<points)//边界是连接了所有的点 
	{
		xiao=INT_MAX;
		for(int i=1;i<=points;i++)
		{
			if(!flag[i]&&dist[i]<xiao)
			{
				xiao=dist[i];
				j=i;//记住连接了第几个点 
			}
		}
		flag[j]=true;
		cnt++;
		sum=sum+dist[j];
		for(int i=1;i<=points;i++)
		{
			if(!flag[i]&&dist[i]>edge[j][i])  dist[i]=edge[j][i];
		}
	} 
	cout<<sum;
	return 0;
}

3.2  Kruskal算法

#include <bits/stdc++.h>
using namespace std;

int fa[100000];
struct edge
{
	int u;//左端点 
	int v;//右端点 
	int dist;//距离 
}ed[100000];

bool cmp(edge a,edge b)
{
	return a.dist<b.dist;
}

void init(int n)
{
	for(int i=1;i<=n;i++)
	{
		fa[i]=i;
	}
}

int find(int x)
{
	if(x==fa[x])  return x;
	int temp=find(fa[x]);
	return temp;
}

int kruskal(int n,int m)
{
	int ans,cnt;
	for(int i=0;i<m;i++)
	{
		int fu=find(ed[i].u);
		int fv=find(ed[i].v);
		if(fu!=fv)
		{
			fa[fu]=fv;
			ans=ans+ed[i].dist;
			cnt++;
			if(cnt==n-1)  break;
		}
	}
	if(cnt!=n-1)  return -1;
	else  return ans;
}

int main()
{
	int n,m;
	cin>>n>>m;
	init(n);
	for(int i=0;i<m;i++)
	{
		cin>>ed[i].u>>ed[i].v>>ed[i].dist;
	}
	sort(ed,ed+m,cmp);
	cout<<kruskal(n,m);
	return 0;
}

如要详细了解各个算法的原理,请移步:图论(入门版)_菜只因C的博客-CSDN博客图论(入门版)https://blog.csdn.net/m0_71934846/article/details/128757672?spm=1001.2014.3001.5501

4  AVL树(难) 

#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <ctime>

using namespace std;

typedef struct Node {
    int value, h;
    struct Node *left, *right;
} Node;

Node __NIL;
#define NIL (&__NIL)
__attribute__((constructor))
void init_NIL() {
    NIL->value = -1;
    NIL->left = NIL->right = NIL;
    NIL->h = 0;
    return ;
}

Node *getNewNode(int value) {
    Node *p = (Node *)malloc(sizeof(Node));
    p->value = value;
    p->left = p->right = NIL;
    p->h = 1;
    return p;
}

void update_h(Node *root) {
    root->h = max(root->left->h, root->right->h) + 1;
    return ;
}
/// AVL树 核心部分/
//左旋,root为要旋转节点的父节点
Node *left_rotate(Node *root) {
    Node *tmp = root->right;//保存要左旋节点为根节点的节点
    root->right = tmp->left;//原先的根节点的右子节点存左旋节点的左节点,这样就不会出现三叉树了
    tmp->left = root;//如果调整右旋节点为根节点
    //更新树高
    update_h(root);
    update_h(tmp);
    return tmp;
}
//右旋
Node *right_rotate(Node *root) {
    Node *tmp = root->left;
    root->left = tmp->right;
    tmp->right = root;
    update_h(root);
    update_h(tmp);
    return tmp;
}

//判断失衡类型
Node *maitain(Node *root) {
    if (abs(root->left->h - root->right->h) <= 1) return root;
    if (root->left->h > root->right->h) {//左子树更高,失衡条件是L
        if (root->left->right->h > root->left->left->h) {
            root->left = left_rotate(root->left);//LR
        }
        root = right_rotate(root);//LL
    } else {
        //右子树更高,失衡条件是R
        if (root->right->left->h > root->right->right->h) {
            root->right = right_rotate(root->right);//RL
        }
        root = left_rotate(root);//RR
    }
    return root;
}


Node *insert(Node *root, int target) {
    if (root == NIL) return getNewNode(target);
    if (root->value == target) return root;
    if (root->value > target) {
        root->left = insert(root->left, target);
    } else {
        root->right = insert(root->right, target);
    }
    update_h(root);
    return maitain(root);//递归时判断失衡且调整
}

Node *get_pre(Node *root) {
    Node *tmp = root;
    while (tmp->right != NIL) {
        tmp = tmp->right;
    }
    return tmp;
}

Node *erase(Node *root, int target) {
    if (root == NIL) return root;
    if (root->value > target) {
        root->left = erase(root->left, target);
    } else if (root->value <target) {
        root->right = erase(root->right, target);
    } else {
        if (root->left == NIL && root->right == NIL) {
            free(root);
            return NIL;
        } else if (root->left == NIL || root->right == NIL) {
            Node *tmp = (root->left != NIL ? root->left : root->right);
            free(root);
            return tmp;
        } else {
            Node *tmp = get_pre(root->left);
            root->value = tmp->value;
            root->left = erase(root->left, tmp->value);
        }
    }
    update_h(root);
    return maitain(root);//递归时判断失衡且调整
}

void clear(Node *root) {
    if (root == NIL) return ;
    clear(root->left);
    clear(root->right);
    free(root);
    return ;
}

void out_put(Node *root) {
    if (root == NIL) return ;
    out_put(root->left);
    printf("%d(%d) | %d, %d\n", root->value, root->h, root->left->value, root->right->value);
    out_put(root->right);
    return ;
}

int main()
{
    srand(time(0));
    Node *root = NIL;
    int n = 5;
    
    for (int i = 0; i < n; i++) {
        int val = rand() % 100;
        printf("\n insert %d to BST: \n", val);
        root = insert(root, val);
        out_put(root);
    }
    clear(root);
    return 0;
}

5  线段树(难)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define Maxsize 1000001
#define ll long long
using namespace std;
int m,n,a[Maxsize];
struct node {
 int l;
 int r;
 ll sum;
 ll lazy;
}tree[Maxsize];
 
void push_up(int k){
 //根据k节点的两个孩子更新k节点
 tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum; 
} 
void build (int k,int l,int r){
 //初始化建树
// cout<<"build\n";
 tree[k].l=l;
 tree[k].r=r;
 tree[k].lazy=0;
 //cout<<"r: "<<tree[k].r<<" l: "<<tree[k].l<<" sum:"<<tree[k].sum<<endl;
 if(l==r){
  tree[k].sum=a[l];
  return ;//递归结束 
 } 
 int mid=(l+r)/2;
 build(2*k,l,mid);
 build(2*k+1,mid+1,r);
 push_up(k);
}
void push_down(int k,int l,int r){
 //判断当前节点k有无lazy标记,将lazy标记向左右孩子传递 
 if(tree[k].lazy){
  int mid=(l+r)/2;
  tree[k<<1].lazy+=tree[k].lazy;
  tree[k<<1|1].lazy+=tree[k].lazy;
  tree[k<<1].sum+=tree[k].lazy*(tree[k*2].r-tree[k*2].l+1);
  tree[k<<1|1].sum+=tree[k].lazy*(tree[k*2+1].r-tree[k*2+1].l+1);
  tree[k].lazy=0;
 }
}
void change (int k,int l,int r,int x){
 //区间更改,更改l[l~r]区间的数值+x
// cout<<endl<<"change"<<endl;
// cout<<"l:"<<tree[k].l<<" r:"<<tree[k].r<<endl;
 if(l<=tree[k].l&&tree[k].r<=r){
  tree[k].sum+=(long long)(tree[k].r-tree[k].l+1)*x;
  tree[k].lazy+=x;
//  cout<<" sum:"<<tree[k].sum<<endl;
  return ;
 } 
 push_down(k,tree[k].l,tree[k].r);
 int mid=(tree[k].l+tree[k].r)/2;
 if(l<=mid){
  change(2*k,l,r,x);
 }
 if(r>mid){
  change(2*k+1,l,r,x);
 }
 push_up(k);
//  cout<<" sum:"<<tree[k].sum<<endl;
}
ll query (int k,int l,int r){
 //当前节点位k,查询区间[l~r]
 if(l<=tree[k].l&&tree[k].r<=r){
  return tree[k].sum;
 } 
 push_down(k,l,r);//当前区间不满足,继续向下遍历
 //若进行单点修改不需要进行这一步,进行区间修改必须进行 
 ll res=0;
 int mid=(tree[k].l+tree[k].r)/2;
 if(l<=mid){
  res+=query(k*2,l,r);
 } 
 if(r>mid){
  res+=query(k*2+1,l,r);
 }
 return res;
}
void update(int k,int x,int temp){
 if(tree[k].r==tree[k].l){
  tree[k].sum=temp;
  return ;
 }
 int mid=(tree[k].l+tree[k].r)/2;
 if(x<=mid){
  update(2*k,x,temp);
 }
 else{
  update(2*k+1,x,temp);
 }
 push_up(k);
} 
int main (){
 scanf("%d %d",&m,&n);
 for(int i=1;i<=m;i++){
  scanf("%d",&a[i]);
 }
 build(1,1,m);
 for(int i=1;i<=n;i++){
  int choice;
  scanf("%d",&choice);
  if(choice==2){
   int l,r;
   scanf("%d %d",&l,&r);
   printf("%ld\n",query(1,l,r));
  }
  else{
   int l,r,t;
   scanf("%d %d %d",&l,&r,&t);
   change(1,l,r,t);
  }
//  cout<<"\ndi: "<<i<<endl;
//        for(int j=1;j<=n;j++){
//         cout<<tree[j].sum<<" "<<tree[j].lazy<<";";
//  } 
 }
 return 0;
}

  • 9
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜只因C

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值