1. 程式人生 > >第一節、漢諾塔與棧

第一節、漢諾塔與棧

算法基礎 棧 回文 練習題

1、漢諾塔

漢諾塔(又稱河內塔)問題是源於印度一個古老傳說的益智玩具。大梵天創造世界的時候做了三根柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。

大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。

技術分享圖片

記得高中有道題就是求漢諾塔操作的步驟,當大家還是一籌莫展的時候數學老師給出了遞推公式,真真令人拍案叫絕!

寫程序,求解漢諾塔主要使用了遞歸的思想,會在之後的《算法思想》中講解(如果可以堅持下去的話)。

這裏的每一個塔,就是一個

2、棧

棧屬於線性表,只允許在一端插入(insert,也叫做入棧)和彈出(pop,也叫做出棧)

線性表可以簡單理解為一個數組(或者簡單鏈表),除了第一個和最後一個數據元素之外,其它數據元素都是首尾相接的。

一個棧結構上包含指向棧頂的一個指針以及存儲數據的線性表,主要操作為入棧(push)和出棧(pop)。

技術分享圖片

我們可以用一個數組模擬棧的實現。

使用一個指針(在數據裏面可以用下標)表示棧頂top,最開始top初始化為0表示棧為空,用一個一維數組存儲棧的數據。

//top表示棧頂所在的數組下標,top==0,表示棧為空
int top=0;
//使用一個數組(線性表)保存棧的數據
int a[10];

入棧的過程就是top增長的過程,同時把數據存到數組裏面。
top++為自增操作,等價於,top=top+1

,程序員都是偷懶的!

a[top]=b;top++;這兩行代碼等價於,a[top++]=b;,程序員都是偷懶的!

//入棧
scanf("%d",&b);
//保存數據到棧,棧頂往上移一位
a[top++]=b;

出棧的操作更加簡單了,把top減小一位就好了。

//出棧
top--;

技術分享圖片

2、栗子

判斷回文是學習C語言都會遇到的問題,回文,顧名思義,就是一個正讀和反讀都一樣的字符串,例如ahha、klmlk都是回文,ahhh、pppkhdf不是回文。

“博大精深”的中華傳統文化就有精彩的回文:

信言不美,美言不信。 《道德經八十一》

古代的回文詩也是一絕,有興趣可以自行百度。

那麽對於一串英文字符串,如何使用

判斷是否是回文呢?請思考一下再接著往下看。

思路:

  • 讀入字符串
  • 將字符串的前半段push到棧
  • 從後半段開始,與棧頂元素比較,相等則彈出,不等直接break
  • 最後判斷棧是否為空,不為空則不是回文,否則是回文

3、代碼

這裏是完整代碼,使用C語言

/*
輸入:ahhha
輸出:YES
輸入:lpppp
輸出:NO
*/

#include <stdio.h>
#include <string.h>
int main()
{
    char a[1024], s[1024];
    int i, length, mid, next, top;

    //讀入字符串
    gets_s(a);
    length = strlen(a);
    //註意,數組下標起始是很神奇的存在,多一少一等細節很“恐怖”,需要耐心思考和調試
    mid = length / 2 - 1;

    //棧初始化
    top = 0;
    for (i = 0;i <= mid;i++)
        s[++top] = a[i];

    //判斷字符串長度,確定中間點起始位置
    if (length % 2 == 0)
        next = mid + 1;
    else
        next = mid + 2;

    //開始匹配
    for (i = next;i < length;i++)
    {
        if (a[i] != s[top])
            break;
        top--;
    }

    //top==0,棧為空,全部匹配完成
    if (top == 0)
        printf("YES");
    else
        printf("NO");

    getchar();getchar();
    return 0;
}

第一節、漢諾塔與棧