<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
我們有兩個佇列:
入棧資料1、 2、 3
可以將資料入佇列至佇列一或者佇列二。
如何出棧?
但出棧要先出1,怎麼辦?
第一步:
將佇列一出隊n-1個至佇列二。
第二步:
pop佇列一的最後一個元素。
接下來怎麼入棧呢?
將元素入隊至不為空的佇列。
怎麼判斷棧空?
佇列一和佇列二都為空的情況下,棧就是空的。
如何取棧頂元素?
取不為空的佇列尾部元素。
總的來說就是,入棧時就將資料插入不為空的佇列,出棧就將不為空的佇列的前n-1個資料匯入至另一個佇列,然後pop最後一個元素。
程式碼實現:
首先我們要構造一個棧。
這個棧要包含兩個佇列
typedef struct { Queue q1; Queue q2; } MyStack;
在此之前我們要準備好佇列的一般介面:
我這裡的佇列是用單連結串列來構建的,具體介面實現可以看我之前的文章。
typedef int QTypeData; typedef struct QueueNode { struct QueueNode* next; QTypeData val; }QN; void QueueInit(Queue* pq)//初始化佇列 size_t QueueSize(Queue* pq)//求佇列元素個數 int QueueBack(Queue* pq)//取佇列尾部資料 void QueuePush(Queue* pq, QTypeData x)//將x入隊 void QueuePop(Queue* pq)//出隊 void QueueDestroy(Queue* pq)//結束佇列
我們要用佇列實現棧的介面:
介面一:MyStack* myStackCreate()
這樣做行嗎?
MyStack* myStackCreate() { MyStack ms; QueueInit(&ms.q1); QueueInit(&ms.q2); return ms; }
很顯然,返回區域性變數的地址是不明智的,因為在函數返回時,ms開闢的空間會重新交給作業系統,再次存取就是非法操作。
因此我們需要將ms開闢在堆區。
參考程式碼:
介面二:void myStackPush(MyStack* obj, int x)
入棧簡單:只要將資料插入到不為空的佇列即可。
入棧之前我們需要判斷佇列滿嗎?
不需要,因為我的佇列是用單連結串列實現的,可以無限連結下去。
如果兩個佇列都為空,該插入到哪個佇列呢?
我們可以這樣做,如果佇列1為空,就插入到佇列2,如果不為空,就插入到佇列1.
參考程式碼:
介面三:int myStackPop(MyStack* obj) //出棧
再次回顧一下我們是如何出棧的。
首先我們有兩個佇列
初始狀態它們都是空的
佇列一:空
佇列二:空
入棧1、2、3、4
執行後
佇列一:空
佇列二:1、2、3、4
出佇列只能先出1,如何出4呢?
把1、2、3先出給佇列一
執行後
佇列一:1、2、3
佇列二:4
然後將4用變數記錄並出隊,最後返回記錄4的變數。
執行後
佇列一:1、2、3
佇列二:空。
出隊三板斧
第一步:即將不為空的佇列的前n-1個元素入至為空的佇列。
第二步:將剩下的1個元素用變數記錄,然後將最後一個元素出隊。
第三步:返回用變數記錄的元素。
需要注意的是:如果棧為空,那麼就返回false。
參考程式碼:
介面四:int myStackTop(MyStack* obj) //取棧頂元素
取棧頂元素之前我們需要保證棧不為空
如果棧為空,返回false。
取棧頂元素,即取不為空的佇列的隊尾元素。
參考程式碼:
介面五:bool myStackEmpty(MyStack* obj) //判斷棧是否為空
如果兩個佇列都是空的那麼該棧就是空的。
這裡多提一下,棧的元素個數怎麼求?
棧的元素個數就是那個不為空佇列的元素個數。
參考程式碼:
介面六:void myStackFree(MyStack* obj) //結束棧
參考程式碼:
void myStackFree(MyStack* obj) { QueueDestroy(&obj->q1); QueueDestroy(&obj->q2); free(obj); }
最後需要注意的是:呼叫棧為空的介面時,要先宣告!!
第一次入隊
將資料1出隊操作
將棧1的資料全匯入棧2
然後棧2進行出棧操作
再次入隊5、6、7
直接將5、6、7入棧至棧1
實際我們的對頭和隊尾是這樣的
總的來說:
用兩個棧實現一個佇列,就得把一個棧專門入隊,另一個棧用作出隊。這裡實現的時候我們用棧1做入隊棧,棧2做出隊棧。
也就是說,只要將資料入隊,直接放入棧1.
出隊就直接出棧2的資料,如果棧2為空,這將棧1的資料全部匯入棧2.
佇列的結構體:
typedef struct { ST st1; ST st2; } MyQueue;
我們需要準備的棧
typedef int STDataType; typedef struct Stack { STDataType* data; int top; int capacity; }ST;
這裡我用的是動態陣列實現的棧
需要提前準備棧的介面:
void STInit(ST* p) void STDestroy(ST* p) void STPush(ST* p,STDataType x) void STPop(ST* p) bool STEmpty(ST* p) int STSize(ST* p) STDataType STRear(ST* p)
MyQueue* myQueueCreate()
同樣的,需要把佇列開闢在堆區,同時對棧1和棧2進行初始化。
參考程式碼:
MyQueue* myQueueCreate() { MyQueue* mq=(MyQueue*)malloc(sizeof(MyQueue)); assert(mq); STInit(&mq->st1); STInit(&mq->st2); return mq; }
void myQueuePush(MyQueue* obj, int x)
我們把棧1做入隊棧,棧2做出隊棧。
也就是說,只要將資料入隊,直接放入棧1.
出隊就直接出棧2的資料,如果棧2為空,這將棧1的資料全部匯入棧2.
參考程式碼:
void myQueuePush(MyQueue* obj, int x) { STPush(&obj->st1,x); }
int myQueuePop(MyQueue* obj)
先要判斷佇列是否為空,如果佇列為空則返回false。
其次如果棧2為空,就將棧1的資料全匯入棧2.
參考程式碼:
int myQueuePop(MyQueue* obj) { if(myQueueEmpty(obj)) { return false; } if(STEmpty(&obj->st2)) { int n=STSize(&obj->st1); while(n--) { STPush(&obj->st2,STRear(&obj->st1)); STPop(&obj->st1); } } int ret=STRear(&obj->st2); STPop(&obj->st2); return ret; }
第四個介面:取隊頭元素
int myQueuePeek(MyQueue* obj)
取隊頭元素之前,要判斷佇列是否為空,如果為空,則返回false
隊頭元素即棧2的尾部元素。
但如果棧2為空呢?
那佇列的隊頭元素就是棧1的頭部元素。
參考程式碼:
int myQueuePeek(MyQueue* obj) { if(myQueueEmpty(obj)) { return false; } if(STEmpty(&obj->st2)) { return STFront(&obj->st1); } return STRear(&obj->st2); }
第五個介面:判斷佇列是否為空
bool myQueueEmpty(MyQueue* obj)
佇列為空,需要棧1和棧2都為空。
參考程式碼:
bool myQueueEmpty(MyQueue* obj) { return STEmpty(&obj->st1) && STEmpty(&obj->st2); }
第六個介面:銷燬佇列
void myQueueFree(MyQueue* obj)
參考程式碼:
void myQueueFree(MyQueue* obj) { STDestroy(&obj->st1); STDestroy(&obj->st2); free(obj); }
注意:當使用判斷佇列是否為空的介面時,注意是否在之前宣告過了。
1.用佇列實現棧:
我們需要用兩個佇列實現棧
棧類是於尾插尾刪
佇列是尾插頭刪
第一次入棧:兩個佇列都為空,隨便插入一個佇列都可
第一次出棧:出棧要出的是尾部資料,佇列只能出頭部資料,這是佇列不能直接實現的。
那麼需要將不為空的佇列前n-1個資料匯入至為空的佇列,再將最後一個元素pop掉。
佇列一:1、2、3、4
佇列二:空
那麼匯入後
佇列一:4
佇列二:1、2、3
最後pop最後一個元素
佇列一:空
佇列二:1、2、3、4
再次尾插:尾插至不為空的佇列即可。
2.用棧實現佇列
我們有兩個棧要求實現佇列的一般介面
棧一:空
棧二:空
第一次入隊:入棧至棧一或者棧二都可,這裡選擇棧一。
假設入隊1、2、3、4
棧一:1、2、3、4
棧二:空
出隊:要先出1
將棧一全部匯入棧二
棧一:空
棧二:4、3、2、1
之後入隊就插入至棧一
出隊就pop棧二。
到此這篇關於C語言棧與佇列相互實現詳解的文章就介紹到這了,更多相關C語言 棧與佇列內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45