顺序栈:(如下)
/*栈的运用,后进先出的一种线性结构,有两种形式,本程序为数组型
注意数据不需要太大,0~128是int在本运行软件中的范围*/
/*1.我这里能否不输入文件新数据的情况下,查看文件内的数据,fread()函数没有运用到*/
#include <stdio.h>
#include <string.h>
#include <windows.h>
int length=0;
#define StackSize 100
typedef char DataType;//为数据起个别名
typedef struct SeqStack{//结构体
DataType data[StackSize];//简单易得当数组下标为 StackSize-1 就代表满了
int top;
}SeqStack;//Client[100]用来储存100个名额
char Client[100];
SeqStack *S;//S->top开始的时候为-1,因为只有在加了一个之后数组下标才会变成0
//SeqStack *s;//用于储存最原始的位置
int ddd=0;
int dddd=0;
//需要实现的功能:置栈空、判栈空、判栈满、进栈、退栈、取栈顶元素,输出栈内所有数据
void InitStack(SeqStack *S);//置栈空
int StackEmpty(SeqStack *S);//判栈空 栈空返回1
int StackFull(SeqStack *S);//判栈满 栈满返回1
int Push(SeqStack *S,DataType x);//进栈
DataType Pop(SeqStack *S);//退栈
DataType StackTop(SeqStack *S);//取栈顶元素
void look(SeqStack *S);//输出栈内的元素
void look_1(SeqStack *S);//形象输出
void chazhao(SeqStack *S);//查找
void menu();//菜单输出
int k=0;//用于后面判断是否成功退栈
int ii=0;
panduan(void);//用于判断用户是否有初始化栈,使栈置空
panduan(void)
{
if(ddd==1)
printf("\n");
else
printf("栈还未置空,请先将栈置空\n");
return 0;
}
int main()
{
//
FILE *fp;
int choose=0, a=0, b=0, c=0, i=0, shu=0;
int ii=0;
//SeqStack *s;
system("color F1");
printf("*****欢迎来到顺序栈型的程序*****\n");
printf("你准备好了吗?");
system("pause");
menu();
choose=-1;
while(choose!=9){
printf("前面的序号代表功能,请输入你选择的功能:");
scanf("%d",&choose);
switch(choose)
{
//
case 1:
//置栈空
S=(SeqStack*)malloc(sizeof(SeqStack));//这一步不要忘记了,需要给s分配一定空间,否则无法正常使用
//s=(SeqStack*)malloc(sizeof(SeqStack));//这一步不要忘记了,需要给s分配一定空间,否则无法正常使用
InitStack(S);
printf("\n已将栈置空!\n");
ddd=1;
dddd=1;
length=0;
break;
case 2:
//进栈
panduan();
if(dddd==0)
break;
length++;
printf("请输入所要进入栈的数据:");
getchar();//这个不能少了,否则可能会引起a的自动读取
scanf("%c",&a);
//s=(SeqStack*)malloc(sizeof(SeqStack));//!!的确是可以进入两个数据,但是第二季数据的储存出现了未知的问题!!
Push(S,a);
break;
case 3:
//出栈
panduan();
if(dddd==0)
break;
length--;
printf("出栈只能出顶部的哦! 暂无人工选择功能\n");
b=Pop(S);
if(k==1)
{
printf("出栈的数据是:%c\n",b);
}
k=0;//重新赋值0,以免后续操作造成重叠
break;
case 4:
//取栈顶元素
panduan();
if(dddd==0)
break;
c=StackTop(S);
if(k==2){
printf("栈顶数据为:%c\n",c);
}
k=0;//重新赋值0,以免后续操作造成重叠
break;
case 5:
//人为清屏
puts("*****——2秒后清屏——*****");
Sleep(2000);
system("cls");
menu();
break;
case 6:
//输出
panduan();
if(dddd==0)
break;
look(S);
break;
case 7:
if(dddd==0)
break;
chazhao(S);
break;
case 8:
if(dddd==0)
break;
puts("以下便是");
look_1(S);
break;
case 9:
//退出
system("cls");
printf("\n2秒后即将退出程序,祝你生活愉快!\n");
Sleep(2000);
return 0;//我习惯使用exit(0);去暂停函数,但是这里采用return 0;去也是随便
case 10:
//读入数据(文件)
if((fp=fopen("C:/Users/86199/Desktop/wangjie.txt","w+"))==NULL)
printf("文件打开失败!\n");
else{
//到了这一步,说明文件已经正常打开了,那么就开始进行下面的操作吧!
//fp++是错误的,fwrite()函数后,(错误)fp会自动的指向下一个位置(错误)(!!!此处的fp根本就不会自动移动!!!)
//fprintf(fp,"%-5s %-5s","\n输出","如下:\n");
fprintf(fp,"\n");
//s->top=0;
//system("chcp 65001");//乱码纠正
fwrite(&Client,sizeof(DataType),S->top+10,fp);//S->top是从-1开始的
// fseek(fp,(s->top+1)*2,0);//移动文件指针用的
printf("输入文件内成功\n");
//fclose(fp);//必须要关闭,防止发生意外(是否是关闭文件早了?***如果此时关闭了文件,那么数据将不会存入文件中***)
}
fclose(fp);
break;
case 11:
//查看bug是有的,比如如果我直接查看的话就出现问题了
//!!!暂且发现其实此处的查看过程根本没有必要打开文件了!!!
//s->top=0;
FILE *fp1;
//SeqStack *ss;
//ss=(SeqStack*)malloc(sizeof(SeqStack));
//ss->top=0;//暂时从0开始
if((fp1=fopen("C:/Users/86199/Desktop/wangjie.txt","r"))!=NULL){
printf("打开成功\n");
rewind(fp1);//等价于fseek(fp,0,SEEK_SET);
fread(&Client,sizeof(DataType),100,fp1);//不该使用满的StackSize
//printf("ok");//运行到此行没有发现问题
/*while(!feof(fp1))//已知bug,不该使用满的StackSize //不能使用ss->top!=S->top,否则最后一个输出没有满足要求
{
Client[ii]=S->data[ss->top];//将data数组内的元素一个一个赋值给Client数组
ss->top++;
ii++;
}*/
//printf("ok");S->top现在就是等于-1,上面的while语句跳过,下面的if语句也进行不了
if(1/*S->top!=-1*/)//不为空
for(i=0;i<StackSize;i++){//已知bug,不该使用满的StackSize
printf("%c\t",Client[i]);
/*shu++;
if(shu%5==0)//偷懒了,已知bug,读入了空格,不益分行
printf("\n");*/
}
}
// fseek(fp,(s->top+1)*2,0);//移动文件指针用的,此处出现了未知的bug
else
printf("读取失败\n");
fclose(fp1);
break;
default :
//错误处理
system("cls");//清屏
menu();
printf("\n输入有误!请重新输入!\n");
break;
}
}
return 0;
}
void menu()
{
printf("\n 1.置栈空 2.进栈 \n");
printf("\n 3.出栈 4.取栈顶元素 \n");
printf("\n 5.人工清屏 6. 输出栈内元素 \n");
printf("\n 7.查找 8.形象输出 \n");
printf("\n 9.退出 10.文件内读入数据 \n");
printf("\n 11.查看 \n");
}
void InitStack(SeqStack *S)//置栈空
{
//
S->top=-1;
//s->top=0;
}
int StackEmpty(SeqStack *S)//判栈空
{
//
return S->top==-1;
}
int StackFull(SeqStack *S)//判栈满
{
return S->top==StackSize-1;
}
void chazhao(SeqStack *S)//查找栈内元素
{
//
int i;
char a;
int length1=0;
SeqStack *ss;
ss=(SeqStack*)malloc(sizeof(SeqStack));
ss->top=S->top;
printf("\n请输入你需要查找的元素:");
fflush(stdin);
scanf("%c",&a);
puts("*****形象的从上往下的看*****");
for(i=0;i<length;i++)
{
length1++;
if(a==S->data[S->top-i])
printf("\n它位于第%d个\n",length1);
}
printf("\n");
S->top=ss->top;//将指针返回到原来的位置
}
void look(SeqStack *S)//输出栈内的元素
{
//栈的指针暂时只是指向头部,所以输出也是从头部开始输出,但是注意在操作完成之后一定要将指针返回原来的位置
int jj=1;
SeqStack *ss;
ss=(SeqStack*)malloc(sizeof(SeqStack));
ss->top=S->top;
puts("\n****************************************\n");
printf("\n此时栈的元素为(从栈顶到栈底部):\n");
while(S->top!=-1)
{
//注意栈指针总是一直指向下一个
printf("第%d个元素:%c ",jj,S->data[S->top--]);//出现了问题!无法正常输出此时栈内的元素
//S->top--;
jj++;
if((jj-1)%4==0)//确保输出的元素4个一行
printf("\n");
}
printf("\n");
S->top=ss->top;//将指针返回到原来的位置
}
void look_1(SeqStack *S)//形象输出
{
//
int i;
SeqStack *ss;
ss=(SeqStack*)malloc(sizeof(SeqStack));
ss->top=S->top;
printf(" * *\n");
printf(" * *\n");
printf(" * *\n");
printf(" *****************\n");
for(i=0;i<length;i++)
{
printf(" * %c *\n",S->data[S->top-i]);
printf(" *****************\n");
}
printf("\n");
S->top=ss->top;//将指针返回到原来的位置
}
int Push(SeqStack *S,DataType x)//进栈
{
//先判断栈已满否
if(StackFull(S))
{
printf("\n不好意思,栈已经满了,无法再进行进栈操作\n");
return 0;
}
S->data[++S->top]=x;
Client[ii]=x;//进栈的时候读取给数组的
//S->top++;//“往返而回”
ii++;
printf("\n进栈成功!\n");
return 1;
}
DataType Pop(SeqStack *S)//退栈
{
//退栈先判断栈是否为空
if(StackEmpty(S))
{
printf("\n不好意思,栈是空的,无法进行退栈操作,请先进行进栈操作\n");
return 0;
}
k=1;
return S->data[S->top--];
printf("\n退栈成功!\n");
}
DataType StackTop(SeqStack *S)//取栈顶元素
{
//首先判断是否有的数据
if(StackEmpty(S))
{
printf("\n不好意思,栈是空的,无法取出任何数据\n");
return 0;
}
k=2;
return S->data[S->top];//注意取不是退,不需要将S->top减一个
}
链栈:(如下)
/*栈的链表形式,将单链表的首段做栈顶端,即头指针作为栈顶指针*/
#include <stdio.h>
#include <windows.h>//Sleep();函数将会用到
#include <stdlib.h>//exit();函数将会用到
#include <conio.h>//getche()函数在这里面
typedef char DataType;//基础数据字符类型
int k=0;//用于后续判断是否成功标志
int kk=0;//用于判断查找的时候是否有查找到所需元素
typedef struct stacknode{//节点的自我描述
DataType data;
struct stacknode *next;//自引用结构
}StackNode;
int dd=0;//用于判断是否有先将栈置空,等于1就相当于已经置空
int length=0;//记录下栈内元素的个数
typedef struct {
StackNode *top;//指向栈顶的指针
}LinkStack;
LinkStack *S;
void menu();//菜单
void InitStack(LinkStack *S);//将链栈置空
int StackEmpty(LinkStack *S);//判断链栈是否是空的
void Push(LinkStack *S,DataType x);//进入链栈
DataType Pop(LinkStack *S);//退出链栈
DataType StackTop(LinkStack *S);//取链栈顶的元素
void shuchu(LinkStack *S);//简单输出
void shuchu_1(LinkStack *S);//形象输出
void chazhao(LinkStack *S);//查找
int main()
{
//
int choose=0;
char a='a', b, c;//字符a的初始化在这里只是为了避免未初始化警告提醒罢了!
system("color F1");
printf("*****欢迎来到链栈程序!*****\n");
printf("你准备好了吗?");
system("pause");
menu();
choose=-1;//先定个初始值,其实也没有那么必要(前面已经置0)
while(choose!=9){
printf("前面的序号代表功能,请输入功能选项:");
scanf("%d",&choose);
switch(choose)
{
//
case 1:
//置栈空
S=(LinkStack *)malloc(sizeof(LinkStack));
InitStack(S);
puts("\n置空完毕!");
dd=1;
break;
case 2:
//进栈
if(dd==1){
printf("\n请输入进链栈的数据:");
getchar();//此getcahr不能省略,此getchar()的功能是接受回车,其实这里也可以写fflush(stdin);
scanf("%c",&a);//!!!记录:自己又再一次忘记加&了!!!
Push(S,a);
}
else{
printf("请先将栈置空\n");
}
break;
case 3:
//出栈
if(dd==1){
printf("\n*****\t\t出链栈,即将栈顶指针所指向的数据退栈\t\t*****\n");
b=Pop(S);
if(k==1)
{
printf("出栈的数据是:%c\n",b);
}
k=0;
}
else{
puts("请先将栈置空");
}
break;
case 4:
//取栈顶元素
if(dd==1){
c=StackTop(S);
if(k==2)
{
printf("\n栈顶的元素为:%c\n",c);
}
k=0;
}
else{
puts("请先将栈置空");
}
break;
case 5:
//形象输出
if(dd==1){
shuchu_1(S);
}
else{
puts("请先将栈置空");
}
break;
case 6:
//人工主动清屏
system("cls");
menu();
break;
case 7:
//简单输出
if(dd==1){
shuchu(S);
}
else{
puts("请先将栈置空");
}
break;
case 8:
if(dd==1){
chazhao(S);
}
else{
puts("请先将栈置空");
}
break;
case 9:
printf("\n2秒后程序即将结束,祝你生活愉快!\n");
Sleep(2000);
exit(0);
//退出
default:
system("cls");
printf("\n输入有误!请重新输入:");
menu();
break;
//处理未知错误情况
}
}
return 0;
}
void menu()//菜单
{
//
printf("\n 1.置栈空 2.进栈 \n");
printf("\n 3.出栈 4.取栈顶元素 \n");
printf("\n 5.形象输出 6.人工主动清屏 \n");
printf("\n 7.输出栈内元素 8.查找 \n");
printf("\n 9.退出 \n");
}
void chazhao(LinkStack *S)
{
int i=0;
char ok;
StackNode *p;
p=(StackNode *)malloc(sizeof(StackNode));
p=S->top;
printf("\n(从上往下)请输出你要查找的元素:");
fflush(stdin);
//scanf("%c",&ok);
ok=getche();
for(i=0;i<length;i++)
{
if(p->data == ok)
{
printf("\n该元素(%c)位于第%d个!\n",ok,i+1);
kk++;
}
p=p->next;
}
if(kk==0)
printf("\n抱歉,我们没有找到该元素,建议查看清楚后再查找!");
}
void shuchu(LinkStack *S)//数据基本类型为char类型
{
//
int i=0;
int length1=length;
StackNode *p;//先创建一个过度的指针
p=(StackNode *)malloc(sizeof(StackNode));//分配必要的动态空间
p=S->top;//将该工作指针指向头指针
printf("\n栈内元素从上往下为:\n");
for(i=0;i<length1;i++)
{
//
printf("第%d个元素为%c\n",i+1,p->data);
p=p->next;
}
}
void shuchu_1(LinkStack *S)
{
//
int i=0;
int length1=length;
StackNode *p;
p=(StackNode *)malloc(sizeof(StackNode));
p=S->top;
printf("\n形象输出:\n");
printf(" * *\n");
printf(" * *\n");
printf(" * *\n");
printf(" *****************\n");
for(i=0;i<length;i++)
{
printf(" * %c *\n",p->data);
printf(" *****************\n");
p=p->next;
}
printf("\n");
}
void InitStack(LinkStack *S)//栈置空
{
//
S->top=NULL;
length=0;
}
int StackEmpty(LinkStack *S)//判断链栈是否为空,顺便提一句,链栈基本属于不会满的结构
{
//
return S->top==NULL;//链态形式的栈若为空就为NULL,而顺序形式的就是为-1
}
void Push(LinkStack *S,DataType x)//进入链栈
{
//
StackNode *p;//先创建一个过度的指针
p=(StackNode *)malloc(sizeof(StackNode));
p->data=x;//接入数据
p->next=S->top;//此行代码与下面一行代码使得数据进入栈内
S->top=p;
puts("此数据进入链栈完成");
length++;
}
DataType Pop(LinkStack *S)//退出链栈
{
//挑选了一个中间指针变量,去过度使得S->top指向下一个
DataType x;
StackNode *p=S->top;
if(StackEmpty(S))
{
printf("\n链栈此时为空,无法进行退栈操作\n");
return 0;
}
x=p->data;
S->top=p->next;
k=1;
length--;
free(p);
return x;
}
DataType StackTop(LinkStack *S)//取栈顶元素
{
//栈内的元素并没有因为查看一下就会减少,所以不需要length--
if(StackEmpty(S))
{
printf("*****\t\t此时的链栈为空,请先进行进栈操作\t\t******\n");
return 0;
}
k=2;
return S->top->data;
}