uva122 二叉樹的實現和層次遍歷(bfs)
阿新 • • 發佈:2018-12-28
原型 null 內存泄漏 計算 內存溢出 遍歷 max 二叉樹的層次遍歷 構造函數
題目見紫書
6.3.2 二叉樹的層次遍歷
1.二叉樹的實現:
a.用指針實現:用結構體記錄結點,利用指針訪問結點
其中變量left,right的值 new的返回值都是地址
/*二叉樹的結點定義和操作*/ //結點類型 struct Node{ bool have_value; //是否被賦值過 int v; //結點值 Node *left,*right; Node():v(-1),have_value(false),left(NULL),right(NULL){}//構造函數};
Node* newnode(){return new Node()}; //申請新結點的函數
b.用數組實現:
計數器cnt為已存在的節點數(編號最大值),用編號代替地址訪問結點,用數組 [編號]來訪問節點,其中left[u],right[u]都是記錄的編號,結構體中的成員變量成了全局數組。
int newnode(){ int u=++cnt; left[u]=right[u]=0; have_value[root]=false; return u; }
其中指針是利用動態內存實現,需要一直申請新內存(new),為防止內存泄漏,需要釋放內存
Node* newnode(){return new Node()}; //申請新結點的函數
而數組是靜態內存實現,編程簡單,容易調試,不需釋放動態內存,只要重置結點計數器和根結點的左有子樹就行了.
可以用靜態數組配合空閑列表實現一個簡單的內存池,防止內存溢出(不太懂,先不學,以後再看,紫書154頁)
二叉樹的bfs要用隊列來實現
//二叉樹的bfs bool bfs(vector<int>& ans){ queue<Node*> q; ans.clear(); q.push(root);//初始時只有一個根結點 while(!q.empty()){ Node* u=q.front(); q.pop(); if(!u->have_value) return false; //有結點未被賦值,輸入有誤 ans.push_back(u->v); //增加到輸出序列的尾部 if(u->left!=NULL) q.push(u->left); //如果有左節點,放入隊列 if(u->right !=NULL) q.push(u->right);//如果有右結點,放入序列 } return true; //輸入正確 }
其他:
· 可以用new運算符申請空間並執行構造函數。如果返回值為NULL,說明空間不足,申請失敗。
· strchr
strchr是計算機編程語言的一個函數,原型為extern char *strchr(const char *s,char c),可以查找字符串s中首次出現字符c的位置。
指針實現如下:
註: u->v 其中u是結構指針;
任何指針都不能為空指針!包括結構指針 Node * root; 若無root=newnode(); root就是空指針,錯都不知道錯到哪了;
if(!strcmp(s,"()"))break;字符串比較就這樣比較
//二叉樹的動態實現與層次遍歷 //new和delete是運算符,沒有頭文件 #include<cstdio> #include<cstdlib> #include<cstring> #include<vector> #include<queue> using namespace std; const int maxn=256+10; bool failed; struct Node{ bool have_valued; int v; Node* left,*right; Node():have_valued(false),left(NULL),right(NULL){}; }; Node* root; // 此時root為空指針 Node* newnode(){return new Node;} bool addnode(int v,char* s){ Node* u=root; int n=strlen(s); for(int i=0;i<n;i++) if(s[i]==‘L‘){if(u->left==NULL)u->left=newnode(); u=u->left; } else if(s[i]==‘R‘){if(u->right==NULL)u->right=newnode(); u=u->right; } if(u->have_valued)failed=true; else u->v=v; u->have_valued=true; return true; } void remove(Node* u){ if(u==NULL)return; if(u->right!=NULL)remove(u->right); if(u->left!=NULL)remove(u->left); delete u; } char s[maxn]; bool input_read(){ failed = false; root = newnode(); int v; for(;;){ if(scanf("%s",s)!=1)return false; if(!strcmp(s,"()"))break; sscanf(&s[1],"%d",&v); addnode(v,strchr(s,‘,‘)+1); } return true; } bool bfs(vector<int>& ans){ ans.clear(); queue <Node* > q; Node* u=root; q.push(u); while(!q.empty()){ if(u->have_valued) ans.push_back(u->v); else return false; q.pop(); if(u->left!=NULL)q.push(u->left); if(u->right!=NULL)q.push(u->right); u=q.front(); } return true; } int main(){ vector <int> ans; while(input_read()){ if(!bfs(ans))failed=true; if(failed)printf("not complete\n"); else {for(int i=0;i<ans.size();i++){ if(i!=0)printf(" "); printf("%d",ans[i]); }printf("\n"); } } return 0; }
數組實現也差不多,用left【】right【】儲存指針域,跟鏈表似的:
//二叉樹的靜態(數組)實現與層次遍歷 #include<cstdio> #include<cstdlib> #include<cstring> #include<vector> #include<queue> using namespace std; const int maxn=256+10; const int root=1; bool failed; int cnt=1; int left[maxn]; int right[maxn]; int value[maxn]; bool have_value[maxn]; int newnode(){int u=++cnt;left[u]=0; right[u]=0;have_value[u]=false; return u;} bool addnode(int v,char* s){ int n=strlen(s),t=root; for(int i=0;i<n;i++){ if(s[i]==‘L‘){ if(left[t]==0)left[t]=newnode(); t=left[t]; } if(s[i]==‘R‘){ if(right[t]==0)right[t]=newnode(); t=right[t]; } } // printf("have value[%d]=%d\n",t,have_value[t]); if(have_value[t]==true)failed=true; else have_value[t]=true; value[t]=v; return true; } void newtree(){ //相當於動態裏newnode結構體拆開,因為是靜態數組,無需申請內存 cnt=root; right[root]=0; left[root]=0; have_value[root]=false; } char s[maxn]; bool input_read(){ failed = false; newtree(); int v; for(;;){ if(scanf("%s",s)!=1)return false; if(!strcmp(s,"()"))break; sscanf(&s[1],"%d",&v); //printf("%s\n",strchr(s,‘,‘)+1); addnode(v,strchr(s,‘,‘)+1); } return true; } bool bfs(vector<int>& ans){ ans.clear(); queue <int> qcnt; int u=1; qcnt.push(u); while(!qcnt.empty()){ u=qcnt.front();//printf("bfs-%d\n",u); if(have_value[u]==false){return false;} qcnt.pop(); ans.push_back(value[u]); if(left[u]!=0)qcnt.push(left[u]); if(right[u]!=0)qcnt.push(right[u]); } return true; } int main(){ memset(have_value,false,sizeof(have_value)); memset(left,0,sizeof(left)); memset(right,0,sizeof(right)); vector <int> ans; while(input_read()){ if(!bfs(ans))failed=true; if(failed)printf("not complete\n"); else {for(int i=0;i<ans.size();i++){ if(i!=0)printf(" "); printf("%d",ans[i]); }printf("\n"); } } return 0; }
uva122 二叉樹的實現和層次遍歷(bfs)