廣度優先遍歷(BFS)例題
阿新 • • 發佈:2018-12-15
二叉樹的層次遍歷 UVa122
題目:
一、輸入資料的處理:
此處兩次用到的c語言字串的靈活性——可以把任何指向字元的指標看成一個字串,從該位置開始直到‘\0’結束的字串。例如,若讀到的字串節點是“(11,LL)”,則‘&s[1]’代表的含義是字串“11,LL)”。函式strchr(s,’,’)返回字串中從左往右第一個‘,’字元的指標,因此strchr(s,’,’)所對應的字串為“LL)”。這樣實際呼叫的是addnode(11,”LL”)。
二、二叉樹基本結構的定義:
struct Node{ bool have_value; int v; Node* left, *right; Node():have_value(false),left(NULL),right(NULL){} };
三、新增節點操作
四、層序遍歷(BFS)、
五、遞迴釋放二叉樹(防止記憶體洩漏)
最後貼上完整程式原始碼:
#include <iostream> #include <cstdlib> #include <cstring> #include <vector> #include <queue> using namespace std; //樹結點 struct Node{ int v ; Node* left,*right ; int have_value ; Node():have_value(false),left(NULL),right(NULL){} ; } ; Node* root ;//根節點 Node* newnode(){ return new Node() ; //返回一個新結點 } bool failed ; void addnode(int v,char* s){//新增新結點 int n = strlen(s); Node* u = root ; 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_value) failed = true ;//是否已經被訪問過; u->v = v; u->have_value = true; } void freetree(Node* u){ //釋放記憶體 if(u == NULL) return ; freetree(u->left); freetree(u->right); delete u; } char s[1005]; bool read_input(){ failed = false ; freetree(root) ; root = newnode(); while(true){ if(scanf("%s", s) != 1) return false; if(!strcmp(s,"()")) break; int v ; sscanf(&s[1],"%d",&v); addnode(v,strchr(s,',')+1); } return true ; } 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 ; } int main(int argc, char *argv[]) { vector<int> ans; while(read_input()){ if(!bfs(ans)) failed = 1; if(failed) printf("not complete\n"); else{ for(int i = 0;i < ans.size();i++) { if(i != 0) cout << " " ; cout << ans[i]; } cout << endl ; } } return 0; }
上面的程式碼寫的比我的好些,但還是習慣性貼上自己的程式碼:
#include<iostream> #include<string> #include<queue> #include<vector> using namespace std; struct node//構造樹的節點,下面的建構函式是非常好的 { bool value; int v; node *left; node *right; node():value(false),v(0),left(NULL),right(NULL){} }; node *root=new node;//建立一個根節點,便於建立和遍歷 //一定要開闢空間 int v; string com_s; /* void print(node *u) { cout<<endl<<u->value; cout<<" "<<u->v; if(u->left) cout<<" "<<"left exit"; if(u->right) cout<<" "<<"right exit"; } */ void extract(string &in_s)//提取命令 { int i; v=0; com_s.clear();//清空是clear,不是empty()。大爺的,查這麼長時間查不出 for(i=1;isdigit(in_s[i]);i++)//s[0]為( v=v*10+(in_s[i]-'0'); //跳出迴圈時,讀取的是,的位置 i++; for(i;in_s[i]!=')';i++) com_s.push_back(in_s[i]); } void creat_node() { node *u=root; for(int i=0;com_s[i];i++) { if(com_s[i]=='L') { if(u->left==NULL) u->left=new node; u=u->left; } else if(com_s[i]=='R')//如果右子樹的空間已經存在 { if(u->right==NULL) u->right=new node; u=u->right; } } u->v=v; if(!u->value) u->value=true; } bool bfs(vector<int> &ans) { ans.clear(); queue<node*> q; q.push(root); while(!q.empty()) { node* u=q.front(); if(!u->value) return false; ans.push_back(u->v); //print(u); q.pop(); if(u->left) q.push(u->left); if(u->right) q.push(u->right); } return true; } void remove_tree(node *u) { if(u==NULL) return; remove_tree(u->left); remove_tree(u->right); delete u; } int main() { string in_s; vector<int> ans; /*輸入資訊,建立樹*/ while(cin>>in_s) { if(in_s=="()") break; extract(in_s);//從中提取命令放入v和com_s中 // cout<<v; //cout<<com_s; creat_node();//建立節點,生成樹 //system("pause"); } /*廣度遍歷樹*/ if(bfs(ans)) { int n=ans.size(); for(int i=0;i<n;i++) cout<<ans[i]<<" "; } else cout<<-1; remove_tree(root); return 0; }