棧:是限定僅在表尾進行插入和刪除操作的線性表(順序結(jié)構(gòu))
棧頂:允許插入跟刪除的一端
棧底:固定的一端,不允許在棧底進行插入跟刪除
入棧:棧的插入操作
出棧:棧的刪除操作
目錄
定義棧
創(chuàng)建空棧
?入棧
?出棧
?源代碼
定義棧
#include<stdio.h>
#include<malloc.h>
#define ok 1
#define error 0
#define sizemax 10
typedef int ElemType;
typedef struct {
ElemType *base;//棧底
ElemType *top;//棧頂
int sizestack;//分配棧的值
}Sqstack;//定義棧
此處定義棧的最大值為10,當然如果需要后續(xù)分配更大的內(nèi)存空間,可以使用realloc函數(shù)增加新的空間(作者還沒學會使用)。
創(chuàng)建空棧
int initstack(Sqstack* s) {
s->base = (ElemType*)malloc(sizeof(ElemType) * SIZEMAX);//給base分配內(nèi)存空間,返回base的首地址
if (!s->base) {
return error;
}
s->top = s->base;//出發(fā)點為base的首地址,棧頂從底地址開始
s->sizestack = SIZEMAX;//最大空間
return ok;
}//創(chuàng)建空棧
創(chuàng)建空棧,就需要給棧底分配一塊內(nèi)存空間,將棧底的首地址返回,就可以通過棧底首地址對棧進行修改。所以將棧底的首地址賦值給棧底(s->top),就可以對棧底進行修改了。
圖解:
值得注意的是,棧底的首地址不一定是從0開始的,而是這里為了方便圖片的展示而寫成0。由于用了malloc函數(shù),編譯器給s->base的地址是隨機分配的,如果需要查看真正的地址,可以調(diào)試監(jiān)控窗口查看。
?入棧
int push(Sqstack* s, ElemType e) {
if (s->top - s->base == SIZEMAX ) {
printf("棧滿,無法入棧\n");
return error;
}
*(s->top) = e;//(由于s是指針,想要將里面的值賦值,需要帶上*號)
s->top++;
return ok;
}//入棧
入棧前首先要判斷棧是否滿了,這里可以用s->top-s->base的值判斷是否滿了(地址的分配原理),將輸入的值賦值給棧頂,用指針對地址里面的值修改,必須要用上星號(指針的原理)。那么問題就來了,是先插入在進行棧頂指針的自增呢,還是先棧頂指針自增在插入呢?動動小腦袋瓜來思考一下,在定義棧的時候,博主將棧底的地址賦值給棧頂指針,入棧時,將e的值賦值給此處棧頂指針,如果先進行指針自增,那么執(zhí)行到插入時,他后面的那一個空棧就會跳過了,此時插入的空間是自增后的那個空間,造成空間浪費,不理解的同學可以上機實踐,看看調(diào)換這個語句的順序會發(fā)生什么。
?正確的做法是先插入,棧頂指針在自增。
?出棧
int pop(Sqstack* s, ElemType *e) {
if (s->top == s->base) {
return error;
}
s->top--;//先--是因為輸入的最后一個值是非整形的,需要忽略非整形的字符
*e = *(s->top);
return ok;
}//出棧
出棧前要判斷棧是否為空,判斷條件是s->top=s->base? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?在動動小腦瓜思考,這里為什么又要先棧頂指針自減在賦值給*e,這就涉及到另一個模塊的代碼了
int creatstack(Sqstack* s) {
int e;
if (initstack(s)) {
printf("棧創(chuàng)建成功!\n");
}
else {
printf("棧創(chuàng)建失敗\n");
return error;
}
printf("請輸入數(shù)據(jù)\n");
while (scanf("%d", &e))
push(s, e);
return ok;
}//創(chuàng)建并輸入
在這個函數(shù)中,我們調(diào)用創(chuàng)建棧的函數(shù),創(chuàng)建成功后進行入棧操作
while (scanf("%d", &e))
push(s, e);
我們使用scanf輸入要入棧的值,由于我們定義的是整形,輸入的也是整形,這里介紹一下scanf的返回值,是成功讀入?yún)?shù)的個數(shù),我們都知道,判定條件,0為假,非0為真。當輸入多組整數(shù)時,按下回車后,這些整數(shù)會進入緩沖區(qū)中,然后scanf函數(shù)會一個個讀取緩沖區(qū)中的數(shù)據(jù),當讀取到一個整數(shù)時返回值是1,當讀到非整數(shù)的值時,返回值是0,因此在while中,想要讓這個輸入循環(huán)停止,就要輸入一個非整數(shù)的值,比如字母a,但是在入棧的時候,輸入非整數(shù)的值仍然會保持在棧中,因此在出棧中,要錯開這個值,所以在出棧函數(shù)中,首先要棧頂指針先自減,在將棧存儲的值賦值給指針*e。
如果先賦值在自減出棧時就會造成如下錯誤:
?輸出了非整數(shù)的值,并且還造成了棧里面的內(nèi)容丟失
?正確操作是先自減在賦值:
?圖解:
文章來源:http://www.zghlxwxcb.cn/news/detail-714561.html
?源代碼
#include<stdio.h>
#include<malloc.h>
#define ok 1
#define error 0
#define SIZEMAX 10
typedef int ElemType;
typedef struct {
ElemType *base;//棧底
ElemType *top;//棧頂
int sizestack;//分配棧的值
}Sqstack;//定義棧
int initstack(Sqstack* s) {
s->base = (ElemType*)malloc(sizeof(ElemType) * SIZEMAX);//給base分配內(nèi)存空間,返回base的首地址
if (!s->base) {
return error;
}
s->top = s->base;//出發(fā)點為base的首地址,棧頂從底地址開始
s->sizestack = SIZEMAX;//最大空間
return ok;
}//創(chuàng)建空棧
int push(Sqstack* s, ElemType e) {
if (s->top - s->base == SIZEMAX ) {
printf("棧滿,無法入棧\n");
return error;
}
*(s->top) = e;//(由于s是指針,想要將里面的值賦值,需要帶上*號)
s->top++;
return ok;
}//入棧
int pop(Sqstack* s, ElemType *e) {
if (s->top == s->base) {
return error;
}
s->top--;//先--是因為輸入的最后一個值是非整形的,需要忽略非整形的字符
*e = *(s->top);
return ok;
}//出棧
int creatstack(Sqstack* s) {
int e;
if (initstack(s)) {
printf("棧創(chuàng)建成功!\n");
}
else {
printf("棧創(chuàng)建失敗\n");
return error;
}
printf("請輸入數(shù)據(jù)\n");
while (scanf("%d", &e))
push(s, e);
return ok;
}//創(chuàng)建并輸入
int printstack(Sqstack* s) {
ElemType e;
while (pop(s, &e))
printf("%3d", e);
return ok;
}//出棧并且輸出
int main() {
Sqstack s;
printf("創(chuàng)建并輸出\n");
creatstack(&s);
printf("出棧并且輸出\n");
printstack(&s);
return 0;
}
?文章來源地址http://www.zghlxwxcb.cn/news/detail-714561.html
到了這里,關于順序棧的入棧與出棧-----(c語言)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!