顺序栈—基本操作的实现及简单应用(C语言)(二)

简介: 顺序栈—基本操作的实现及简单应用(C语言)

2. 数制转换


代码如下:

//数制转换voidconversion(intNum,inttime)
{
inte,Elem;
Elem=Num;
SqStackS;
S.base=S.top=NULL;           //将空栈的栈顶和栈底指针赋值为NULL,因为此时并未对栈进行任何操作InitStack(S);                    //构造一个空栈while(Num)
    {
Push(S,Num%time);
Num=Num/time;
    }
printf("10进制整数%d对应的%d进制整数的值为:",Elem,time);
while(!StackEmpty(S))            //如果此时栈为空栈    {
e=Pop(S);              //使用e接收删除的栈顶的值 printf("%d",e);
    }
printf("\n");                    //换行 }

思路:

十进制N和其它进制数的转换是计算机实现计算的基本问题,基于下列原理:

N=(n div d)*d+n mod d

( 其中:div为整除运算,mod为求余运算)

因此,如果将计算过程中所得到的其他进制的数的各位顺序进栈,则按出栈序列打印输出的即为与输入对应的其他进制数

代码解释:

Num为要转换的十进制下的数,time为对应的其他进制的数

构造一个空栈用于存储所得的余数,利用while循环不断的将Num与time的余数入栈,再将Num的值变为Num/time,当Num为0退出while循环时再利用一次while来将之前入栈的元素依次出栈,所得即为十进制转换为对应进制下的数。

四. 运行结果演示:


1. 基本功能演示


①构造一个空栈

image.png

②批量元素入栈两次并判断长度以及打印(为了简便,每次入栈3个元素,分别为1,2,3)

image.png

image.png

image.png

image.png

image.png

③删除栈顶元素并返回其值

image.png

④插入新的栈顶元素520并打印顺序栈

image.png

image.png

⑤重置顺序栈并判断是否为空

image.png

image.png

⑥销毁顺序栈并判断是否为空

image.png

image.png

2. 简单应用演示


1.括号匹配

①输入一个不含括号的序列

image.png

image.png

②只输入一个括号

image.png

③输入左右括号数量相等但是并不匹配的序列

image.png

④输入一个符合要求的序列

image.png

2.数制转换

输入十进制下的数5转换为二进制下的数

image.png

总结


栈的本质是操作受限的线性表,,因此可称为限定性的数据结构。但从数据结构的角度看,它们是和线性表大不相同的一类重要的抽象数据类型。由于栈广泛的应用在各种软件系统中,因此在面向对象的程序设计中,是一种多型数据类型。

(附录)源码:


#include<stdio.h>#include<stdlib.h>#include<malloc.h>#include<windows.h>//函数结果状态代码 #define TRUE     1     //代码中出现TRUE相当于出现了1 #define FALSE    0     //出现FALSE相当于出现了0 #define OK       1     //出现OK相当于出现了1 #define ERROR    2     //出现ERROR相当于出现了2#define INFEASIBLE    -1#define OVERFLOW      -2 typedefintStatus;
typedefintSElemType; 
#define STACK_INIT_SIZE    100     //栈的储空间的初始分配量 #define STACKINCREMENT     10      //栈的存储空间的分配增量typedefstruct{
SElemType*top;        //栈顶指针 SElemType*base;       //栈底指针,在构造栈时和销毁栈时均为NULL intstacksize;         //当前已经分配的存储空间 }SqStack;
//构造一个空的顺序栈 StatusInitStack(SqStack&S)    
{
S.base= (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));      //开辟一块连续的空间 if(!S.base)                //如果存储空间分配失败 exit(OVERFLOW); 
S.top=S.base;            //当栈为空栈时栈底和栈顶指针位置相同S.stacksize=STACK_INIT_SIZE;      //更新栈的空间大小returnOK;
}
//批量元素入栈StatusValueStack(SqStack&S,intNum)
{
if(!S.base){               //如果栈不存在 printf("栈不存在,元素无法入栈\n");
returnERROR;
    }
if(S.base!=S.top){                //判断传来的顺序栈中是否为空栈if(Num>=S.stacksize){         //如果要入栈的元素数量大于栈的空间大小 S.base= (SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT) *sizeof(SElemType));
S.stacksize=S.stacksize+STACKINCREMENT;         //更新栈的空间大小         }
inttemp[Num];                  //定义一个辅助数组 for(inti=1;i<=Num;i++){
printf("请输入第%d个元素的值:",i);
scanf("%d",&temp[i-1]);       //将之后输入的值暂时存储在临时数组中         }
for(intj=1;j<=Num;j++){
*S.top=temp[j-1];
S.top++;
        } 
printf("%d个元素入栈成功\n",Num);
    }
else{
for(inti=1;i<=Num;i++){
printf("请输入第%d个元素的值:",i);
scanf("%d",&S.base[i-1]);
*(S.top++);
        }
printf("%d个元素入栈成功\n",Num);
    } 
//这条语句的目的是为了检测栈顶指针的位置是否在栈顶元素的下一个位置//如果输出的值等于输入元素的个数,则说明此时栈顶指针和栈底指针的位置都在正确的位置 //  printf("%d\n",S.top-S.base);         returnOK;
}
//对顺序栈进行销毁 StatusDistoryStack(SqStack&S)
{
if(!S.base){
printf("顺序栈不存在,无法销毁\n");
returnERROR;
    }
free(S.base);             //使用free函数,将之前动态分配的内存还给系统 S.stacksize=0;          //将栈的存储容量重置为0S.top=NULL;             //重置栈顶指针为NULL S.base=NULL;            //重置栈底指针为NULLprintf("顺序栈销毁成功\n"); 
returnOK;
}
//对顺序栈进行重置 StatusClearStack(SqStack&S)
{
if(!S.base){
printf("顺序栈不存在,不需要进行重置\n");
returnERROR; 
    }
S.top=S.base;           //将栈底指针赋值给栈顶指针 /*重置顺序栈时只需要将栈底指针的地址赋值给栈顶指针就可以了因为栈顶指针和栈底指针都没有指向之前赋值过的元素,而且S.top=S.base时认为栈为空栈其次在开辟一块连续的存储地址时,地址内也会有原本的值,开辟出的新空间并不是空的在之后无论是销毁栈又或者是重新给栈进行赋值时都会将之前赋的值覆盖掉 */printf("顺序栈重置成功\n");
returnOK;
} 
//判断顺序栈是否为空StatusStackEmpty(SqStackS)
{
if(!S.base)
returnERROR;
if(S.top==S.base)
returnTRUE;
elsereturnFALSE;
}
//获取顺序栈的长度StatusStackLength(SqStackS)
{
if(!S.base){
printf("顺序栈不存在,没有长度\n");
returnERROR;
    }
intK;
K=S.top-S.base;
/*为什么顺序表中有length而顺序栈中却没有length因为在顺序栈中,栈的长度就是S.top-S.base*/printf("栈的长度为:%d\n",K);
returnOK;           //返回顺序栈的长度 } 
//获取栈顶元素StatusGetTop(SqStackS)
{
if(!S.base){
printf("顺序栈不存在,不存在栈顶元素\n");
returnERROR;
    }elseif(S.base==S.top){
printf("顺序栈为空栈,不存在栈顶元素\n");
returnERROR;
    }
inte;
e=*(S.top-1);
printf("栈顶元素为:%d\n",e);
returnOK;
} 
//插入新的栈顶元素并返回其值 StatusPush(SqStack&S,SElemTypee)
{
if(!S.base){
printf("顺序栈不存在,无法插入新的栈顶元素\n");
returnERROR;
    }
elseif(S.top-S.base>=S.stacksize)      //此时顺序栈已满,追加存储空间    {
if(!S.base){         //如果存储空间分配失败 printf("存储空间分配失败\n");
exit(OVERFLOW);
        }
S.base= (SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT) *sizeof(SElemType));
S.top=S.base+S.stacksize;
S.stacksize=S.stacksize+STACKINCREMENT;         //更新栈的空间大小     }
*S.top=e;
S.top++;
returne;               //返回新插入的栈顶元素的值 }
//打印顺序栈StatusPrintStack(SqStackS)
{
if(!S.base){
printf("顺序栈不存在,无法打印\n");
returnERROR;
    }
elseif(S.base==S.top)
printf("顺序栈为空栈\n");
printf("当前顺序栈的元素为:");
for(inti=0;i< (S.top-S.base);i++){
printf(" %d",S.base[i]);
    }
printf("\n");               //换行 returnOK;
}
//删除栈顶元素并返回其值StatusPop(SqStack&S)
{
if(!S.base)
return-1; 
elseif(S.base==S.top)
return-2;
SElemTypee;
e=*(S.top-1);
S.top=S.top-1;
returne;           //返回被删除的栈顶元素的值 } 
/*遇到的问题会有以下几点1. 当输入的一个序列中没有括号时2. 当只输入一个右括号时 3. 左右两边的括号数目相同但是却不是配对的括号 *///括号匹配的检验Statusexamine(char*List)
{
SqStackS;
S.base=S.top=NULL;           //将空栈的栈顶和栈底指针赋值为NULL,因为此时并未对栈进行任何操作InitStack(S);                    //构造一个空栈intresult; 
inttemp=0;
intfinal=0; 
intlength=strlen(List);       //获取字符数组的长度 charArrays[length];             //定义一个与传来的字符数组长度相等的字符数组作为辅助数组 if(length==1)
    {
printf("输入的序列括号不匹配\n");
printf("输入的序列长度为:%d\n",length);
returnERROR;
    } 
for(inti=0;i<length;i++)
    {
switch(List[i])                     //利用switch语句来控制括号的入栈和出栈         {
case'(':
case'[':
case'{':
            {
Arrays[i] =Push(S,List[i]);
temp=1;
            }break;
case')':
case']':
case'}':
            {
Arrays[i] =Pop(S);
if(Arrays[i] =='('&&List[i] !=')')           //如果遇到了右括号判断是否与之前入栈的左括号对应 final=-1;                                  //如果左括号与右括号不匹配就将final的值修改为-1 elseif(Arrays[i] =='['&&List[i] !=']')
final=-1;
elseif(Arrays[i] =='{'&&List[i] !='}')
final=-1;
            }
        }
    }
if(StackEmpty(S) &&temp!=1){
printf("您输入的序列中没有括号\n");
final=2;
    }
if(temp==1&&!StackEmpty(S)){
printf("输入的序列括号不匹配\n");
printf("输入的序列长度为:%d\n",length);
returnOK;
    }
if(final==-1)
    {
printf("输入的序列括号不匹配\n");
printf("输入的序列长度为:%d\n",length);
returnOK;
    }elseif(final==0&&temp==1)
    {
result=StackEmpty(S);         //使用result接收判断是否为空栈的结果if(result==TRUE)
printf("输入的序列括号匹配\n");
elseif(result==FALSE)
printf("输入的序列括号不匹配\n");
printf("输入的序列长度为:%d\n",length);
//      printf("%s\n",Arrays);          //这条语句用于检测出栈的顺序     }
returnOK;
}
//数制转换voidconversion(intNum,inttime)
{
inte,Elem;
Elem=Num;
SqStackS;
S.base=S.top=NULL;           //将空栈的栈顶和栈底指针赋值为NULL,因为此时并未对栈进行任何操作InitStack(S);                    //构造一个空栈while(Num)
    {
Push(S,Num%time);
Num=Num/time;
    }
printf("10进制整数%d对应的%d进制整数的值为:",Elem,time);
while(!StackEmpty(S))            //如果此时栈为空栈    {
e=Pop(S);              //使用e接收删除的栈顶的值 printf("%d",e);
    }
printf("\n");                    //换行 }
intmain()
{
SetConsoleTitle("Dream_飞翔");              //控制windows终端控制台的名称 SqStackS;
S.base=S.top=NULL;                //将栈顶和栈底指针赋值为NULL,因为此时并未对栈进行任何操作intchoose,index,Num,e,time,final;
while(1){
printf("*****************************************\n");
printf("*                                       *\n");
printf("*  顺序栈的顺序表示和实现:             *\n");
printf("*                                       *\n");
printf("*    1.  构造一个空的顺序栈             *\n");
printf("*    2.  批量元素入栈                   *\n");
printf("*    3.  对顺序栈进行销毁               *\n");
printf("*    4.  对顺序栈进行重置               *\n");
printf("*    5.  判断顺序栈是否为空             *\n");
printf("*    6.  获取顺序栈的长度               *\n");
printf("*    7.  获取栈顶元素                   *\n");
printf("*    8.  插入新的栈顶元素并返回其值     *\n");
printf("*    9.  删除当前栈顶元素并返回其值     *\n");
printf("*    10. 打印顺序栈                     *\n");
printf("*                                       *\n");
printf("*****************************************\n");
printf("*                                       *\n");
printf("*  栈的简单应用:                       *\n");
printf("*                                       *\n");
printf("*    11. 括号匹配的检验                 *\n");
printf("*    12. 数制转换                       *\n");
printf("*                                       *\n");
printf("*****************************************\n");
printf("*    13. 退出                           *\n");
printf("*****************************************\n");
printf("请做出您的选择:");
scanf("%d",&choose);
switch(choose){
case1:{
final=InitStack(S);
if(final==OK)
printf("空栈构造成功\n");
            }
break;
case2:
            {
printf("请压入顺序栈的元素个数:");
scanf("%d",&Num); 
ValueStack(S,Num);
            }
break;
case3:DistoryStack(S);break;
case4:ClearStack(S);break;
case5:{
final=StackEmpty(S);
if(final==ERROR){
printf("顺序栈不存在,无法判断是否为空\n");
break;
                }
elseif(final==TRUE)
printf("顺序栈是空栈\n");
elseprintf("顺序栈不是空栈\n");
                }
break;
case6:StackLength(S);break;
case7:GetTop(S);break;
case8:{
printf("请输入要压入的元素:");
scanf("%d",&e);
final=Push(S,e);
if(final==e)
printf("新的栈顶元素插入成功\n");
            }
break;
case9:{
final=Pop(S);
if(final==-1){
printf("顺序栈不存在,无法删除栈顶元素\n");
break;
                }elseif(final==-2){
printf("顺序栈为空栈,无法删除栈顶元素\n");
break;
                }
printf("栈顶元素删除成功\n");
printf("删除的栈顶元素为:%d\n",final);
            }
break;
case10:PrintStack(S);break;
case11:
            {
charList[30];
printf("请输入一个带有括号的序列:"); 
scanf("%s",List);
examine(List);
            }
break;
case12:{
printf("请输入一个非负的十进制整数:");
scanf("%d",&Num);
printf("请输入想要将其转换成多少进制下的数:");
scanf("%d",&time);
if(time<=0)
                {
printf("请输入一个有效值\n");
break;
                }
conversion(Num,time);
            }
break;
case13:exit(0); 
        }
    } 
return0;
}
相关文章
|
1月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
215 9
|
2月前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
89 4
|
28天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
54 5
|
28天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
27天前
|
机器学习/深度学习 算法 数据挖掘
C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出
本文探讨了C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出。文章还介绍了C语言在知名机器学习库中的作用,以及与Python等语言结合使用的案例,展望了其未来发展的挑战与机遇。
44 1
|
27天前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
61 1
|
28天前
|
网络协议 物联网 数据处理
C语言在网络通信程序实现中的应用,介绍了网络通信的基本概念、C语言的特点及其在网络通信中的优势
本文探讨了C语言在网络通信程序实现中的应用,介绍了网络通信的基本概念、C语言的特点及其在网络通信中的优势。文章详细讲解了使用C语言实现网络通信程序的基本步骤,包括TCP和UDP通信程序的实现,并讨论了关键技术、优化方法及未来发展趋势,旨在帮助读者掌握C语言在网络通信中的应用技巧。
41 2
|
1月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
1月前
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
|
2月前
|
C语言
数组栈的实现(C语言描述)
本文介绍了如何在C语言中使用数组来实现栈的数据结构,包括栈的创建、入栈、出栈、获取栈顶元素、检查栈是否为空、获取栈的大小以及销毁栈等操作,并提供了相应的函数实现。
45 1