隊列——解密QQ號

  新學期開始了,小哈是小哼的新同桌(小哈是個小美女哦~),小哼向小哈詢問QQ號,小哈固然不會直接告訴小哼啦,緣由嘛你懂的。因此小哈給了小哼一串加密 過的數字,同時小哈也告訴了小哼解密規則。規則是這樣的:首先將第1個數刪除,緊接着將第2個數放到這串數的末尾,再將第3個數刪除並將第4個數再放到這 串數的末尾,再將第5個數刪除……直到剩下最後一個數,將最後一個數也刪除。按照剛纔刪除的順序,把這些刪除的數連在一塊兒就是小哈的QQ啦。如今你來幫幫 小哼吧。小哈給小哼加密過的一串數是「6 3 1 75 8 9 2 4」。html

 
        OK,如今輪到你動手的時候了。快去找出9張便籤或小紙片,將「6 3 1 75 8 9 2 4」這9個數分別寫在9張便籤上,模擬一下解密過程。若是你沒有理解錯解密規則的話,解密後小哈的QQ號應該是「6 1 5 94 7 2 8 3」。
        其實解密的過程就像是將這些數「排隊」。每次從最前面拿兩個,第1個扔掉,第2個放到尾部。具體過程是這樣的:剛開始這串數是「6 3 1 75 8 9 2 4」,首先刪除6並將3放到這串數的末尾,這串數更新爲「1 7 5 89 2 4 3」。接下來刪除1並將7放到末尾,即更新爲「5 8 9 24 3 7」。再刪除5並將8放到末尾即「9 2 4 3 7 8」,刪除9並將2放到末尾即「4 3 7 8 2」,刪除4並將3放到末尾即「7 8 2 3」,刪除7並將8放到末尾即「2 3 8」,刪除2並將3放到末尾即「8 3」,刪除8並將3放到末尾即「3」,最後刪除3。所以被刪除的順序是「6 1 5 9 4 7 2 8 3」,這就是小哈的QQ號碼了,你能夠加她試試看^_^。
        既然如今已經搞清楚瞭解密法則,不妨本身嘗試一下去編程,我相信你必定能夠寫出來的。
        首先須要一個數組來存儲這一串數即intq[101]。並初始化這個數組即intq[101]={0,6,3,1,7,5,8,9,2,4};(此 處初始化是我多寫了一個0,用來填充q[0],由於我比較喜歡從q[1]開始用,對數組初始化不是很理解的同窗能夠去看下個人上一本書《啊哈C!思考快你 一步》)接下來就是模擬解密的過程了。
        解密的第一步是將第一個數刪除,你能夠想一下如何在數組中刪除一個數呢?最簡單的方法是將全部後面的數都往前面挪動一位,將前面的數覆蓋。就比如我 們在排隊買票,最前面的人買好離開了,後面全部的人就須要所有向前面走一步,補上以前的空位,可是這樣的作法很耗費時間。
 

 

        在這裏,我將引入兩個整型變量head和tail。head用來記錄隊列的隊首(即第一位),tail用來記錄隊列的隊尾(即最後一位)的下一個位 置。你可能會問爲何tail不直接記錄隊尾,卻要記錄隊尾的下一個位置呢?這是由於當隊列當中只剩下一個元素時,隊首和隊尾重合會帶來一些麻煩。咱們這 裏規定隊首和隊尾重合時,隊列爲空。
        如今有9個數,9個數所有放入隊列以後head=1;tail=10;此時head和tail之間的數就是目前隊列中「有效」的數。若是要刪除一個 數的話,就將head++就OK了,這樣仍然能夠保持head和tail之間的數爲目前隊列中「有效」的數。這樣作雖然浪費了一個空間,卻節省了大量的時 間,這是很是划算的。新增長一個數也很簡單,把須要增長的數放到隊尾即q[tail]以後再tail++就歐克啦。
 
        咱們來小結一下,在隊首刪除一個數的操做是head++;
        在隊尾增長一個數(假設這個數是x)的操做是q[tail]=x;tail++;
        整個解密過程,請看下面這個霸氣外漏的圖。
 
        最後的輸出就是6 1 5 94 7 2 8 3,代碼實現以下。
 
#include <stdio.h>
int main() { int q[102]={0,6,3,1,7,5,8,9,2,4},head,tail; int i; //初始化隊列 head=1; tail=10; //隊列中已經有9個元素了,tail執向的隊尾的後一個位置 while(head<tail) //當隊列不爲空的時候執行循環  { //打印隊首並將隊首出隊 printf("%d ",q[head]); head++; //先將新隊首的數添加到隊尾 q[tail]=q[head]; tail++; //再將隊首出隊 head++; } getchar();getchar(); return 0; }
 

 

        怎麼樣上面的代碼運行成功沒有?如今咱們再來總結一下隊列的概念。隊列是一種特殊的線性結構,它只容許在隊列的首部(head)進行刪除操做稱之爲 「出隊」,而在隊列的尾部(tail)進行插入操做稱之爲「入隊」。當隊列中沒有元素時(即head==tail),稱爲空隊列。在咱們的平常生活中有很 多狀況都符合隊列的特性。好比咱們以前提到過的買票,每一個排隊買票的窗口就是一個隊列。在這個隊列當中,新來的人老是站在隊列的最後面,來的越早的人越靠 前也就越早能買到票,就是先來的人先服務,咱們稱爲「先進先出」(First InFirst Out,FIFO)原則。
        隊列將是咱們從此學習廣度優先搜索以及隊列優化的Bellman-Ford最短路算法的核心數據結構。因此如今將隊列的三個基本元素(一個數組,兩個變量)封裝爲一個結構體類型,以下。
struct queue { int data[100];//隊列的主體,用來存儲內容 int head;//隊首 int tail;//隊尾 };

 

        上面咱們定義了一個結構體類型,咱們一般將其放在main函數的外面,請注意結構體的定義末尾有個;號。struct是結構體的關鍵字,queue 是咱們爲這個結構體起的名字。這個結構體有三個成員分別是:整型數組data、整型head和整型tail。這樣咱們就能夠把這三個部分放在一塊兒做爲一個 總體來對待。你能夠這麼理解:咱們定義了一個新的數據類型,這個新類型很是強大,用這個新類型定義出的每個變量能夠同時存儲一個整型數組和兩個整數。
 
 
        有了新的結構體類型,如何定義結構體變量呢?很簡單,這與咱們以前定義變量的方式是同樣,以下。
struct queue q;

 

        請注意struct queue須要總體使用,不能直接寫queue q;這樣咱們就定義了一個結構體變量q。這個結構體變量q就能夠知足隊列的全部操做了。那又該如何訪問結構體變量的內部成員呢?可使用.號,它叫作成員運算符或者點號運算符,以下:
q.head=1; q.tail=1; scanf("%d",&q.data[q.tail]);

 

        好了,下面這段代碼就是使用結構體來實現的隊列操做。
 
#include <stdio.h>
struct queue { int data[100];//隊列的主體,用來存儲內容 int head;//隊首 int tail;//隊尾 }; int main() { struct queue q; int i; //初始化隊列 q.head=1; q.tail=1; for(i=1;i<=9;i++) { //依次向隊列插入9個數 scanf("%d",&q.data[q.tail]); q.tail++; } while(q.head<q.tail) //當隊列不爲空的時候執行循環  { //打印隊首並將隊首出隊 printf("%d ",q.data[q.head]); q.head++; //先將新隊首的數添加到隊尾 q.data[q.tail]=q.data[q.head]; q.tail++; //再將隊首出隊 q.head++; } getchar();getchar(); return 0; }
 

 

        上面的這種寫法看起來雖然冗餘了一些,可是能夠增強你對隊列這個算法的理解。C++的STL庫已經有隊列的實現,有興趣的同窗能夠參看相關材料。隊 列的起源已經沒法追溯。在尚未數字計算機以前,數學應用中就已經有對隊列的記載了。咱們生活中隊列的例子也比比皆是,好比排隊買票,又或者吃飯時候用來 排隊等候的叫號機,又或者撥打銀行客服選擇人工服務時,每次都會被提示「客服人員正忙,請耐心等待」,由於客服人員太少了,撥打電話的客戶須要按照打進的 時間順序進行等候等等。這裏表揚一下肯德基的宅急送,沒有作廣告的嫌疑啊,每次一打就通,基本不須要等待。可是我每次打銀行的客服(具體是哪家銀行就不點 名了)基本都要等待很長時間,老是告訴我「正在轉接,請稍後」,嘟嘟嘟三聲後就變成「客服正忙,請耐心等待!」而後就給我放很難聽的曲子。看來錢在誰那裏 誰就是老大啊……

轉自http://bbs.ahalei.com/thread-4489-1-1.html算法

相關文章
相關標籤/搜索