• 基本数据结构


    本章讲述了栈、队列、树、指针、对象的基本实现。boring AND difficult!!!

    (1) 栈

    概念定义:栈属于动态集合,采用先进后出策略(LIFO)。基本操作是压入(PUSH)和弹出(POP)。如果s.top=0,表示栈空,如果试图对空栈进行POP操作会发生下溢(underflow)。如果s.top>n,表示栈满,如果进行PUSH操作会发生上溢(overflow)。

    基本代码

     1 //基本的栈操作
     2 #include <iostream>
     3 #include <time.h>
     4 using namespace std;
     5 const n=10;
     6 struct stack
     7 {
     8     int top;
     9     int Array[n];
    10 }s;
    11 //初始化一个空栈
    12 int Init_Stack()
    13 {
    14     s.top = 0;//top为0表示空栈
    15     return 1;
    16 }
    17 //判断栈是否为空
    18 bool stack_empty(int Array[])
    19 {
    20     if (s.top==0)
    21     {
    22         return true;
    23     }
    24     else
    25     {
    26         return false;
    27     }
    28 }
    29 //入栈
    30 void stack_push(int Array[],int x)
    31 {
    32     if (s.top==n)
    33     {
    34         cerr<<"overflow!"<<endl;
    35     } 
    36     else
    37     {
    38         s.top++;
    39         s.Array[s.top]=x;
    40         
    41     }
    42 }
    43 //出栈
    44 int stack_pop(int Array[])
    45 {
    46     if (stack_empty(s.Array))
    47     {
    48         cerr<<"underflow"<<endl;
    49         return -1;
    50     }
    51     else
    52     {
    53         s.top--;
    54         return s.Array[s.top+1];
    55     }    
    56 }
    57 void main()
    58 {
    59     struct stack s;
    60     Init_Stack();
    61     int x=0;
    62     srand( (unsigned)time( NULL ) );
    63     for ( int i=0;i<n;i++)
    64     {
    65         x=rand()%100;
    66         stack_push(s.Array,x);
    67     }
    68     for (i=0;i<n;i++)
    69     {
    70         cout<<stack_pop(s.Array)<<endl;
    71     }
    72 
    73 }

    (2) 队列

    概念定义:队列属于动态集合,采用先进先出策略(FIFO)。基本操作是出队(enqueue)和出队(dequeue)。如果head=tail,表示队列为空,如果试图对空队列进行enqueue操作会发生下溢(underflow)。如果head=tail+1,表示队列满,如果进行dequeue操作会发生上溢(overflow)。

    基本代码:

     1 //基本的队列操作
     2 #include <iostream>
     3 #include <time.h>
     4 using namespace std;
     5 const n=5;
     6 struct Queue
     7 {
     8     int head;
     9     int tail;
    10     int Array[n];
    11 }Q;
    12 void Init_Queue()
    13 {
    14     Q.head=Q.tail=1;//表示队列为空栈
    15 }
    16 //判断栈是否为空
    17 bool Queue_empty(int Array[])
    18 {
    19     if (Q.head==Q.tail)
    20     {
    21         return true;
    22     }
    23     else
    24     {
    25         return false;
    26     }
    27 }
    28 void ENQueue(int Array[],int x)
    29 {
    30     if (Q.head==Q.tail+1)
    31     {
    32         cerr<<"overflow!"<<endl;
    33     } 
    34     else
    35     {
    36         Q.Array[Q.tail]=x;
    37         if (Q.tail==n)
    38         {
    39             Q.tail=0;
    40         }
    41         else
    42         {
    43             Q.tail++;
    44         }
    45     }
    46 }
    47 int DEQueue(int Array[])
    48 {
    49     int x=0;
    50     if (Queue_empty(Q.Array))
    51     {
    52        cerr<<"underflow"<<endl;
    53     } 
    54     else
    55     {
    56         x=Q.Array[Q.head];
    57         if (Q.head==n)
    58         {
    59             Q.head=0;
    60         } 
    61         else
    62         {
    63             Q.head++;
    64         }
    65     }
    66    return x;
    67 }
    68 void main()
    69 {
    70     struct Queue Q;
    71     Init_Queue();
    72     int x=0;
    73     srand( (unsigned)time( NULL ) );
    74     for ( int i=0;i<n;i++)
    75     {
    76         x=rand()%100;
    77         ENQueue(Q.Array,x);
    78     }
    79     for (i=0;i<n;i++)
    80     {
    81         cout<<DEQueue(Q.Array)<<endl;
    82     } 
    83 }

    (3)链表

     基本概念:链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序存储结构,操作复杂。

    基本代码:

      1 //书中双向链表无哨兵实现
      2 
      3 #include <iostream>
      4 #include <time.h>
      5 using namespace std;
      6 #define LEN sizeof(struct List)
      7 struct List
      8 {
      9     struct List*prev;
     10     struct List*next;
     11     struct List*head;
     12     int key;
     13 };
     14 //查找数据
     15 struct List*search(struct List L,int k)
     16 {
     17     struct List*x;
     18     x=L.head;
     19     while (x!=NULL&&x->key!=k)
     20     {
     21         x=x->next;
     22     }
     23     return x;
     24 }
     25 //插入数据
     26 struct List*insert(struct List L,struct List*x)
     27 {
     28    x->next=L.head;
     29    if (L.head!=NULL)
     30    {
     31        L.head->prev=x;
     32    }
     33    L.head=x;
     34    x->prev=NULL;
     35    return L.head;
     36 }
     37 //删除数据
     38 struct List*Delete(struct List L,struct List*x)
     39 {
     40    if (x->prev!=NULL)
     41    {
     42        x->prev->next=x->next;
     43    } 
     44    else
     45    {
     46        L.head=x->next;
     47    }
     48    if (x->next!=NULL)
     49    {
     50        x->next->prev=x->prev;
     51    }
     52    return L.head;
     53 }
     54 //打印数据
     55 void Print(List L)  
     56 {  
     57     struct List*p = L.head;  
     58     while(p)  
     59     {  
     60         cout<<p->key<<' ';  
     61         p = p->next;  
     62     }  
     63     cout<<endl;  
     64 }  
     65 void main()
     66 {
     67    struct List L,*x,*t;
     68    srand( (unsigned)time( NULL ) );
     69    L.head=NULL;x=NULL;
     70    for (int i=0;i<10;i++)
     71    {
     72        x= (struct List*)malloc(LEN);
     73        x->key=rand()%100;
     74        if (i==6)
     75        {
     76            t=x;
     77        }
     78        L.head=insert(L,x);
     79    }
     80    Print(L);
     81    x=search(L,60);
     82    if (x==NULL)
     83    {
     84        cout<<"未找到数据!"<<endl;
     85    } 
     86    else
     87    {
     88        cout<<"已经找到数据"<<x->key<<endl;
     89    }
     90    L.head=Delete(L,t);
     91    Print(L);
     92 }
    
    书中双向链表有哨兵实现:
    #include <iostream>
    #include <time.h>
    using namespace std;
    #define LEN sizeof(struct List)
    struct List
    {
        struct List*prev;
        struct List*next;
        struct List*nil;
        int key;
    };
    struct List*Initialization(struct List &L)
    {
       L.nil;
       L.nil=(struct List*)malloc(LEN);
       L.nil->next=L.nil;
       L.nil->prev=L.nil;
       return L.nil;
    }
    struct List*search(struct List &L,int k)
    {
       struct List*x;
       x=L.nil->next;
       while (x!=L.nil&&x->key!=k)
       {
           x=x->next;
       }
       return x;
    }
    struct List*insert(struct List &L,struct List*x)
    {
        x->next=L.nil->next;
        L.nil->next->prev=x;
        L.nil->next=x;
        x->prev=L.nil;
        return L.nil;
    }
    struct List*Delete(struct List &L,struct List*x)
    {
        x->prev->next=x->next;
        x->next->prev=x->prev;
        return L.nil;
    }
    //打印数据
    void Print(List L)  
    {  
        struct List*p = L.nil->next; 
        if(p!=L.nil)
        {
            while(p!=L.nil)  
            {  
                cout<<p->key<<' ';  
                p = p->next;  
            }  
            cout<<endl; 
        }
        else
        {
            cout<<"此链表为空!"<<endl;
        }
    } 
    void main()
    {
        struct List L,*x,*t;
        Initialization(L);
        Print(L);
        srand( (unsigned)time( NULL ) );
        x=NULL;
        for (int i=0;i<10;i++)
        {
            x= (struct List*)malloc(LEN);
            x->key=rand()%100;
            if (i==6)
            {
                t=x;
            }
            insert(L,x);
        }
        Print(L);
        x=search(L,60);
        if (x==L.nil)
        {
            cout<<"未找到数据!"<<endl;
        } 
        else
        {
            cout<<"已经找到数据"<<x->key<<endl;
        }
       Delete(L,t);
       Print(L);
    }
    View Code

    (4)指针和对象的实现

    基本概念:当有些语言不支持指针和对象数据类型时,我们可以用数组和数组下标构造对象和指针。这种链表称为静态链表

    对象的多数组和单数组表示基本的字典操作+申请分配内存

    基本代码:

    对象的多数组表示

         用三个数组next key prev 分别表示链表的后继 数据 前驱。

      1 //由于有些语言不支持指针,所以我们可以用多数组表示的静态双链表。
      2 #include <iostream>
      3 #include <time.h>
      4 #include <windows.h>
      5 using namespace std;
      6 #define MAX 10//于表头的前驱和表尾的后继都不存放元素,所以实际能存放的有效元素个数比MAX少2个
      7 #define Null -1
      8 int head=Null,Free=0;
      9 int j=0;
     10 struct List
     11 {
     12     int next[MAX];
     13     int key[MAX];
     14     int prev[MAX];
     15 };
     16 int isIn(int *num,int index,int pat)//生成的随机数pat是否已经存在
     17 {
     18     int i=0;
     19     for(i=0;i<index;++i)
     20         if(pat==num[i])
     21             return 1;
     22         return 0;   
     23 }
     24 int RAND(int *num)//随机抽取元素互异的key 这样key不会出现重复数值,易于以后的删除工作。
     25 {
     26     int result=0;
     27     if (j>=MAX)
     28     {
     29         return Null;
     30     }
     31     while(1)
     32     {
     33         result=rand()%MAX;
     34         if(!isIn(num,j,result))
     35         {
     36             num[j]=result;
     37             j++;
     38             break;
     39         }
     40     }
     41     return result;
     42 }
     43 //链表初始化
     44 void Initialization(struct List &T,int*num)
     45 {
     46    Free=RAND(num);//[1,MAX-1]之间的数随机选择一个作为表头元素下标
     47    for (int i=0;i<MAX;i++)
     48    {
     49        T.key[i]=0;
     50        T.prev[i]=0;
     51    }
     52    int p=Free;
     53    for ( i=0;i<MAX-1;i++)
     54    {
     55        p=T.next[p]=RAND(num);
     56    }
     57    T.next[p]=Null;//链表最后的next指针为空。-1代表空
     58    j=0;//结构体T初始化后,临时数组num下标设置为0.
     59 }  
     60 //分配空间
     61 int Allocate_object(struct List &T,int*num)
     62 {
     63     if (Free==Null)
     64     {
     65         cerr<<"out of space!"<<endl;
     66         return Null;
     67     }
     68     else
     69     {    
     70       int x=Free; 
     71    Free=T.next[x];
     72       return x;
     73     }
     74 }
     75 //释放空间
     76 void Free_object(struct List &T,int x)
     77 {
     78    T.next[x]=Free;
     79    Free=x;
     80 }
     81 //插入数据
     82 void insert(struct List &T,int k,int *num)
     83 {
     84      int x=Allocate_object(T,num);//类似指针开辟一段内存空间
     85   if (x==Null)
     86   {
     87    return;
     88   }
     89   T.next[x]=head;
     90   T.key[x]=k;
     91   if (head!=Null)
     92   {
     93    T.prev[head]=x;
     94   }
     95   head=x;
     96   T.prev[x]=Null;
     97 }
     98 //查找数据
     99 int search(struct List &T,int k)
    100 {
    101    int t=head;
    102    if (head==Null)
    103    {
    104        cout<<"链表为空!无法查找!"<<endl;
    105        return Null;
    106    }
    107    while (t!=-1&&T.key[t]!=k)
    108    {
    109        t=T.next[t];
    110    }
    111    if (t==Null)
    112    {
    113        cout<<"不存在这个数据!"<<endl;
    114        return Null;
    115    } 
    116    else
    117    {
    118       cout<<"待查找数据已经找到!"<<endl;
    119       return t;//将待删除的数据下标返回,易于删除工作。
    120    }
    121 }
    122 //删除数据
    123 void Delete(struct List &T,int k)//删除特定值的删除函数
    124 { 
    125     int p=0;
    126         p=search(T,k);
    127         if (p!=Null)
    128         {
    129        
    130             if (T.prev[p]!=Null)
    131             {
    132                 T.next[T.prev[p]]=T.next[p];
    133             } 
    134             else
    135             {
    136                 head=T.next[p];
    137             }
    138             if (T.next[p]!=Null)
    139             {
    140                 T.prev[T.next[p]]=T.prev[p];
    141             }
    142             cout<<"删除成功!"<<endl;
    143             Free_object(T,p);
    144         } 
    145         else
    146         {
    147             cout<<"待删除的数据不存在!无法删除!"<<endl;
    148         }
    149 }
    150 void Print(struct List &T)
    151 {
    152     int i=head;
    153     if (head==Null)
    154     {
    155         cout<<"此链表为空!"<<endl;
    156         return;
    157     }
    158     while (i!=Null)
    159     {
    160         cout<<T.key[i]<<"->";
    161         i=T.next[i];
    162     }
    163     cout<<endl;
    164 }
    165 void main()
    166 {
    167     struct List T;
    168     srand((unsigned)time(NULL));
    169     int num[MAX]={0};//临时存放next[MAX]和key[MAX]数组的值,目的是用于生成互异的随机数
    170     cout<<"初始化链表中。";
    171     for( int j=0; j <= 100; j++ )      // 打印百分比   
    172      {  
    173       cout.width(3);  
    174       cout << j << "%";  
    175          Sleep(40);  
    176       cout << "";//退格符号  
    177   }  
    178     cout << "
    ";  
    179     Initialization(T,num);
    180     Print(T);
    181     cout<<"给链表添加数据中。";
    182  for(  j=0; j <= 100; j++ )      // 打印百分比   
    183  {  
    184   cout.width(3);  
    185   cout << j << "%";  
    186   Sleep(40);  
    187   cout << "";//退格符号  
    188  }  
    189     cout << "
    "; 
    190     for (int i=0;i<MAX+1;i++)
    191     {
    192   int k=RAND(num);
    193         insert(T,k,num);
    194     }
    195     insert(T,35,num);
    196     Print(T);
    197     cout<<"查找数据中。";
    198  for(  j=0; j <= 100; j++ )      // 打印百分比   
    199  {  
    200   cout.width(3);  
    201   cout << j << "%";  
    202   Sleep(40);  
    203   cout << "";//退格符号  
    204  }  
    205  cout << "
    "; 
    206     search(T,6);
    207     cout<<"删除数据中。";
    208  for( j=0; j <= 100; j++ )      // 打印百分比   
    209  {  
    210   cout.width(3);  
    211   cout << j << "%";  
    212   Sleep(40);  
    213   cout << "";//退格符号  
    214  }  
    215     cout << "
    "; 
    216     Delete(T,0);
    217     Delete(T,2);
    218  Delete(T,5);
    219  Delete(T,500);
    220  insert(T,25,num);
    221  Print(T);
    222 }
    View Code

    对象的单数组表示

         用一个数组即可表示双链表,这种表示法比较灵活,因为它允许不同长度的对象存储于同一数组中。一般地我们考虑的数据结构多是由同构的元素构成,因此采用对象的多数组表示法足够满足我们的需求。

    以下的代码分别展示了基本的字典操作和如何申请分配内存。

      1 //我们用key next prev表示双链表,如果array[i-1]为key,那么array[i]为next,array[i+1]为prev。
      2 #include <iostream>
      3 #include <time.h>
      4 #include <windows.h>
      5 using namespace std;
      6 #define MAX 120
      7 #define Null -1
      8 int head=0,Free=0;
      9 int isIn(int *num,int index,int pat)//生成的随机数pat是否已经存在
     10 {
     11     int i=0;
     12     for(i=0;i<index;++i)
     13         if(pat==num[i])
     14             return 1;
     15         return 0;   
     16 }
     17 int RAND(int *num,int &j)//随机抽取元素互异的key 这样key不会出现重复数值,易于以后的删除工作。
     18 {
     19     
     20     int result=0;
     21     if (j==0)
     22     {
     23         num[j]=head;j++;
     24     }
     25     while(1)
     26     {
     27         if (MAX/3==0)//防止被除数为0
     28         {
     29             return Null;
     30         }
     31         else
     32         {
     33             result=(rand()%(MAX/3)) * 3 + 1;
     34         }
     35         if(!isIn(num,j,result))
     36         {
     37             num[j]=result;
     38             j++;
     39             break;
     40         } 
     41     }
     42     return result;
     43 }
     44 //分配空间
     45 int Allocate_object(int *Array,int*num)
     46 {
     47     static x;
     48     if (Free==Null)
     49     {
     50         cout<<endl;
     51         cerr<<"out of space!"<<endl;
     52         return Null;
     53     }
     54     else
     55     {   
     56         x=Free;
     57         Free=Array[x];
     58         return x;
     59     }
     60 }
     61 //释放空间
     62 void Free_object(int *Array,int x)
     63 {
     64     Array[x]=Free;
     65     Free=x;
     66 }
     67 //链表初始化
     68 void Initialization(int *Array,int*num,int &j)
     69 {
     70     for (int i=0;i<MAX;i++)
     71     {
     72          Array[i]=0;
     73     }
     74     int p=RAND(num,j);
     75     Free=head=p;
     76     for (i=0;i<MAX/3-1;i++)
     77     {
     78          p=Array[p]=RAND(num,j);
     79     }
     80    Array[p]=Null;//链表最后的next指针为空。-1代表空
     81 }
     82 int insert(int *Array,int *num,int &j)
     83 {
     84     static p=head,q=Null;
     85     int x=Allocate_object(Array,num);
     86     if (p!=Null)
     87     {
     88         Array[p-1]=rand()%MAX+1;
     89         Array[p+1]=q;
     90         q=p;
     91         p=Array[x];
     92     }
     93     else cout<<"链表开辟的内存空间不足! 无法插入!"<<endl;
     94     return p;
     95 }
     96 //查找数据
     97 int search(int *Array,int k)
     98 {
     99     int t=head;
    100     if (Array[t-1]==0)
    101     {
    102         cout<<"链表为空!无法查找!"<<endl;
    103         return Null;
    104     }
    105     while (t!=-1&&Array[t-1]!=k)
    106     {
    107         t=Array[t];
    108     }
    109     if (t==Null)
    110     {
    111         cout<<"不存在这个数据!"<<endl;
    112         return Null;
    113     } 
    114     else
    115     {
    116         cout<<"待查找数据已经找到!"<<endl;
    117         return t;//将待删除的数据下标返回,易于删除工作。
    118     }
    119 }
    120 //删除数据
    121 void Delete(int Array[],int k)//删除特定值的删除函数
    122 {
    123     int p=0;
    124     p=search(Array,k);
    125     if (p!=Null)
    126     {
    127         if (Array[p+1]!=Null)
    128         {
    129             Array[Array[p+1]]=Array[p];
    130         } 
    131         else
    132         {
    133             head=Array[p];
    134         }
    135         if (Array[p]!=Null)
    136         {
    137             Array[Array[p]+1]=Array[p+1];
    138         }
    139         Free_object(Array,p);
    140         cout<<"删除成功!"<<endl;
    141     }
    142     else
    143     {
    144        cout<<"待删除的数据不存在!无法删除!"<<endl;
    145     }
    146 }
    147 void Print(int *Array)
    148 {
    149     int i=head;int flag=1;
    150     if (Array[head-1]==0)
    151     {
    152         cout<<"链表为空!"<<endl;
    153         return;
    154     }
    155     while (flag)
    156     {
    157         if (Array[i]==Null)
    158         {
    159             flag=0;
    160         }
    161         cout<<Array[i-1]<<"	";
    162         i=Array[i];        
    163     }
    164 }
    165 void main()
    166 {
    167     int Array[MAX];
    168     int num[MAX]={0};//临时存放数据的next指针的值,目的是用于生成互异的随机数
    169     int j=0;
    170     srand((unsigned)time(NULL));
    171     cout<<"初始化链表中。";
    172     for( int i=0; i <= 100; i++ )      // 打印百分比 
    173     {
    174         cout.width(3);
    175         cout << i << "%";
    176         Sleep(40);
    177         cout << "";//退格符号
    178     }
    179     cout << "
    ";
    180     Initialization(Array,num,j);
    181     Print(Array);
    182     cout<<"给链表添加数据中。";
    183     for(  i=0; i<= 100; i++ )      // 打印百分比 
    184     {
    185         cout.width(3);
    186         cout << i << "%";
    187         Sleep(40);
    188         cout << "";//退格符号
    189     }
    190     insert(Array,num,j);
    191     insert(Array,num,j);
    192     insert(Array,num,j);
    193     insert(Array,num,j);
    194     insert(Array,num,j);
    195     for ( i=0;i<MAX/3;i++)
    196     {
    197         insert(Array,num,j);
    198     }
    199     Print(Array);
    200     cout<<"查找数据中。";
    201     for(  i=0; i <= 100; i++ )      // 打印百分比 
    202     {
    203         cout.width(3);
    204         cout << i << "%";
    205         Sleep(40);
    206         cout << "";//退格符号
    207     }
    208     cout << "
    ";
    209     search(Array,5);
    210     cout<<"删除数据中。";
    211     for(  i=0; i <= 100; i++ )      // 打印百分比 
    212     {
    213         cout.width(3);
    214         cout << i << "%";
    215         Sleep(40);
    216         cout << "";//退格符号
    217     }
    218     cout << "
    ";
    219     Delete(Array,5);
    220     Delete(Array,6);
    221     Delete(Array,7);
    222     Delete(Array,7);
    223     Delete(Array,6);
    224     Print(Array);
    225 }
    View Code

    (5)树

    基本代码:

    递归实现:

    #include <iostream>
    using namespace std;
    #define LEN sizeof(struct Tree)
    struct Tree
    {
        int key;
        struct Tree*lchild;
        struct Tree*rchild;
    };
    //二叉树的创建
    void create(struct Tree **p)
    {
      *p=new struct Tree [LEN];
      cout<<"请输入二叉树key值:(按0结束当前分支输入)"<<endl;
      cin>>(*p)->key;
      static i=0;
      if ((*p)->key!=0)
      {
          create((&(*p)->lchild));
          create((&(*p)->rchild));
      }
    }
    //先序遍历递归过程。。。。(位置1)
    void PreOderTraverse(struct Tree *p)
    {//递归实现先序遍历
        if (p->key)
        {
            cout<<p->key<<" ";
            PreOderTraverse(p->lchild);
            PreOderTraverse(p->rchild);
        }
    }
    //中序遍历
    void InOderTraverse(struct Tree *p)
    {
        if (p->key)
        {        
            InOderTraverse(p->lchild);
            cout<<p->key<<" ";
            InOderTraverse(p->rchild);
        }
    }
    //后序遍历
    void BackOderTraverse(struct Tree *p)
    {
        if (p->key)
        {        
            BackOderTraverse(p->lchild);
            BackOderTraverse(p->rchild);
            cout<<p->key<<" ";
        }
    }
    void main()
    {
        struct Tree *p=NULL;
        create(&p);
        cout<<"先序遍历:"<<endl;
        PreOderTraverse(p);
        cout<<endl;
        cout<<"中序遍历:"<<endl;
        InOderTraverse(p);
        cout<<endl;
        cout<<"后序遍历:"<<endl;
        BackOderTraverse(p);
        cout<<endl;
    }
    View Code

    循环实现:

    栈实现:

    .也可以用栈的数组实现,栈的实现,包括PUSH POP等栈操作全部自己实现。这个应该是符合《算法导论》10.4-3题目条件。
    
    #include <iostream>
    using namespace std;
    #define LEN sizeof(struct Tree)
    #define m 10//栈的最大容纳空间可以调整
    struct Tree
    {
        int key;
        struct Tree*lchild;
        struct Tree*rchild;
    };
    struct Stack
    {
        int top;
        int Array[m];
        bool empty();
        void push(struct Tree*);
        int pop();
    }s;
    //判断栈是否为空
    bool Stack::empty()
    {
        if (s.top==-1)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    //入栈
    void Stack::push(struct Tree*p)
    {
        if (s.top==m)
        {
            cerr<<"overflow!"<<endl;
        } 
        else
        {
            s.top++;
            s.Array[s.top]=reinterpret_cast<int>(p);//将树形结构体的地址转化为整数储存到栈里面。
        }
    }
    //出栈
    int Stack::pop()
    {
        if (empty())
        {
            cerr<<"underflow"<<endl;
            return NULL;
        }
        else
        {
            s.top--;
            return s.Array[s.top+1];
        }    
    }
    void create(struct Tree **p)
    {
      *p=new struct Tree [LEN];
      cin>>(*p)->key;
      static i=0;
      if ((*p)->key!=0)
      {
          create((&(*p)->lchild));
          create((&(*p)->rchild));
      }
    } 
    void PreOderTraverse(struct Tree *root)  
    {  //用栈的数组实现,POP PUSH等函数全部自己来写
        if (root == NULL) return; 
        s.top=-1;
        s.push(root);
        struct Tree *p=root;
        while (!s.empty()) {   
            p=reinterpret_cast<struct Tree *>(s.Array[s.top]);//将数组中的数据恢复为编译器所能识别的指针
            cout<<p->key<<" ";
            s.pop();
            if (p->rchild->key != 0) 
            {
                s.push(p->rchild); 
            }
            if (p->lchild->key != 0) 
            {
                s.push(p->lchild);  
            }
        }  
        cout << endl;  
    }
    void main()
    {
        struct Tree *p=NULL;
        create(&p);
        PreOderTraverse(p);
    }
    View Code

    还有一种不用辅助栈,但需要父结点:

    //(1). 访问左孩子
    //(2). 访问右孩子
    //(3). 如果是从右孩子返回,表明整棵子树已访问完,需要沿树而上寻找父节点。直到是从左孩子返回,或者访问到根节点的父节点
    #include <iostream>
    #include <stack>
    using namespace std;
    #define LEN sizeof(struct Tree)
    struct Tree
    {
        int key;
        struct Tree*lchild;
        struct Tree*rchild;
        struct Tree*parent;
    };
    void create(struct Tree **p)
    {
        static struct Tree *p1=NULL;//p1保存当前结点的父亲结点
        *p=new struct Tree [LEN];
        cin>>(*p)->key;
        (*p)->parent=p1;
        p1=*p;
        if ((*p)->key!=0)
        {
            create((&(*p)->lchild));
            p1=*p;    
            create((&(*p)->rchild));
        }
    }
    void InOderTraverse(struct Tree *p)
    {
       if(!p->key) return;
        struct Tree *x=NULL;
        while(1)
        {
            //访问左孩子
            if(x != p->lchild)
            {
                while(p->lchild->key) 
                {
                    p=p->lchild;
                }
            }
            cout<<p->key<<" ";
            //访问右孩子
            if(p->rchild->key)
            {
                p=p->rchild;
                continue;
            }
            //回溯
            do
            {
                x=p;
                p=p->parent;
                //访问到根节点的父节点(NULL)
                if(!p) return;
            }while(x==p->rchild);
        }
    }
    void main()
    {
        struct Tree *p=NULL;
        create(&p);
        InOderTraverse(p);
    }
    View Code

    左孩子右兄弟表示多叉树:

    //左孩子右兄弟表示多叉树
    #include <iostream>
    using namespace std;
    #define LEN sizeof(struct Tree)
    struct Tree*root=NULL;
    struct Tree
    {
        int key;
        struct Tree*left_child;
        struct Tree*right_sibling;
    };
    struct Tree*create(struct Tree**p)
    {//注意创建多叉树的过程中,根结点没有右兄弟,所以最后回溯到根结点时,要把根节点的右兄弟设置为0.
      *p=new struct Tree[LEN];
      cin>>(*p)->key; 
      if ((*p)->key!=0)
      {
          create(&(*p)->left_child);
          create(&(*p)->right_sibling);
      }      
       return root;
    }
    //先序遍历递归过程
    void PreOderTraverse(struct Tree *p)
    {
        if (p->key)
        {
            cout<<p->key<<" ";
            PreOderTraverse(p->left_child);
            PreOderTraverse(p->right_sibling);
        }
    }          
    void main()
    {
        struct Tree *p=NULL;
        create(&p);
        PreOderTraverse(p);
    }
    View Code

    参考资料:

    1、栈和队列的简单应用:

    http://www.cnblogs.com/robinli/archive/2011/02/26/1965630.html

    2、简单数据结构的理论升级:

    http://blog.csdn.net/z84616995z/article/details/19202773

  • 相关阅读:
    centos7之防止root密码被破解
    近期codeforces做题的总结?(不定期更新)
    小程序分享微信好友
    小程序自定义头部导航栏滑动颜色渐变
    小白快速上手的react.js教程
    架构型设计模式-同步模式
    仿vue-cli写一个简易的脚手架
    VUE基础知识篇-vue从零开始学VUE
    彻底理解Vue组件间7种方式通信
    设计模式--观察者模式
  • 原文地址:https://www.cnblogs.com/zzsf/p/4297977.html
Copyright © 2020-2023  润新知