数据结构与算法(C语言) | 栈和队列——栈(自己做过测试)
棧是一種重要的線性結(jié)構(gòu),通常稱,棧和隊(duì)列是限定插入和刪除只能在表的“端點(diǎn)”進(jìn)行的線性表。(后進(jìn)先出)
–棧的元素必須“后進(jìn)先出”。
–棧的操作只能在這個(gè)線性表的表尾進(jìn)行。
–注:對(duì)于棧來(lái)說(shuō),這個(gè)表尾稱為棧的棧頂(top),相應(yīng)的表頭稱為棧底(bottom)。
?因?yàn)闂5谋举|(zhì)是一個(gè)線性表,線性表有兩種存儲(chǔ)形式,那么棧也有分為棧的順序存儲(chǔ)結(jié)構(gòu)和棧的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)。
?最開始棧中不含有任何數(shù)據(jù),叫做空棧,此時(shí)棧頂就是棧底。然后數(shù)據(jù)從棧頂進(jìn)入,棧頂棧底分離,整個(gè)棧的當(dāng)前容量變大。數(shù)據(jù)出棧時(shí)從棧頂彈出,棧頂下移,整個(gè)棧的當(dāng)前容量變小。
?
//棧的順序存儲(chǔ)結(jié)構(gòu)
typedef struct
{
? ? ElemType *base;
? ? ElemType *top;
? ? int stackSize;
}sqStack;
?????????????????????????????????????????????????????????????順序棧
//----- 棧的動(dòng)態(tài)分配順序存儲(chǔ)結(jié)構(gòu) -----
#define STACK_INIT_SIZE 100 ? //順序棧初始容量
#define STACKINCREMENT ?10 ? ? //順序棧容量增量
typedef struct {
? ? SElemType ?*base; ? ? //順序棧基地址(棧底指針)
? ? SElemType ?*top; ? ? ? //棧頂指針
? ? int ? ? ? ? ? ?stacksize; ? ?//順序棧當(dāng)前存儲(chǔ)容量
}SqStack;
初始化
//----- 基本操作的算法描述 -----
Status InitStack( SqStack &S ) {
? ? // 構(gòu)造一個(gè)空棧 S
? ? S.base=(SElemType*)malloc
? ? ? ? ? ? ? ? ?(STACK_INIT_SIZE*sizeof(SElemType));
? ? if ?(!S.base) exit(OVERFLOW); ? ?// 存儲(chǔ)分配失敗
? ? S.top = S.base; ?
? ? S.stacksize = STACK_INIT_SIZE; ??
? ? return OK;
}//InitStack?
返回棧頂元素
Status GetTop( SqStack S, SElemType &e ) {
? ? // 若棧不空,則用 e 返回 S 的棧頂元素,并返回 OK;
? ? ?// 否則返回 ERROR
? ? if ?(S.top = = S.base) ?return ERROR;
? ? e = *(S.top-1); ?
? ? return OK;
}//GetTop?
壓入棧
Status Push( SqStack &S, ?SElemType e ) {
? ? // 在棧 S 中插入元素 e 為新的棧頂元素
? ? if (S.top-S.base>=S.stacksize) { // 棧滿,追加存儲(chǔ)空間?
? ? ? ?newbase=(SElemType*)realloc(S.base, ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? (S.stacksize+STACKINCREMENT)*sizeof(SElemType));
? ? ? ?if ?(!newbase) exit(OVERFLOW); ? ?// 存儲(chǔ)分配失敗
? ? ? ?S.base = newbase;
? ? ? ?S.top = S.base+S.stacksize; ?
? ? ? ?S.stacksize += STACKINCREMENT;?
? ? }
? ? *S.top++ = e; ?
? ? return OK;
}//Push?
彈出棧
Status Pop( SqStack S, SElemType &e ) {
? ? // 若棧不空,則刪除 S 的棧頂元素,用 e 返回其值,
? ? ?// 并返回 OK; 否則返回 ERROR
? ? if ?(S.top = = S.base) ?return ERROR;
? ? e = *--S.top; ?
? ? return OK;
}//Pop?
????????
注:c語(yǔ)言中->和.的區(qū)別——->用于指針, .用于對(duì)象
"->"用于指向結(jié)構(gòu)成員,它的左邊應(yīng)為指向該結(jié)構(gòu)類型的指針(結(jié)構(gòu)指針),而"."的左邊應(yīng)為該結(jié)構(gòu)類型的變量(結(jié)構(gòu)變量),如已定義了一個(gè)結(jié)構(gòu)體struct student,里面有一個(gè)int a;然后有一個(gè)結(jié)構(gòu)體變量struct student stu及結(jié)構(gòu)體變量指針struct student *p;且有p=&stu,那么p->a和stu.a表示同一個(gè)意思。
?
????????????????????????????????????????????????????
實(shí)例分析:
?題目:利用棧的數(shù)據(jù)結(jié)構(gòu)特點(diǎn),將二進(jìn)制轉(zhuǎn)換為十進(jìn)制數(shù)。
?分析:地球人都知道,二進(jìn)制數(shù)是計(jì)算機(jī)數(shù)據(jù)的存儲(chǔ)形式,它是由一串0和1組成的,每個(gè)二進(jìn)制數(shù)轉(zhuǎn)換成相應(yīng)的十進(jìn)制數(shù)方法如下:
(XnXn-1……X3X2X1)2 = X1*2^0+X2*2^1+…+Xn*2^(n-1)
?一個(gè)二進(jìn)制數(shù)要轉(zhuǎn)換為相應(yīng)的十進(jìn)制數(shù),就是從最低位起用每一位去乘以對(duì)應(yīng)位的積,也就是說(shuō)用第n位去乘以2^(n-1),然后全部加起來(lái)。
由于棧具有后進(jìn)先出的特性,例如我們輸入11001001這樣的二進(jìn)制數(shù)
?
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
?
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
?
typedef char ElemType;
typedef struct
{
? ? ElemType *base;
? ? ElemType *top;
? ? int stackSize;
}sqStack;
?
void InitStack(sqStack *s)
{
? ? s->base = (ElemType *)malloc(STACK_INIT_SIZE*sizeof(ElemType));
? ? if(!s->base)
? ? {
? ? ? ? exit(0);
? ? }
? ? s->top = s->base;
? ? s->stackSize = STACK_INIT_SIZE;
}
?
void Push(sqStack *s,ElemType e)
{
? ? if(s->top-s->base >= s->stackSize )
? ? {
? ? ? ? s->base = (ElemType *)realloc(s->base,(s->stackSize + STACKINCREMENT)*sizeof(ElemType));
? ? ? ? if(!s->base)
? ? ? ? {
? ? ? ? ? ? exit(0);
? ? ? ? }
? ? s->top = s->base + s->stackSize;
? ? s->stackSize = s->stackSize + STACKINCREMENT;
? ? }
? ? *(s->top) = e;
? ? s->top++;
?
}
void Pop(sqStack *s,ElemType *e)
{
? ? if(s->top == s->base)
? ? {
? ? ? ? return;
? ? }
? ? *e = *--(s->top);
}
?
int StackLen(sqStack s)
{
? ? return (s.top - s.base);
? ? //不是地址的相減而是內(nèi)容
}
int main()
{
? ? ElemType c;
? ? sqStack s;
? ? int len, i, sum = 0;
? ? InitStack(&s);
? ? printf("請(qǐng)輸入二進(jìn)制書,輸入#符號(hào)表示結(jié)束!\n");
? ? scanf("%c",&c);
? ? while(c!= '#')
? ? {
? ? ? ? Push(&s, c);
? ? ? ? scanf("%c",&c);
? ? }
? ? //清理鍵盤緩沖區(qū) 回車的ASCII=10
? ? getchar();
? ? len = StackLen(s);
? ? printf("棧的當(dāng)前容量是:%d\n",len);
? ? for(i=0; i<len ; i++)
? ? {
? ? ? ? Pop(&s,&c);
? ? ? ? sum = sum + (c-48) * pow(2, i);
? ? }
? ? printf("轉(zhuǎn)化為十進(jìn)制為:%d \n",sum);
? ? return 0;
}
二進(jìn)制轉(zhuǎn)化為八進(jìn)制、二進(jìn)制轉(zhuǎn)化為十六進(jìn)制:
二進(jìn)制每三位轉(zhuǎn)化為一個(gè)八進(jìn)制
修改一下以上的主函數(shù)部分:
int main()
{
? ? ElemType c;
? ? sqStack s1;
? ? sqStack s2;
? ? int len, i, j, sum = 0;
?
? ? InitStack(&s1); // 初始化棧s1,用來(lái)存放二進(jìn)制輸入
?
? ? printf("請(qǐng)輸入二進(jìn)制數(shù),輸入‘#’號(hào)表示結(jié)束!\n\n");
? ? scanf("%c", &c);
? ? while( c != '#' )
? ? {
? ? ? ? if( c=='0' || c=='1' ) ?// 檢查輸入是否二進(jìn)制
? ? ? ? ? ? Push(&s1, c);
? ? ? ? scanf("%c", &c);
? ? }
? ? getchar(); ? ? ?// 把'\n'從緩沖區(qū)去掉
? ? len = StackLen(s1);
?
? ? InitStack(&s2); // 初始化棧s2,用來(lái)存放轉(zhuǎn)換的八進(jìn)制
?
? ? for( i=0; i < len; i+=3 )
? ? {
? ? ? ? for( j=0; j < 3; j++ )
? ? ? ? {
? ? ? ? ? ? Pop( &s1, &c ); // 取出棧頂元素
? ? ? ? ? ? sum = sum + (c-48) * pow(2, j);
?
? ? ? ? ? ? if( s1.base == s1.top )
? ? ? ? ? ? {
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? Push( &s2, sum+48 );
? ? ? ? sum = 0;
? ? }
?
? ? printf("\n轉(zhuǎn)化為八進(jìn)制數(shù)是: ");
? ? while( s2.base != s2.top )
? ? {
? ? ? ? Pop( &s2, &c );
? ? ? ? printf("%c", c);
? ? }
? ? printf("(O)\n");
?
? ? return 0;
}
二進(jìn)制每四位有一個(gè)十六進(jìn)制與之呼應(yīng)
int main()
{
? ? ElemType c;
? ? sqStack s1;
? ? sqStack s2;
? ? int len, i, j, sum = 0;
?
? ? InitStack(&s1); // 初始化棧s1,用來(lái)存放二進(jìn)制輸入
?
? ? printf("請(qǐng)輸入二進(jìn)制數(shù),輸入‘#’號(hào)表示結(jié)束!\n\n");
? ? scanf("%c", &c);
? ? while( c != '#' )
? ? {
? ? ? ? if( c=='0' || c=='1' ) ?// 檢查輸入是否二進(jìn)制
? ? ? ? ? ? Push(&s1, c);
? ? ? ? scanf("%c", &c);
? ? }
? ? getchar(); ? ? ?// 把'\n'從緩沖區(qū)去掉
? ? len = StackLen(s1);
?
? ? InitStack(&s2); // 初始化棧s2,用來(lái)存放轉(zhuǎn)換的八進(jìn)制
?
? ? for( i=0; i < len; i+=4 )
? ? {
? ? ? ? for( j=0; j < 4; j++ )
? ? ? ? {
? ? ? ? ? ? Pop( &s1, &c ); // 取出棧頂元素
? ? ? ? ? ? sum = sum + (c-48) * pow(2, j);
?
? ? ? ? ? ? if( s1.base == s1.top )
? ? ? ? ? ? {
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? switch( sum )
? ? ? ? {
? ? ? ? ? ? case 10: sum = 'A'; break;
? ? ? ? ? ? case 11: sum = 'B'; break;
? ? ? ? ? ? case 12: sum = 'C'; break;
? ? ? ? ? ? case 13: sum = 'D'; break;
? ? ? ? ? ? case 14: sum = 'E'; break;
? ? ? ? ? ? case 15: sum = 'F'; break;
? ? ? ? ? ? default: sum += 48;
? ? ? ? }
?
? ? ? ? Push( &s2, sum );
? ? ? ? sum = 0;
? ? }
?
? ? printf("\n轉(zhuǎn)化為十六進(jìn)制數(shù)是: ");
? ? while( s2.base != s2.top )
? ? {
? ? ? ? Pop( &s2, &c );
? ? ? ? printf("%c", c);
? ? }
? ? printf("(H)\n");
?
? ? return 0;
}
???????????????????????????????????????????????????????????鏈?zhǔn)綏?/p>
?
teypedef struct StackNode
{
ElemType data;?? ?// 存放棧的數(shù)據(jù)
struct StackNode *next;
} StackNode, *LinkStackPtr;
teypedef struct LinkStack
{
LinkStackPrt top;?? ?// top指針
int count;?? ??? ?// 棧元素計(jì)數(shù)器
}
?
?
實(shí)踐:計(jì)算數(shù)學(xué)表達(dá)式(1-2)*(4+5)
簡(jiǎn)介:逆波蘭表達(dá)式
——后來(lái),在20世紀(jì)三十年代,波蘭邏輯學(xué)家Jan.Lukasiewicz不知道是像牛頓一樣被蘋果砸到腦袋而想到萬(wàn)有引力原理,或者還是像阿基米德泡在浴缸里突發(fā)奇想給皇冠是否純金做驗(yàn)證,總之他也是靈感閃現(xiàn)了,然后發(fā)明了一種不需要括號(hào)的后綴表達(dá)式,我們通常把它稱為逆波蘭表達(dá)式(RPN) 。
?如果用逆波蘭表示法,應(yīng)該是這樣:1 2 – 4 5 + *
實(shí)現(xiàn)對(duì)逆波蘭輸入的表達(dá)式進(jìn)行計(jì)算,并且支持帶小數(shù)點(diǎn)的數(shù)據(jù)。
---------------------?
linux上面編譯的時(shí)候需要加上-lm選項(xiàng),因?yàn)樯厦娴念愐昧?include <math.h>
gcc zhan.c -o zhan -lm
作者:Shannon333?
來(lái)源:CSDN?
原文:https://blog.csdn.net/qq_35924276/article/details/81384826?
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請(qǐng)附上博文鏈接!
總結(jié)
以上是生活随笔為你收集整理的数据结构与算法(C语言) | 栈和队列——栈(自己做过测试)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 埃塞俄比亚首都是哪里(埃塞俄比亚首都)
- 下一篇: gcc - lm的含义