BST | 1064 完全二叉搜索树
生活随笔
收集整理的這篇文章主要介紹了
BST | 1064 完全二叉搜索树
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
OJ:https://www.patest.cn/contests/pat-a-practise/1064
(一)23分(3個case未過)代碼
建樹的規律是我瞎猜的。首先用樣例數據分析。
10 1 2 3 4 5 6 7 8 9 0對數據排序后:
0 1 2 3 4 5 6 7 8 9
有10個數據,因為是完全二叉樹,底層應該有3個葉子,上層有1+2+4=7個結點。用以下代碼計算:
int up_num=1,t=1;while(up_num + t*2 < n){t*=2;up_num+=t;}int leaves_num=n-up_num;0 1 2 ?| ?3 4 5 6 7 8 9
將左側葉子結點分割開,對右側結點進行分析。
6就是根結點。計算方式是取中間。這個算法中所有的“取中間”都滿足以下規律:
奇數個數:直接取中間
偶數個數:取中間靠右
定義以下函數計算:
int get_mid(int a,int b){if((a+b)%2){return (a+b)/2+1;}return (a+b)/2; }6就是從3到9取中間而來。之后就可以遞歸建樹了。
6的左葉子是0到5取中間的3。
6的右葉子是7到9取中間的8。
……
23分代碼:
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map>#define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 1010 #define MAX (1<<30)-1 #define V vector<int>using namespace std;int a[LEN]; int n;typedef struct Node{int d;struct Node* l=NULL;struct Node* r=NULL;Node(int d=0):d(d){} };int get_mid(int a,int b){if((a+b)%2){return (a+b)/2+1;}return (a+b)/2; }Node * build_tree(int s,int e) {if(e<s) return NULL;if(e==s) return new Node(a[s]);int t=get_mid(s,e);Node *node=new Node(a[t]);node->l=build_tree(s,t-1);node->r=build_tree(t+1,e);return node; }int main(){ // freopen("1064.txt","r",stdin);I("%d",&n);int i;FF(i,n) I("%d",&a[i]);sort(a,a+n);int up_num=1,t=1;while(up_num + t*2 < n){t*=2;up_num+=t;}int leaves_num=n-up_num;int root_i=get_mid(leaves_num,n-1);Node *root=new Node(a[root_i]);root->l=build_tree(0,root_i-1);root->r=build_tree(root_i+1,n-1);queue<Node*> q;q.push(root);int cnt=0;while(!q.empty()){Node* tmp=q.front();q.pop();cnt++;O("%d",tmp->d);if(cnt<n)O(" ");if(tmp->l)q.push(tmp->l);if(tmp->r)q.push(tmp->r);}return 0; }?
?
看了大佬的博客之后,才知道自己是多么naive。這題其實很簡單,利用BST的性質:中序遍歷的序列遞增有序,再用dfs(其實深搜的本質就是中序遍歷)和一個二叉堆來遞歸建樹。最后都不用隊列來模擬層序,直接把二叉堆依次輸出就可以了。
AC代碼:
#include <stdio.h> #include <memory.h> #include <math.h> #include <string> #include <vector> #include <set> #include <stack> #include <queue> #include <algorithm> #include <map>#define I scanf #define OL puts #define O printf #define F(a,b,c) for(a=b;a<c;a++) #define FF(a,b) for(a=0;a<b;a++) #define FG(a,b) for(a=b-1;a>=0;a--) #define LEN 10010 #define MAX 0x06FFFFFF #define V vector<int>using namespace std;int n; int a[LEN] ,ans[LEN]; int p=-1; //p是中序遍歷序列的索引,初始化為-1,因為在操作中首先會被+1而變成0 void dfs(int x){ //x是二叉堆(完全二叉樹)的索引,根節點是0,葉子節點滿足二倍關系 if(x>=n){ //超出界限p++; //進行了一輪超出界限的操作,意味著操作序列的更新 return; //記得退出,不然會爆棧。找到目標解或者到了遞歸邊界而退出是dfs的必須操作 }dfs(x*2+1); //左子樹遞歸 ans[x]=a[p]; //ans數組就是二叉堆,a是中序遍歷序列。 dfs(x*2+2); //右子樹遞歸 }int main(){ // freopen("D:\\input\\A1064.txt","r",stdin);I("%d",&n);int i;FF(i,n) I("%d",&a[i]);sort(a,a+n);dfs(0);FF(i,n){O("%d",ans[i]);if(i!=n-1) O(" ");}return 0; }?
轉載于:https://www.cnblogs.com/TQCAI/p/8530913.html
總結
以上是生活随笔為你收集整理的BST | 1064 完全二叉搜索树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jquery地址栏链接与a标签链接匹配添
- 下一篇: webpack前言:前端模块系统的演进