【坐在馬桶上看算法】算法5:解密回文——棧


        上一節中我們學習了隊列,它是一種先進先出的數據結構。還有一種是后進先出的數據結構它叫做棧。棧限定只能在一端進行插入和刪除操作。比如說有一個小桶,小桶的直徑只能放一個小球,我們現在向小桶內依次放入2號、1號、3號小球。假如你現在需要拿出2號小球,那就必須先將3號小球拿出,再拿出1號小球,最后才能將2號小球拿出來。在剛才取小球的過程中,我們最先放進去的小球最后才能拿出來,而最后放進去的小球卻可以最先拿出來。這就是后進先出,也可以稱為先進后出。
 
        我們生活中還有很多這樣的例子,比如我們在吃桶裝薯片的時候,要想吃掉最后一片,就必須把前面的全部吃完(貌似現在的桶裝薯片為了減少分量,在桶里面增加了一個透明的抽屜);再比如我們瀏覽網頁時候需要退回到之前的某個網頁,我們需要一步步的點擊后退鍵。還有手-槍的彈夾,在裝子彈的時候,最后裝的一發子彈,是被第一個打出去的。棧的實現也很簡單,只需要一個一維數組和一個指向棧頂的變量top就可以了。我們通過變量top來對棧進行插入和刪除操作。
 
        這種特殊的數據結構棧究竟有哪些作用呢?我們來看一個例子。“xyzyx”是一個回文字符串,所謂回文字符串就是指正讀反讀均相同的字符序列,如“席主席”、“記書記”、“aha”和“ahaha”均是回文,但“ahah”不是回文。通過棧這個數據結構我們將很容易判斷一個字符串是否為回文。
 
        首先我們需要讀取這行字符串,並求出這個字符串的長度。
char a[101]; //101是一個估算值,只需比待讀入的字符串長度大即可
int len;
gets(a);
len=strlen(a);

        如果一個字符串是回文的話,那么它必須是中間對稱,我們需要求這個字符串的 中點,即:
mid=len/2-1;
        接下來就輪到棧出場了。
        我們先將mid之前的部分的字符全部入棧。因為這里的棧是用來存儲字符的,所以這里用來實現棧的數組類型是字符數組即char s[101]; 初始化棧很簡單,top=0;就可以了。入棧的操作是top++;s[top]=x; (假設需要入棧的字符存儲暫存在字符變量x中)其實可以簡寫為s[++top]=x;
        現在我們就來將mid之前的字符依次全部入棧。這里循環要0開始,因為剛才讀取字符串使用了gets()函數,讀取的第一個字符存儲在s[0]中,隨后一個字符存儲在s[len-1]中。
for(i=0;i<=mid;i++)
{
    s[++top]=a[i];
}

        接下來進入判斷回文的關鍵步驟。將當前棧中的字符依次出棧,看看是否能與mid之后的字符一一匹配,如果都能匹配則說明這個字符串是回文字符串,否則這個字符串就不是回文字符串。
for(i=mid+1;i<=len-1;i++) //其實這里並不一定是mid+1,需要討論字符串長度的奇偶性
{
    if (a[i]!=s[top])
    {
          break;
    }
    top--;
}
if(top==0)
    printf("YES");
else
    printf("NO");

 

        最后如果top的值為0,就說明棧內所有的字符都被一一匹配了,那么這個字符串就是回文字符串。完整的代碼如下。
#include <stdio.h>
#include <string.h>
int main()
{
    char a[101],s[101];
    int i,len,mid,next,top;
   
    gets(a); //讀入一行字符串
    len=strlen(a); //求字符串的長度
    mid=len/2-1; //求字符串的中點
   
    top=0;//棧的初始化
    //將mid前的字符依次入棧
    for(i=0;i<=mid;i++)
        s[++top]=a[i];
   
    //判斷字符串的長度的是奇數還是偶數,並找出需要進行字符匹配的起始下標   
    if(len%2==0)
        next=mid+1;
    else
        next=mid+2;
                  
    //開始匹配
    for(i=next;i<=len-1;i++)
    {
        if(a[i]!=s[top])
            break;
        top--;
    }
   
    //如果top的值為0,則說明棧內的所有的字符都被一一匹配了
    if(top==0)
        printf("YES");
    else
        printf("NO");
getchar();getchar();
return 0; }
        可以輸入以下數據進行驗證
ahaha
        運行結果是
YES

 

        棧還可以用來進行驗證括號的匹配。比如輸入一行只包含“()[]{}”的字符串,形如“([{}()])”或者“{()[]{}}”請判斷是否可以正確匹配。顯然上面兩個例子都是可以正確匹配的。“([)]”是不能匹配的。有興趣的同學可以自己動手來試一試。
        堆棧最早由Alan M. Turing(艾倫·圖靈)於1946年提出,當時為了解決子程序的調用和返回。艾倫·圖靈這個大帥哥可是個大牛人,圖靈獎就是以他的名字命名的。如果你對他感興趣不妨去讀一讀他的傳記《艾倫•圖靈傳:如謎的解謎者》。
 
碼字不容易啊,轉載麻煩注明出處
【一周一算法】算法5:解密回文——棧
(出處: 啊哈磊_編程從這里起步)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM