| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 784 人关注过本帖
标题:还是汉诺塔的问题
只看楼主 加入收藏
mfkblue
Rank: 5Rank: 5
等 级:职业侠客
帖 子:472
专家分:343
注 册:2008-12-21
结帖率:96.25%
收藏
已结贴  问题点数:20 回复次数:9 
还是汉诺塔的问题
书上例题用Stack这个堆栈类来保存每次移动后三个塔内里的情况,但没写出显示出来的代码。
我记得原来论坛里有人做了一个汉诺塔的游戏,不知道他用的是不是堆栈,保存搜没搜出来。
我尝试写出每次移动后输出塔内里情况,按下面的例子,用5调用TowersOfHanoi第一的输出应该为:
**
***
****
*****
因为第一个塔就出错了,所以来不及考虑其它两个塔的输出,不过暂时也没有思路,在同一排同时输出三个塔里的情况。
我写的输出代码 输出了两次1塔里的情况,也就是移动的第三次出错,不知道是错在哪里了.
去掉输出,运行是不会出错的.
#include <iostream.h>
class NoMem
{
public:
    NoMem(){}
};
void OutOfBounds()
{
    throw NoMem();
}
template <class T>
class Stack
{
    public:
        Stack(int MaxStackSize=10);
        ~Stack(){delete []stack;}
        bool IsEmpty()const {return top==-1;}
        bool IsFull()const {return top==MaxTop;}
        T Top()const;
        Stack<T>& Add(const T& x);
        Stack<T>& Delete(T& x);
        int Length(){return top+1;}
        void Output(ostream& out) const;
        Stack<T>& Divide(Stack<T>& x);
        Stack<T>& Merge(Stack<T>& x);
        friend istream& operator>>(istream& in,Stack<T>& x);
    private:
        int top;
        int MaxTop;
        T *stack;
  
};
template <class T>
Stack<T>& Stack<T>::Merge(Stack<T>& x)
{
    int n=top+x.top+2;
    if (MaxTop<n)
    {
        delete []stack;
        stack=new T[n];
    }
    int xi=0;
    for(int i=top+1;i<n;i++)
    {
        stack[i]=x.stack[xi++];
        top++;
    }
    delete []x.stack;
    x.stack=new T[20];
    x.top=-1;
    return *this;
}
template <class T>
Stack<T>& Stack<T>::Divide(Stack<T>& x)
{
    int n=x.top+1;
    for(int i=0;i<n/2;i++)
        {
        stack[i]=x.stack[i];
        top++;
        }
    x.top=0;
    for( ;i<n;i++)
        {
            x.stack[x.top++]=x.stack[i];
        }
    x.top--;
    return *this;
}
template <class T>
istream& operator>>(istream& in,Stack<T>& x)
{
    T t;
    cin>>t;
    x.Add(t);
    return in;
}
template <class T>
void Stack<T>::Output(ostream& out) const
{
    int n=top+1;
    for(int i=0;i<n;i++)
        out<<stack[i] ;
    cout<<endl;
}
template <class T>
ostream& operator<<(ostream& out,Stack<T>& x)
{
    x.Output(out);
    return out;
}
template <class T>
Stack<T>::Stack(int MaxStackSize)
{
    MaxTop=MaxStackSize-1;
    stack=new T[MaxStackSize];
    top=-1;
}
template <class T>
T Stack<T>::Top()const
{
    if(IsEmpty()) throw OutOfBounds();
    else return stack[top];
}
template <class T>
Stack<T>& Stack<T>::Add(const T& x)
{
 
    stack[++top]=x;
    return *this;
}
template <class T>
Stack<T>& Stack<T>::Delete(T& x)
{
    if(IsEmpty()) throw OutOfBounds();
    x=stack[top--];
    return *this;
}
void TowersOfHanoi(int);
class Hanoi
{
    friend void TowersOfHanoi(int);
public:
    void TowerOfHanoi(int n,int x,int y,int z);
private:
    Stack<int> *S[4];
};
void Hanoi::TowerOfHanoi(int n,int x,int y,int z)
{
    int d;
    if(n>0)
    {
        TowerOfHanoi(n-1,x,z,y);
        S[x]->Delete(d);
        S[y]->Add(d);
     
        int l=S[x]->Length();//    从这里
        int t=S[x]->Top();
        for(int i=0;i<l;i++)
        {
            for(int j=0;j<t;j++)
                cout<<"*";
            cout<<endl;
            t++;
        }
        cout<<endl;
                             //           到这里是我写的输入代码,如果去掉运行还是蛮正常
        TowerOfHanoi(n-1,z,y,x);
    }
}
void TowersOfHanoi(int n)
{
    Hanoi X;
    X.S[1]=new Stack<int> (n);
    X.S[2]=new Stack<int> (n);
    X.S[3]=new Stack<int> (n);
    for(int d=n;d>0;d--)
        X.S[1]->Add(d);
    X.TowerOfHanoi(n,1,2,3);
}
void main()
{
    TowersOfHanoi(5);
}

[ 本帖最后由 mfkblue 于 2009-9-3 00:27 编辑 ]
搜索更多相关主题的帖子: 汉诺塔 
2009-09-03 00:24
xufen340
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
帖 子:166
专家分:1351
注 册:2009-8-7
收藏
得分:20 
//你写的stack太复杂,我简化一下了,结果可以在当前目录out.txt察看。
#include <fstream>
#include <vector>
#include <iostream>
using namespace std;
/*stack*/
ofstream fout("out.txt");
template<typename T>
class stack{
    private:
        vector<T> elems;
    public:
        void push(T const&);
        void pop();
        T top() const;
        bool empty() const{
            return elems.empty();
        };
        vector<T>& getelems(){ return this->elems;};
        friend ostream& operator<<(ostream& out,stack<T>& x);
};

template <class T>
ostream& operator<<(ostream& out,stack<T>& x)
{
    for(int i=0;i<x.getelems().size();i++){
        out<<x.getelems()[i];
        out<<endl;
    }
    return out;
}


template<typename T>
void stack<T>::push(T const& elem)
{
    elems.push_back(elem);
}

template<typename T>
void stack<T>::pop()
{
    if(elems.empty()){
        throw out_of_range("stack<>::pop():empty stack");
    }
    elems.pop_back();
}

template<typename T>
T stack<T>::top() const
{
    if(elems.empty()){
        throw out_of_range("stack<>::top():empty stack");
    }
    return elems.back();
}

/*判断x,y, 更改3个stack*/
void Move(int n,char x,char y,stack<int>& stack1,stack<int>& stack2,stack<int>& stack3)
{
  fout<<"把"<<n<<"号从"<<x<<"挪动到"<<y<<endl;
  switch(x){
      case 'a':
          stack1.pop();
          break;
      case 'b':
          stack2.pop();
          break;
      case 'c':
          stack3.pop();
          break;
  }
   switch(y){
       case 'a':
          stack1.push(n);
          break;
       case 'b':
          stack2.push(n);
          break;
       case 'c':
          stack3.push(n);
          break;
  }
   fout<<"第一个塔:"<<endl<<stack1<<endl;
   fout<<"第二个塔:"<<endl<<stack2;
   fout<<"第三个塔:"<<endl<<stack3<<endl;
}
  
  
      
void Hannoi(int n,char a,char b,char c,stack<int>& stack1,stack<int>& stack2,stack<int>& stack3)
{
    if(n==1)
              Move(1,a,c,stack1,stack2,stack3);
    else
    {
          Hannoi(n-1,a,c,b,stack1,stack2,stack3);
          Move(n,a,c,stack1,stack2,stack3);
          Hannoi(n-1,b,a,c,stack1,stack2,stack3);
    }
}

int main()
{
    stack<int> stack1;//第一个
    stack<int> stack2;//第二个
    stack<int> stack3;//第二个
    for(int i=7;i>0;i--) stack1.push(i);//7个号码压入
    fout<<"以下是7层汉诺塔的解法:"<<endl;
    Hannoi(7,'a','b','c',stack1,stack2,stack3);
    cout<<"输出完毕!"<<endl;
    return 0;
}
2009-09-03 13:50
mfkblue
Rank: 5Rank: 5
等 级:职业侠客
帖 子:472
专家分:343
注 册:2008-12-21
收藏
得分:0 
是想不通为什么会错了,想输出图形出来。
如改那段输出代码改为:
    int xl=S[x]->Length();
        int yl=S[y]->Length();
        int zl=S[z]->Length();
        cout<<"x="<<xl<<" ";
        cout<<"y="<<yl<<" ";
        cout<<"z="<<zl<<" ";
        cout<<endl;
运行是很正常的。
2009-09-03 14:35
mfkblue
Rank: 5Rank: 5
等 级:职业侠客
帖 子:472
专家分:343
注 册:2008-12-21
收藏
得分:0 
有点想通了,stack空了,我还在取栈顶的值,估计就错这里了.
2009-09-03 15:48
mfkblue
Rank: 5Rank: 5
等 级:职业侠客
帖 子:472
专家分:343
注 册:2008-12-21
收藏
得分:0 
有点想通了,stack空了,我还在取栈顶的值,估计就错这里了.
2009-09-03 15:48
mfkblue
Rank: 5Rank: 5
等 级:职业侠客
帖 子:472
专家分:343
注 册:2008-12-21
收藏
得分:0 
问题解决:
输出不是很满意,想不到有什么办法可以同一行显示三个塔的状态。
不过有另一个思路就是在栈里保存*号的字符串,然后打印时就不会为了打多少空格和多少*而头痛了,偷懒不写了,做下题去.
下面是改过的输出代码,还是有个问题,怪不得2楼输出在文本文档里,原来输出行数太多,dos框里显示不了前面的.
int xl=S[x]->Length();
        int yl=S[y]->Length();
        int zl=S[z]->Length();
        int xt=0,yt=0,zt=0,i,j,k,t;
        if(!S[x]->IsEmpty())
        {
            cout<<"1:"<<endl;
            xt=S[x]->Top();
            for(i=0;i<xl;i++)
            {
                for(j=0;j<xt;j++)
                    cout<<"*";
                xt++;
                cout<<endl;
            }
            cout<<endl;
        }
        if(!S[y]->IsEmpty())
        {
            cout<<"2:"<<endl;
            yt=S[y]->Top();
            for(i=0;i<yl;i++)
            {
                for(j=0;j<yt;j++)
                    cout<<"*";
                yt++;
                cout<<endl;
            }
            cout<<endl;
        }
        if(!S[z]->IsEmpty())
        {
            cout<<"3:"<<endl;
            zt=S[z]->Top();
            for(i=0;i<zl;i++)
            {
                for(j=0;j<zt;j++)
                    cout<<"*";
                zt++;
                cout<<endl;
            }
            cout<<endl;
        }
        
2009-09-03 16:45
xufen340
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
帖 子:166
专家分:1351
注 册:2009-8-7
收藏
得分:0 
//你的Stack没有取值功能, 比如 stack a,我不能从a[i]取值,也就没法画图,
//我还是用我昨天的程序加上绘图的程序输出图形。
#include <fstream>
#include <vector>
#include <iostream>
#include<iomanip>
using namespace std;

ofstream fout("out.txt");
/*stack*/
template<typename T>
class stack{
    private:
        vector<T> elems;
    public:
        void push(T const&);
        void pop();
        T top() const;
        bool empty() const{
            return elems.empty();
        };
        vector<T>& getelems(){ return this->elems;};
        friend ostream& operator<<(ostream& out,stack<T>& x);
};

template <class T>
ostream& operator<<(ostream& out,stack<T>& x)
{
    for(int i=x.getelems().size()-1;i>=0;i--){
        out<<x.getelems()[i];
        out<<endl;
    }
    return out;
}


template<typename T>
void stack<T>::push(T const& elem)
{
    elems.push_back(elem);
}

template<typename T>
void stack<T>::pop()
{
    if(elems.empty()){
        throw out_of_range("stack<>::pop():empty stack");
    }
    elems.pop_back();
}

template<typename T>
T stack<T>::top() const
{
    if(elems.empty()){
        throw out_of_range("stack<>::top():empty stack");
    }
    return elems.back();
}

/*判断x,y, 更改3个stack*/
void Move(int n,char x,char y,stack<int>& stack1,stack<int>& stack2,stack<int>& stack3)
{
  fout<<"把"<<n<<"号从"<<x<<"挪动到"<<y<<endl;
  switch(x){
      case 'a':
          stack1.pop();
          break;
      case 'b':
          stack2.pop();
          break;
      case 'c':
          stack3.pop();
          break;
  }
   switch(y){
       case 'a':
          stack1.push(n);
          break;
       case 'b':
          stack2.push(n);
          break;
       case 'c':
          stack3.push(n);
          break;
  }
   cout<<"第一个塔:"<<endl<<stack1<<endl;
   cout<<"第二个塔:"<<endl<<stack2;
   cout<<"第三个塔:"<<endl<<stack3<<endl;
       /*
       3个塔每层对应栈的位置,
       通过stack*.getelems()[stack1pos]可以取到栈值。
       栈值对应盘的大小,输出'*'.
       为了方便看图,我把每个栈的图形选择不一样*O#三种。
       */
       int stack1pos;
       int stack2pos;
       int stack3pos;
       int i,j;
       //7层汉诺塔
       for(i=0;i<7;i++){           
           /*
           判断栈1在每i层是否有值,有值就画出盘的大小,否则输出7
           个空。
           */
           if((stack1.getelems().size())>=(7-i)){
           //取得i层栈1的位置
           stack1pos=7-i-1;
            //如果盘是5,则前面留2个位置,从第三个输出‘*’
               cout<<setw(7-stack1.getelems()[stack1pos]+1);
               for(j=0;j<stack1.getelems()[stack1pos];j++) cout<<'*';
           }else cout<<"       ";           //汉诺塔每次7层,如果栈一这层没有,就输出7个空。
           if((stack2.getelems().size())>=(7-i)){
               stack2pos=7-i-1;
               cout<<setw(7-stack2.getelems()[stack2pos]+1);
               for(j=0;j<stack2.getelems()[stack2pos];j++) cout<<'o';
           }else cout<<"       ";
           if((stack3.getelems().size())>=(7-i)){
               stack3pos=7-i-1;
               cout<<setw(7-stack3.getelems()[stack3pos]+1);
               for(j=0;j<stack3.getelems()[stack3pos];j++) cout<<'#';
           } cout<<"       ";
           cout<<endl;
       }
}
  
  
      
void Hannoi(int n,char a,char b,char c,stack<int>& stack1,stack<int>& stack2,stack<int>& stack3)
{
    if(n==1)
              Move(1,a,c,stack1,stack2,stack3);
    else
    {
          Hannoi(n-1,a,c,b,stack1,stack2,stack3);
          Move(n,a,c,stack1,stack2,stack3);
          Hannoi(n-1,b,a,c,stack1,stack2,stack3);
    }
}

int main()
{
    stack<int> stack1;//第一个
    stack<int> stack2;//第二个
    stack<int> stack3;//第二个
    for(int i=7;i>0;i--) stack1.push(i);//7个号码压入
    fout<<"以下是7层汉诺塔的解法:"<<endl;
    Hannoi(7,'a','b','c',stack1,stack2,stack3);
    cout<<"输出完毕!"<<endl;
    return 0;
}
2009-09-04 11:05
xufen340
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
帖 子:166
专家分:1351
注 册:2009-8-7
收藏
得分:0 
从屏幕上看到显示正确了,在塞到文件里。
fout<<"第一个塔:"<<endl<<stack1<<endl;
   fout<<"第二个塔:"<<endl<<stack2;
   fout<<"第三个塔:"<<endl<<stack3<<endl;
       /*
       3个塔每层对应栈的位置,
       通过stack*.getelems()[stack1pos]可以取到栈值。
       栈值对应盘的大小,输出'*'.
       为了方便看图,我把
       */
       int stack1pos;
       int stack2pos;
       int stack3pos;
       int i,j;
       //7层汉诺塔
       for(i=0;i<7;i++){           
           /*
           判断栈1在每i层是否有值,有值就画出盘的大小,否则输出7
           个空。
           */
           if((stack1.getelems().size())>=(7-i)){
           //取得i层栈1的位置
           stack1pos=7-i-1;
            //如果盘是5,则前面留2个位置,从第三个输出‘*’
               fout<<setw(7-stack1.getelems()[stack1pos]+1);
               for(j=0;j<stack1.getelems()[stack1pos];j++) fout<<'*';
           }else fout<<"       ";           //汉诺塔每次7层,如果栈一这层没有,就输出7个空。
           if((stack2.getelems().size())>=(7-i)){
               stack2pos=7-i-1;
               fout<<setw(7-stack2.getelems()[stack2pos]+1);
               for(j=0;j<stack2.getelems()[stack2pos];j++) fout<<'o';
           }else fout<<"       ";
           if((stack3.getelems().size())>=(7-i)){
               stack3pos=7-i-1;
               fout<<setw(7-stack3.getelems()[stack3pos]+1);
               for(j=0;j<stack3.getelems()[stack3pos];j++) fout<<'#';
           } fout<<"       ";
           fout<<endl;
       }
2009-09-04 11:15
mfkblue
Rank: 5Rank: 5
等 级:职业侠客
帖 子:472
专家分:343
注 册:2008-12-21
收藏
得分:0 
其实汉诺塔的递归原理我还没想通,我都不想做这道题了,你倒是做挺起劲
2009-09-04 14:27
mfkblue
Rank: 5Rank: 5
等 级:职业侠客
帖 子:472
专家分:343
注 册:2008-12-21
收藏
得分:0 
没事做又改写了一次,这次倒是同一行输出了,可惜输出的顺序又错了,原因是还没搞懂这题的递归原理,不过这次真的不做了,去做火车进站去.
#include <iostream>
#include <string>
using namespace std;


class Hanoi;

template <class T>
class LinkedStack;

template <class T>
class Node
{
    friend Hanoi;
    friend LinkedStack<T>;
    public:
        T data;
        Node<T> *link;
};

template <class T>
class LinkedStack
{
    public:
        LinkedStack(){top=0;}
        ~LinkedStack();
        bool IsEmpty()const {return top==0;}
        bool IsFull() const;
        T Top() const;
        LinkedStack<T>& Add(const T& x);
        LinkedStack<T>& Delete(T& x);
        int Length();
        void Output(ostream& out) const;
        friend istream& operator>>(istream& in,LinkedStack<T>& x);
        LinkedStack<T>& Divide(LinkedStack& x);
        LinkedStack<T>& Merge(LinkedStack& x);
        Node<T>* First()const;
    private:
        Node<T> *top;
};

template <class T>
Node<T>* LinkedStack<T>::First()const
{
    return top;
}

template <class T>
LinkedStack<T>& LinkedStack<T>::Merge(LinkedStack& x)
{
    T t;
    int n=x.Length();
    for(int i=0;i<n;i++)
    {
        x.Delete(t);
        Add(t);
    }
    return *this;
}

template <class T>
LinkedStack<T>& LinkedStack<T>::Divide(LinkedStack& x)
{
    int n=x.Length();
    T t;
    for(int i=0;i<n/2;i++)
    {
        x.Delete(t);
        Add(t);
    }
    return *this;
}

template <class T>
int LinkedStack<T>::Length()
{
    Node<T> *p=top;
    int i=0;
    while(p)
    {
        
        p=p->link;
        i++;
    }
    return i;
}

template <class T>
void LinkedStack<T>::Output(ostream& out) const
{
    Node<T> *p=top;   
    while(p)
    {
        out<<p->data<<" ";
        p=p->link;
    }
    cout<<endl;
}

template <class T>
ostream& operator<<(ostream& out,LinkedStack<T>& x)
{
    x.Output(out);
    return out;
}

template <class T>
LinkedStack<T>::~LinkedStack()
{
    Node<T> *next;
    while(top)
    {
        next=top->link;
        delete top;
        top=next;
    }
}

template <class T>
bool LinkedStack<T>::IsFull()const
{
    try
    {
        Node<T> *p=new Node<T>;
        delete p;
        return false;
    }
    catch(NoMem){return true;}
}

template <class T>
T LinkedStack<T>::Top()const
{
    return top->data;
}

template <class T>
LinkedStack<T>& LinkedStack<T>::Add(const T& x)
{
    Node<T> *p=new Node<T>;
    p->data=x;
    p->link=top;
    top=p;
    return *this;
}

template <class T>
LinkedStack<T>& LinkedStack<T>::Delete(T& x)
{
    x=top->data;
    Node<T> *p=top;
    top=top->link;
    delete p;
    return *this;
}




class Hanoi
{
public:
    Hanoi(int n);
    void Hanoi::TowerOfHanoi(int n,int x,int y,int z);
    LinkedStack<string> S[4];
};

Hanoi::Hanoi(int n)
{
    string a="*",b="",c="";
    int i,j,k;
    for(i=0;i<n;i++)
    {
        for(j=i;j<n;j++)
            b=b+a;
        for(k=0;k<i;k++)
        c=c+" ";
        c=c+b;
        S[1].Add(c);
        b="";
        c=b;
    }
}

void Hanoi::TowerOfHanoi(int n,int x,int y,int z)
{
    string a;
    if(n>0)
    {
        TowerOfHanoi(n-1,x,z,y);
        S[x].Delete(a);
        S[y].Add(a);
        Node<string> *t1,*t2,*t3;
        int i,j,k,s,m;
        i=S[1].Length();
        j=S[2].Length();
        k=S[3].Length();
        if(!S[1].IsEmpty())
            t1=S[1].First();
        if(!S[2].IsEmpty())
            t2=S[2].First();
        if(!S[3].IsEmpty())
            t3=S[3].First();
        for(m=0;m<4;m++)
        {
            if(i<4-m&&j<4-m&&k<4-m)
            {   
                cout<<endl;
                continue;
            }
        
        
            if(!S[1].IsEmpty())
            {
                if(i<4-m)
                for(s=0;s<24;s++)
                        cout<<" ";
                else
                {
                    cout<<t1->data;
                    for(s=0;s<20;s++)
                        cout<<" ";
                    t1=t1->link;
                    i--;
                }
            
            }
            
            if(!S[2].IsEmpty())
            {
                if(j<4-m)
                for(s=0;s<24;s++)
                        cout<<" ";
                else
                {
                    cout<<t2->data;
                    for(s=0;s<20;s++)
                        cout<<" ";
                    t2=t2->link;
                    
                }
            
            }

            if(!S[3].IsEmpty())
            {
                if(k<4-m)
                for(s=0;s<24;s++)
                        cout<<" ";
                else
                {
                    cout<<t3->data;
                    for(s=0;s<20;s++)
                        cout<<" ";
                    t3=t3->link;
                    
                }
            
            }
        
            cout<<endl;
            
        }
        cout<<"  "<<1<<"                        "<<2<<"                      "<<3<<endl;
     TowerOfHanoi(n-1,z,y,x);   
        
    }
}

void main()
{
    Hanoi h(4);
    h.TowerOfHanoi(4,1,2,3);
}
2009-09-05 16:58
快速回复:还是汉诺塔的问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017314 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved