【資料結構高分筆記題目整理】
【題意】
如上所示,由正整數1,2,3……組成了一顆特殊二叉樹。我們已知這個二叉樹的最後一個結點是n。現在的問題是,結點m所在的子樹中一共包括多少個結點。
比如,n = 12,m = 3那麼上圖中的結點13,14,15以及後面的結點都是不存在的,結點m所在子樹中包括的結點有3,6,7,12,因此結點m的所在子樹中共有4個結點。
【解題思路】
用l和r分別儲存這個結點下一層的最左和最右結點,每一層結點的數目都是上一層*2,所以用cnt記數,當r大於等於n時跳出迴圈,說明現在已經到達所需的結點的那一層,即原結點數+所需結點-最左結點+1即為最後的結點數。
【程式碼】
#include<bits/stdc++.h> using namespace std; int main() { int n,m; while(~scanf("%d%d",&m,&n) && n || m) { int ans=1,l=2*m,r=2*m+1,cnt=1; while(r<n) { cnt=cnt*2; ans+=cnt; l=l*2; r=r*2+1; } if(l<=n)ans+=n-l+1; printf("%d\n",ans); } return 0; }
【題意】
給定一棵二叉樹的前序遍歷和中序遍歷,求其後序遍歷(提示:給定前序遍歷與中序遍歷能夠唯一確定後序遍歷)。
【解題思路】
root為當前子樹的根結點在前序pre中的下標,left和rigtht為當前子樹的最左邊和最右邊的結點在中序in中的下標。用i找到當前子樹的根結點root在中序中的下標,然後左邊和右邊就分別為當前根結點root的左子樹和右子樹,然後遞迴實現。
【程式碼】
#include<bits/stdc++.h> using namespace std; char pre[30],in[30]; int n; vector<char>v; void dfs(int root,int left,int right) { if(left>right)return; int i=left; while(pre[root]!=in[i])i++; if(i>n)return; dfs(root+1,left,i-1); dfs(root+1+i-left,i+1,right); v.push_back(pre[root]); } int main() { while(~scanf("%s%s",pre,in)) { n=strlen(pre)-1; dfs(0,0,n); for(int i=0;i<v.size();i++) printf("%c",v[i]); printf("\n"); memset(pre,0,sizeof(pre)); memset(in,0,sizeof(in)); v.clear(); } return 0; }
【題意】
有一棵樹,輸出某一深度的所有節點,有則輸出這些節點,無則輸出EMPTY。該樹是完全二叉樹。
【程式碼】
這題被自己蠢哭qaq題目還是簡單的辣
1.注意是完全二叉樹不是滿二叉樹,所以最後一層的葉子節點數不一定是滿的,在輸出節點時需要加上條件i<=n
2.因為完全二叉樹的最大高度h為log2(n)向下取整+1,所以只需判斷m和h的大小即可
【解題思路】
#include<bits/stdc++.h> using namespace std; const int maxn=1005; int a[maxn]; int main() { int n,m; while(~scanf("%d",&n) && n) { for(int i=1;i<=n;i++) scanf("%d",&a[i]); scanf("%d",&m); int h=floor(log(n)/log(2))+1; if(m>h)printf("EMPTY\n"); else { int l=pow(2,m-1),r=pow(2,m); printf("%d",a[l]); for(int i=l+1;i<r && i<=n;i++) printf(" %d",a[i]); printf("\n"); } } return 0; }
【題意】
輸入一系列整數,建立二叉排序樹,並進行前序,中序,後序遍歷。
【解題思路】
模板題,注意一下輸出即可。
【程式碼】
#include<bits/stdc++.h>
using namespace std;
typedef struct Node
{
int data;
struct Node* left,*right;
}Node,*PNode;
PNode insertBST(PNode root,int x)
{
if(root==NULL)
{
root=new Node();
root->data=x;
root->left=NULL;
root->right=NULL;
return root;
}
else if(x<root->data)
root->left=insertBST(root->left,x);
else if(x>root->data)
root->right=insertBST(root->right,x);
return root;
}
void preorder(PNode root)
{
if(root==NULL)return;
printf("%d ",root->data);
preorder(root->left);
preorder(root->right);
}
void inorder(PNode root)
{
if(root==NULL)return;
inorder(root->left);
printf("%d ",root->data);
inorder(root->right);
}
void postorder(PNode root)
{
if(root==NULL)return;
postorder(root->left);
postorder(root->right);
printf("%d ",root->data);
}
PNode findMax(PNode root)
{
if(root!=NULL) //非遞迴查詢
while(root->right!=NULL)
root=root->right;
return root;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
PNode root=NULL;
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
root=insertBST(root,x);
}
preorder(root);
printf("\n");
inorder(root);
printf("\n");
postorder(root);
printf("\n");
}
return 0;
}
【題意】
判斷兩序列是否為同一二叉搜尋樹序列。
【解題思路】
只需判斷兩棵樹的前序遍歷序列是否相同即可。
【程式碼】
#include<bits/stdc++.h>
using namespace std;
vector<int>a,b;
typedef struct Node
{
int val;
struct Node *left,*right;
}Node,*BNode;
BNode insertnode(BNode root,int x)
{
if(root==NULL)
{
root=new Node();
root->val=x;
root->left=root->right=NULL;
return root;
}
if(x<root->val)
root->left=insertnode(root->left,x);
else if(x>root->val)
root->right=insertnode(root->right,x);
return root;
}
void preorder(BNode root,int flag)
{
if(root==NULL)return;
if(flag)a.push_back(root->val);
else b.push_back(root->val);
preorder(root->left,flag);
preorder(root->right,flag);
}
int main()
{
int n;
string s;
while(~scanf("%d",&n) && n)
{
a.clear();
cin>>s;
BNode root=NULL;
for(int i=0;i<s.size();i++)
root=insertnode(root,s[i]-'0');
preorder(root,1);
for(int i=0;i<n;i++)
{
cin>>s;
b.clear();
BNode root2=NULL;
for(int i=0;i<s.size();i++)
root2=insertnode(root2,s[i]-'0');
preorder(root2,0);
if(a==b)printf("YES\n");
else printf("NO\n");
}
}
return 0;
}