官术网_书友最值得收藏!

  • 數據結構與實訓
  • 張紅霞 白桂梅主編
  • 961字
  • 2018-12-27 18:17:51

3.2 棧典型題例

【例3-3】若某堆棧的輸入序列為1,2,3,…,n-1,n,輸出序列的第1個元素為n,問第i個輸出元素是什么?

【分析與解答】堆棧的輸入序列為1,2,3,…,n-1,n,堆棧的特性是后進先出,輸出序列的第1個元素為n,那么第2個元素為n-1,第3個元素為n-2,依次類推,第i個輸出元素是n-i+1。

【例3-4】簡述以下算法的功能。

void Reverse (SeqStack s)

{

n=0;

while (!StackEmpty (s))

{
a[n]=Pop(s);
n++;
}
for(i=0;i<n;i++)
Push(s,a[i]);
} /*Reverse*/
void Remove (LinkStack s,ElementType e)
{
while (!StackEmpty (s))
{
d=Pop(s);
if (d!=e) Push(t,d);
}
while (!StackEmpty (t))
     {
        d=Pop(t);
        Push(s,d);
     }
} /* Remove */

【分析與解答】算法Reverse中,堆棧s的元素從棧底到棧頂的序列設為e1,e2,…,en,while循環將s的元素出棧,存入a數組,a數組中各元素的值如表3-1所示,for循環將a數組元素依a[0],a[1],…,a[n-1](即en,en-1,…,e1)的順序入s棧,從棧底到棧頂的序列為en,en-1,…,e1。因此,該算法借助數組a實現了堆棧s的逆置。

表3-1 數組a中元素的值

算法Remove中,第1個while循環將s的元素(除元素e)出棧進入t棧,t棧是s棧不包括e元素的逆置;第2個while循環則將t的元素出棧后又進入s棧,s棧是t棧的逆置,最終s經過兩次逆置又恢復成原來的元素序列(不包括元素e),因此該算法借助堆棧t將堆棧s中的數據元素e刪除。

【例3-5】圖3-5所示是一組n條帶頭結點的鏈表表示的堆棧(n個鏈棧),top[0],top[1],…, top[n-1]分別是各堆棧棧頂指針,試給出該組堆棧的數據類型定義,并寫一算法對這組堆棧初始化。

【分析與解答】數據類型(鏈表中結點類型StackNode與鏈指針類型LinkStack)定義如下。

#define MaxSize 棧頂指針數組的最大長度
typedef struct snode
    { ElementType data;
      struct snode *next;
    }StackNode;
typedef StackNode *LinkStack;
    / * LinkStack為指向StackNode的指針類型* /

圖3-5 一組n條帶頭結點的鏈表示的堆棧

構成n個棧頂指針的數組數據類型定義如下。

LinkStack top[MaxSize];

堆棧組初始化算法如下。

void StackInit(LinkStack top[],int n)
{
    for (i=0;i<n;i++)
    {
        p=(LinkStack)malloc(sizeof(StackNode));/*生成堆棧頭結點*/
        p->next=NULL;/*堆棧頭結點指針為空*/
        top[i]=p;/*各數組元素為指向頭結點的頭指針*/
    }
}/* StackInit */

【例3-6】寫一算法,將十進制數轉換為十進制以下進制的數。

【分析與解答】將十進制數轉換成其他進制數有一種簡單的方法,即利用公式:

N=(N div d)*d+N mod d

其中div為整除運算,mod為求余運算,N是十進制數,d表示要轉換到的目標進制(其他進制)。公式中十進制數N轉換為d進制數的過程就是,N除以d取其余數,最先得到的余數就是最低位,依次到最高位。

例如,將十進制數67轉換為二進制數,其轉換過程如下。

67 div 2=33余數為1

33 div 2=16余數為1

16 div 2=8余數為0

8 div 2=4余數為0

4 div 2=2余數為0

2 div 2=1余數為0

1 div 2=0余數為1

結果為余數的逆序1000011,即(67)10=(1000011)2

算法描述如下。

int Conversion(int n,int d)
/*將十進制數n轉換為d進制(十進制以下進制)數*/
{
    SeqStack s;
    result=0;
    s.top=-1;
    while (n)
    {
       Push(s,n%d); /*余數入棧*/
       n=n/d;
    }
    while (!StackEmpty (s))
       result=result*10+Pop(s);
    return(result);
} /*conversion */

【例3-7】一個簡單的行編輯程序的功能是接收用戶的終端輸入,并允許用戶對輸入的錯誤及時修改。約定“#”為退格符,表示前一個輸入的字符無效,“@”為退行符,表示當前行的輸入無效。若用戶的終端輸入為while##le (s1#!=0),則對應的有效輸入為while(s!=0)。寫一模擬行編輯程序的算法。

【分析與解答】可借用兩個堆棧s、t來模擬行編輯程序的工作過程。

(1)堆棧s用來接收用戶輸入的普通字符,如果輸入的是特殊字符“#”或“@”,則對s棧做一次出棧或清空操作。

(2)當一行字符輸入結束后,將s棧中的字符依次出棧并壓入t棧,t棧中存放有s棧字符的逆序列。

(3)將t棧中的字符依次出棧存放在數組str中,數組str中存放有t棧字符的逆序列,即s棧字符的正序列,并且每行字符都存入str。

(4)當輸入結束時,輸出字符數組str的值,也就輸出了用戶輸入、編輯后的有效字符。

void LineEdit()
/*行編輯程序模擬算法*/
{  s=StackInit ();
   t=StackInit ();
   strlen=0;
   ch=getchar();
   while(ch!=EOF) /*EOF表示輸入結束符*/
      {  while(ch!=EOF && ch!='\n') /*接收一行字符*/
        {  switch(ch)
        {  case '#' : ch=Pop(s);break;
           case '@' : StackClear (s);break;/*將s棧置空*/
           default : Push(s,ch);break;  /*輸入字符存入s棧*/
         }
         ch=getchar();
      }
      if (ch=='\n') Push(s,ch);/*換行符進棧*/
      while(!StackEmpty(s))
      {  x=Pop(s);
         Push(t,x);/* t棧存放s棧中字符序列的逆序*/
      }
      while(!Empty(t))
      {  x=Pop(t);
         str[strlen++]=x;
      }
      if (ch!=EOF) ch=getchar();
     }
     str[strlen]='\0';
     printf(str);
} /* LineEdit */
主站蜘蛛池模板: 扶绥县| 南宫市| 清新县| 浠水县| 防城港市| 郸城县| 辽阳县| 临汾市| 广灵县| 拜城县| 遵义市| 江源县| 芦山县| 阿荣旗| 梧州市| 闸北区| 咸丰县| 南涧| 苏州市| 大足县| 兰坪| 珠海市| 枣阳市| 长春市| 保靖县| 巫山县| 金昌市| 阿坝| 曲水县| 台中市| 敦煌市| 涞源县| 武陟县| 钦州市| 驻马店市| 交口县| 宁远县| 湘阴县| 家居| 安西县| 维西|