1. 二叉树的中序遍历非递归实现
- void InOrderTraverse1(BiTree T) // 中序遍历的非递归
- {
- if(!T)
- return ;
- BiTree curr = T; // 指向当前要检查的节点
- stack<BiTree> s;
- while(curr != NULL || !s.empty())
- {
- while(curr != NULL)
- {
- s.push(curr);
- curr = curr->lchild;
- }
- if(!s.empty()) //当节点没有左儿子时,开始输出当前节点,同时将当前即当前节点更新为右儿子
- {
- curr = s.top();
- s.pop();
- cout<<curr->data<<” “;
- curr = curr->rchild;
- }
- }
- }
顺便补充下前序和后序遍历:
- void PreOrder_Nonrecursive(BiTree T) //先序遍历的非递归
- {
- if(!T)
- return ;
- stack<BiTree> s;
- s.push(T);
- while(!s.empty())
- {
- BiTree temp = s.top();
- cout<<temp->data<<” “;
- s.pop();
- if(temp->rchild) //右儿子先进栈
- s.push(temp->rchild);
- if(temp->lchild)
- s.push(temp->lchild);
- }
- //双栈法(后序是左——右——根,利用栈反下就是根——右——左,和前序遍历相似)
- void PostOrder_Nonrecursive(BiTree T) // 后序遍历的非递归
- {
- stack<BiTree> s1 , s2;
- BiTree curr ; // 指向当前要检查的节点
- s1.push(T);
- while(!s1.empty()) // 栈空时结束
- {
- curr = s1.top();
- s1.pop();
- s2.push(curr);
- if(curr->lchild) //由于s2负责输出,所以先左儿子进栈
- s1.push(curr->lchild);
- if(curr->rchild)
- s1.push(curr->rchild);
- }
- while(!s2.empty())
- {
- printf(“%c “, s2.top()->data);
- s2.pop();
- }
- }
2. 输入N,输出是1~N的全排列,非递归实现
基本思想是:
1.对初始队列进行排序,找到所有排列中最小的一个排列Pmin(1,2,3, … ,N)。
2.找到刚刚好比Pmin大比其它都小的排列P(min+1)。
3.循环执行第二步,直到找到一个最大的排列,算法结束。
如排列123456,这是所有排列中最小的一个排列,刚好比ABCDE大的排列是:123465。
算法如下:
给定已知序列P = (A1,A2,A3,…..,An)
对P按字典排序,得到P的一个最小排列Pmin = A1A2A3….An ,满足Ai > A(i-1) (1 < i <= n)
从Pmin开始,找到刚好比Pmin大的一个排列P(min+1),再找到刚好比P(min+1)大的一个排列,如此重复。具体方法如下:
1.从后向前(即从An->A1),找到第一对为升序的相邻元素,即Ai < A(i+1)。若找不到这样的Ai,说明已经找到最后一个全排列,可以返回了。
2.从后向前,找到第一个比Ai大的数Aj,交换Ai和Aj。
3.将排列中A(i+1)A(i+2)….An这个序列的数逆序倒置,即An…..A(i+2)A(i+1)。因为由前面第1、2可以得知,A(i+1)>=A(i+2)>=…..>=An,这为一个升序序列,应将该序列逆序倒置,所得到的新排列才刚刚好比上个排列大。
4.重复步骤1-3,直到返回。
举例如下:
当序列为162543,找到第一对逆序数为<2,5>,Ai=2;而第一个大于2的数为Aj=3,两者交换后序列为163542;将<542>倒置,序列为163245,刚好大于原序列。
- //将数组a中的下标i到下标j之间的所有元素逆序倒置
- void reverse(int a[],int i,int j)
- {
- for(; i<j; ++i,–j) {
- swap(a,i,j);
- }
- }
-
- //将数组中所以元素按序输出
- void print(int a[],int length)
- {
- for(int i=0; i<length; ++i)
- cout<<a[i]<<” “;
- cout<<endl;
- }
- //求取全排列,打印结果,可令a[]为[1,2,3,…,N],length=N
- void combination(int a[],int length)
- {
- if(length<2) return;
- bool end=false;
- while(true) {
- print(a,length); //输出数组a
- int i,j;
- for(i=length-2; i>=0; –i) { //找到不符合趋势的元素的下标i,即首次满足Ai<Ai+1
- if(a[i]<a[i+1]) break;
- else if(i==0) return; //找到最大的排列
- }
- for(j=length-1; j>i; –j) { //从后到前找到第一个满足Aj>Ai
- if(a[j]>a[i]) break;
- }
- swap(a,i,j); //交换Ai和Aj
- reverse(a,i+1,length-1); //转置Ai+1,…,An
- }
- }
补充下全排列的递归解法:
(A、B、C、D)的全排列为:(1)A后面跟(B、C、D)的全排列;(2)B后面跟(A、C、D)的全排列;(3)C后面跟(A、B、D)的全排列;(4)D后面跟(A、B、C)的全排列。
- template<typename T>
- void permutation(T array[], int begin, int end)
- {
- int i;
- if(begin == end){
- for(i = 0; i <= end; ++i){
- cout<<array[i]<<” “;
- }
- cout<<endl;
- return;
- } else {
- //for循环遍历该排列中第一个位置的所有可能情况
- for(i = begin; i <= end; ++i) {
- swap(array[i], array[begin]);
- permutation(array, begin + 1, end);
- swap(array[i], array[begin]);
- }
- }
- }