顺序栈 和 链栈

顺序栈:(如下)

/*栈的运用,后进先出的一种线性结构,有两种形式,本程序为数组型
注意数据不需要太大,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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值