完全二杈树的层次序遍历 树的遍历通常是从父结点到子结点或子结点到父结点的顺序(前序,后序,中序),如果要实现同一层的所有元素用一般的方法要用堆栈来做,而且实现非常复杂。这里提供一种特别的遍历方法。 我们先按从上到下从左到右的顺序给二杈树的元素编号:第一层的一个元素编1号,第二层左边第一个编2号,第二个编3号,第三层左边第一个编1号,第二个编2号,第三个编3号第四个编4号……大致情况如下: 1 2,3 4,5,6,7 8,9,10,11,12,13,14,15 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 …… 从后的情形很清楚了,只要能知道第几个元素在哪很容易就能实现层次序的遍历。我们现在关注的是如何能知道24号在哪很快就能找到它? 我才用了如下方法,将编号除以2的余数是1还是0来确定它在父结点的左边还是右边,余数是1在右点是0在左边,再将商除以2看余数。如此循环直到结果等于1为止。我用vector将每次的结果保存起来,以make_path函数来实现。 int make_path(int index) {
serial.clear(); int t = index; while ( t != 1) { if( t % 2 == 0) { serial.push_back(t % 2); } else { serial.push_back(t % 2); t--; } t/=2; }
return 0;
} 思路很简单,就是把编号除以二把余数存入serial中 它的定义如下: vector<int> serial; 再跟据生成的路径寻找到指定原素: int go_to(int index) { pcurrent= root; if(index == 1) return 0; make_path(index); for( vector<int>::reverse_iterator iter = serial.rbegin(); iter != serial.rend(); iter ++) { if(*iter) { pcurrent = pcurrent->right; } else { pcurrent = pcurrent->left; } } return 0; } 如果serial中是0就访问他的左结点,否则就是右结点。Pccurrent是访问的当前节点的指针。 下面是插入算法,值得它是个和go_to想似的算法,不同就是如果即将访问的子节点的指针是NULL的话即认为找到,插入。还有就是当树为空时的插入。 int insert(T data) { pcurrent = root; if(root) { make_path(m_count+1); for( vector<int>::reverse_iterator iter = serial.rbegin(); iter != serial.rend(); iter ++) { if(!*iter) { if(pcurrent->left) pcurrent = pcurrent->left; else { pcurrent->left = new Node<T>(data,pcurrent); break; } } else { if(pcurrent->right) pcurrent = pcurrent->right; else { pcurrent->right = new Node<T>(data,pcurrent); break; } } } } else { root = new Node<T>(data); } m_count ++; return m_count ;
} T是用模版定义的一个类型参数,用它来实现算法的数据无关性。 下面遍厉就很简单了: for( int i = 1; i <= tree.m_count ; i++) { cout << tree[i] ; if( i+1 == pow(2,c)) { cout << endl; c++; } else cout << ","; } if是为了考虑换行,因为每一行的第一个是2的c次方所以如果打印的是2的c次方减1的话换行。 下面是完整的原代码: // bintree.cpp : 定义控制台应用程序的入口点。 //
#include "stdafx.h" #include "iostream" #include "vector" #include "conio.h" #include "cmath"
using namespace std; template<class T> class Node { private: Node(); public: T data; Node *left; Node *right; Node *parent; Node(int n):left(NULL),right(NULL),parent(NULL),data(n) { } Node(int n,Node *p):left(NULL),right(NULL),parent(p),data(n) { } operator=(const int &n) { data = n; } Node &operator=(const Node &n) { data = n.data; return *this; } bool operator>(const Node &n) { return data > n.data; } };
template<class T> class Tree { public: Node<T> *root; Node<T> *pcurrent; vector<int> serial; int m_count;
Tree():root(NULL),pcurrent(NULL),m_count(0) { } ~Tree() { remove(); } int go_to(int index) { pcurrent= root; if(index == 1) return 0; make_path(index); for( vector<int>::reverse_iterator iter = serial.rbegin(); iter != serial.rend(); iter ++) { if(*iter) { pcurrent = pcurrent->right; } else { pcurrent = pcurrent->left; } } return 0; } T operator[](int index) { go_to(index); return pcurrent->data;
} int insert(T data) { pcurrent = root; if(root) { make_path(m_count+1); for( vector<int>::reverse_iterator iter = serial.rbegin(); iter != serial.rend(); iter ++) { if(!*iter) { if(pcurrent->left) pcurrent = pcurrent->left; else { pcurrent->left = new Node<T>(data,pcurrent); break; } } else { if(pcurrent->right) pcurrent = pcurrent->right; else { pcurrent->right = new Node<T>(data,pcurrent); break; } } } } else { root = new Node<T>(data); } m_count ++; return m_count ;
} int remove() { rec_del(root); m_count=0; return 0;
} int rec_del( Node<T>* &p) { if(!p) return 1; if(p->left) rec_del(p->left); if(p->right) rec_del(p->right); delete p; p = NULL; return 0;
} int sort( Node<T> *p) { Node<T> t(p->data); if(p->parent) { if(*p > *p->parent) { *p = *p->parent; *p->parent = t; } } return 0; } int sort(int index) { go_to(index); sort(pcurrent); return 0;
} int make_path(int index) {
serial.clear(); int t = index; while ( t != 1) { if( t % 2 == 0) { serial.push_back(t % 2); } else { serial.push_back(t % 2); t--; } t/=2; }
return 0;
}
}; int _tmain(int argc, _TCHAR* argv[]) { int n; int in; Tree<int> tree; cin >> n; tree.remove(); for( int i = 1; i <= n ; i ++) { cin >> in; tree.insert(in); } int layer = 1; for( int i = n; i > 0; i--) { tree.sort(i); } int c= 1; for( int i = 1; i <= tree.m_count ; i++) { cout << tree[i] ; if( i+1 == pow(2,c)) { cout << endl; c++; } else cout << ","; }
getch();
return 0; }
编译平台: windows xp sp2,VC++2003
|