DS博客作業03--棧和隊列


1.本周學習總結

本周對棧和隊列進行了學習,就總體而言,難度不大。通過課本上對於棧和隊列的基本操作函數的學習,不僅學會了如何入棧出棧、入隊出隊,而且了解了棧空、棧滿的條件,並了解了共享棧、鏈棧、循環隊列......等更深入的知識。有過之前對於順序表的學習,這些都還是比較簡單的。當然,無論是棧的后入先出還是隊列的先入先出,需要對棧和隊列的概念的理解要深刻,有同學這么和我說道,棧就像是一個單向開口的羽毛球桶,放球進去,取球出來,棧的后入先出就再也不會忘記了;而隊列更簡單,隊列就像是生活當中的隊伍一般,又或者,理解為水管,水流的流向就是那樣,水先入先出......我覺得這樣的描述很形象,有可取之處,哈哈。再之后就是對於c++的stl容器的使用了,目前接觸到了stack(棧)和queue(隊列),這兩種模板很實用,但第一次使用的我還是掉入了一些初學者容易犯的錯誤中去。問題一:在調用模板的函數時沒有加括號,如要對棧s調用pop函數,寫成了s.pop,導致程序崩潰,直接報錯了,如圖一、二;問題二:在調用pop函數時,缺乏對是否棧(隊列)是否為空的判斷,導致程序奔潰,如圖三。這些問題注意之后,對這些模板的應用基本沒什么問題,無非就是缺解決問題的思路了。

2.PTA實驗作業

2.1.題目1:題目名稱

6-2 在一個數組中實現兩個堆棧 (20 分)
本題要求在一個數組中實現兩個堆棧。注意:如果堆棧已滿,Push函數必須輸出“Stack Full”並且返回false;如果某堆棧是空的,則Pop函數必須輸出“Stack Tag Empty”(其中Tag是該堆棧的編號),並且返回ERROR。

2.1.1設計思路

函數題思路不寫啦......這里丟一下Operation GetOp(); /* details omitted */函數和void PrintStack( Stack S, int Tag ); /* details omitted */函數,當時用來測試數據時保留下了......有需要的可以拿去試試pta測試數據。

Operation GetOp()
{
	Operation c;
	char a[5];
	scanf("%s", a);
	if (!strcmp(a, "Push"))
		return push;
	else if (!strcmp(a, "Pop"))
		return pop;
	else if (!strcmp(a, "End"))
		return end;
}
void PrintStack(Stack S, int Tag) 
{
	int i;
	switch (Tag)
	{
		case 1:
			printf("Pop from Stack 1:");
			for (i = S->Top1; i >= 0; i--)
			{
				printf("%d ", S->Data[i]);
			}
			printf("\n");
			break;
		case 2:
			printf("Pop from Stack 2:");
			for (i = S->Top2; i <= S->MaxSize-1; i++)
			{
				printf("%d ", S->Data[i]);
			}
			printf("\n");
			break;
	}
}

2.1.2代碼截圖

2.1.3本題PTA提交列表說明。

  • 問題一:第一次提交錯誤是因為在判斷棧滿時出現了疏忽如圖:

    寫成了:
  • 問題二:這里有一個隱藏的問題,極大的影響了上機考試......在后面考試錯題詳細展開講。

2.2 題目2

7-3 符號配對 (20 分)
請編寫程序檢查C語言源程序中下列符號是否配對://、(與)、[與]、{與}。輸入為一個C語言源程序。當讀到某一行中只有一個句點.和一個回車的時候,標志着輸入結束。程序中需要檢查配對的符號不超過100個。首先,如果所有符號配對正確,則在第一行中輸出YES,否則輸出NO。然后在第二行中指出第一個不配對的符號:如果缺少左符號,則輸出?-右符號;如果缺少右符號,則輸出左符號-?。

2.2.1設計思路

首先是建立兩個字符串(左符號字符串和右符號字符串,同時左右配對字符在字符串中的位置相同,以便於后面使用string類的find函數來判斷符號是否配對)。解決題目的中心思路是,利用c++的棧模板,當遇到左括號時入棧,當遇到右括號時,與棧頂符號配對是否成功(用find函數)。當然要先考慮一些情況,如在棧為空的時候,讀取到了右符號(缺乏左符號),或在字符串讀取結束時,棧中有多余左符號。本題還要求對注釋符號 / * * / 也進行匹配。原思路是頭鐵地連續判斷兩個字符來判斷是否是 / *或者 * /,之后再把/當作左符號(可入棧),匹配時與 * / 進行匹配。但這種處理方式存在嚴重的短板,即在遇到連續兩個左注釋符、連續兩個右注釋符等情況時,可能會導致 / / 反復讀取,如連續兩個左注釋符應該讀為兩個左注釋符,而容易誤讀為兩個左注釋符和一個右注釋符,導致出錯。改進方向——>在輸入字符串后,直接對題目中的注釋符進行預處理(**將 左注釋符和 右注釋符轉化為<>,同時放入左右符號字符串中一並用find函數來判斷),而不是在判斷時下大功夫。

2.2.2代碼截圖


2.2.3本題PTA提交列表說明。

2.3 題目3

6-12 jmu-ds-舞伴問題 (20 分)
假設在周末舞會上,男士和女士們分別進入舞廳,各自排成一隊。跳舞開始,依次從男隊和女隊隊頭各出一人配成舞伴,若兩隊初始人數不同,則較長那一隊未配對者等待下一輪舞曲。現要求寫一算法模擬上述舞伴配對問題。 你需要用隊列操作實現上述算法。請完成下面5個函數的操作。先輸入參加舞會人數,再分別輸入參加舞會人的姓名和性別,先輸出配對的男女舞伴,若隊伍有剩人,則輸出剩下人性別及剩下人數目。函數接口定義:int QueueLen(SqQueue Q);//隊列長度 、int EnQueue(SqQueue &Q, Person e);//加入隊列 、int QueueEmpty(SqQueue &Q);//隊列是否為空 、int DeQueue(SqQueue &Q, Person &e);//出隊列 、void DancePartner(Person dancer[], int num); //配對舞伴

2.3.1設計思路

先把所有參加晚會的人分為男隊Mdancers和女隊 Fdancers,分隊結束后,男隊女隊再同時各出隊一人男女配對,直至至少有一隊沒人,操作結束后有兩種情況,兩隊均結束,無人多余;或有一隊剩余,在main函數中題目自帶處理,無需再處理......有點像以前的二路歸並的方法,同時從兩串數據中取一個數據,直至一方結束,再對剩下的數據進行輸出處理。

2.3.2代碼截圖


2.3.3本題PTA提交列表說明。

  • 問題一:錯用c++語法,沒有仔細看題目的頭文件。
  • 問題二:測試數據居然要求在男性和女性名字間有兩個空格......被坑了¥*@#&%#$‖<&>

2.4 題目4

7-5 jmu-報數游戲 (15 分)
報數游戲是這樣的:有n個人圍成一圈,按順序從1到n編好號。從第一個人開始報數,報到m(m<n)的人退出圈子;下一個人從1開始報數,報到m的人退出圈子。如此下去,直到留下最后一個人。其中n是初始人數;m是游戲規定的退出位次(保證為小於n的正整數)。要求用隊列結構完成。輸出數字間以空格分隔,但結尾不能有多余空格。

2.4.1設計思路

n個人從1開是編號,即人的編號為1到n。本題的中心解題思路為,用一個名為i的變量來充當個人所報的數,當i達到題目要求的數m(即這個人應該出隊),再將i歸零(出隊者的下一個人從0開始繼續報數)。持續此操作直到隊伍只剩一人。

2.4.2代碼截圖

2.4.3本題PTA提交列表說明。

  • 問題一:......真不是故意的......要求隊列要有編程題,兩題都是這樣的......先這樣,等后面的打完了再看看改。

3、棧和隊列上機考試

這次上機考不理想,首先選擇題開始就沒做好,其次主要是在一題做過的題目上花了大量的時間(遇到了以前從來沒有遇到過的問題報錯)折騰太久了以至於后面的題目都沒打,所以這里的錯題就選擇那題苦惱了很久的題目和選擇題。

第一題:選擇題錯題

第二題:6-2 在一個數組中實現兩個堆棧 (20 分)

首先看看我在原題集的提交列表:

再看看我在考試的時候的提交列表:

這題出錯的心理原因有兩個,第一個問題是在原題集做的時候較為順利,所以不知不覺中直接過了所有的點,沒有理解透徹題目,稀里糊塗,很有自信開考五分鍾就打出來了,但是過不了......;第二個問題是,首次見到了輸出超限這個錯誤點,在考試時突然見到這個很懵逼,慌亂了。
這題的真正原因在於,在判斷棧滿時應該分開判斷,而不是同時判斷!
錯誤代碼如下:

應該改成這樣:

  • 后續需要改進的地方:遇到未見過的問題,應該冷靜分析,而不是慌亂不知所措。其實有時候,一些小問題一下子想不出來,應該先打其他題目冷靜一下,再回過頭來看。


免責聲明!

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



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