2021数据结构CH03【栈和队列】

3.1 栈

3.

c语言字符数组与字符串的使用详解参考这里

字符型数组以\0结束,此时数组多耗费了一个字符的空间,但是可以避免输出时尾部出现乱码。

char C[]={'I','O','I','I','O','I','O','O','\0'};
	for(int i=0;C[i]!='\0';i++){
	printf("%c ",C[i]);
	}
#include<stdio.h>  
#include<stdlib.h>  

//判断入栈出栈的操作序列是否合法 I O
bool Judge(char S[ ]){
	int i;
	int cnt=0;
	for(i=0;S[i]!='\0';i++){
		if(S[i]=='I') cnt++;
		if(S[i]=='O') cnt--;
		if(cnt<0){
			printf("由于cnt<0,操作序列不合法\n");
			return false;
		}
	}
	if(cnt!=0){
		printf("由于cnt!=0,操作序列不合法\n");
		return false;
	}
	printf("操作序列合法\n");
	return true;
}

int main(){
	char p;
	printf("A序列为:IOIIIIOO\n");
	printf("B序列为:IOOIOIOO\n");
	printf("C序列为:IOIIOIOO\n");
	printf("请选择你需要测试的序列,输入A,B或C:");
	scanf("%c",&p);
	if(p=='A'){
	char A[8]={'I','O','I','I','I','I','O','O'};
	printf("你选择了测试A序列\n");
	printf("测试结果:");
	Judge(A);
	}
	if(p=='B'){
	printf("你选择了测试B序列\n");
	char B[8]={'I','O','O','I','O','I','O','O'};
	printf("测试结果:");
	Judge(B);
	}
	if(p=='C'){
	printf("你选择了测试C序列\n");
	char C[8]={'I','O','I','I','O','I','O','O'};
	printf("测试结果:");
	Judge(C);
	}
	return 0;
}

4.

由于数组的定义s[n],n不能是变量,为此#define n 4。本代码已经测试了链表长度为偶数情况下的正确性,如果需要测试奇数的情况,则#define n 3即可。


#include<stdio.h>  
#include<stdlib.h>  
#define n 3
//字符串结构体
typedef struct LNode{    
	char data;    
	struct LNode *next;     
}LNode, *LinkList; 
 
 //初始化带头结点的单链表
bool InitListDai(LinkList &L){
	L=(LNode*)malloc(sizeof(LNode));
	if(L==NULL) return false;
	L->next=NULL;
	printf("初始化完成\n");
	return true;
}
 
//打印单链表中的字符串 带头
void printListDai(LinkList L){
    if (L->next==NULL) {
        printf("链表为空,打印失败\n");
    }else{
		LNode *p=L->next;
        while (p!= NULL) {
            printf("%c",p->data);
            p=p->next;
        }
        printf("\n");
    }
}
 
//利用尾插法在单链表中插入字符串 带头
LinkList List_TailInsertDai(LinkList &L){
	char x;
	L=(LNode *)malloc(sizeof(LNode));
	LNode *r=L;
	LNode *s;
	while((x=getchar())!='\n'){
		s=(LNode *)malloc(sizeof(LNode));
		s->data=x;
		r->next=s;
		r=s;
		x=getchar();
	}
	r->next=NULL;
	return L;
}
 
//求单链表中字符串的长度
int Listlen(LinkList L){
	int len=0;
	while(L->next!=NULL){
	len++;
	L=L->next;
	}
	return len;
}
//使用栈来判断链表中的数据是否中心对称
bool duicheng(LinkList &L,int len){
	LNode *p=L->next;
	int i=0;
	char s[n/2];
	for(;i<n/2;i++){
	s[i]=p->data;
	p=p->next;
	}
	i--;
	if(n%2==1)
		p=p->next;
	while(p!=NULL&&s[i]==p->data){
		
		i--;
		p=p->next;
	}
	if(p==NULL)//p扫描到最后,说明s中所有元素均与链表后半部分相等
	{printf("链表中心对称\n"); return true;}
	else
	{printf("链表不中心对称\n");return false;}
}
 
int main(){
	LinkList L;
	printf("准备创建一个长度为n的字符型单链表,n的大小为:%d\n",n);
	InitListDai(L);
	printf("输入单链表中的元素,以回车键结束:");
	List_TailInsertDai(L);
	printf("L:");
	printListDai(L);
	printf("\n");	
	duicheng(L,n);
	return 0;
	
}

5.


#include<stdio.h>  
#include<stdlib.h>  
#define maxsize 10//定义栈中元素的最大个数
#define ElemType int//假设元素类型为int
//共享栈的存储类型描述为
typedef struct{    
	ElemType stack[maxsize];    
	int top[2];//top含有两个指针
}stk; 
 
 //共享栈的初始化
void InitSTK(stk &S){
	S.top[0]=-1;
	S.top[1]=maxsize;
	printf("共享栈初始化完成......\n");
}
//判断栈空
bool STKempty(stk S){
	if(S.top[0]==-1&&S.top[1]==maxsize){
		printf("栈为空\n");return true;}
	else{
		printf("栈不为空\n");return false;}
}
//入栈操作
ElemType push(stk &S,int i,ElemType x){
//i=0入左栈,i=1入右栈,x为入栈元素
	if(i<0||i>1){
		printf("栈号输入错误,i=0入左栈,i=1入右栈");
		exit(0);
	}
	if(S.top[1]-S.top[0]==1){
		printf("栈满了,无法继续入栈\n");
		return 0;
	}
	switch(i){
		case 0:S.stack[++S.top[0]]=x;printf("元素%d入左栈\n",x);return 1;break;
		case 1:S.stack[--S.top[1]]=x;printf("元素%d入右栈\n",x);return 1;
	}
}
//出栈操作
ElemType pop(stk &S,int i){
//i代表含义同入栈操作
//退栈成功返回退栈元素 否则返回-1
if(i<0||i>1){
		printf("栈号输入错误,i=0入左栈,i=1入右栈");
		exit(0);
	}
switch(i){
case 0:
	if(S.top[0]==-1){
		printf("左栈已空,无需退栈\n");
		return -1;
	}
	else
		return S.stack[S.top[0]--];
case 1:
	if(S.top[1]==maxsize){
		printf("右栈已空,无需退栈\n");
		return -1;
	}
	else
		return S.stack[S.top[1]++];
}
}


 
int main(){
	stk S;
	InitSTK(S);
	push(S,0,1);
	push(S,0,2);
	push(S,0,3);
	push(S,0,4);
	push(S,0,5);
	push(S,1,10);
	push(S,1,9);
	push(S,1,8);
	push(S,1,7);
	push(S,1,6);
	push(S,0,11);
	printf("\n");	
	return 0;
	
}

3.2 队列

1.


#include<stdio.h>  
#include<stdlib.h>  
#define maxsize 3//定义队列中元素的最大个数
#define ElemType int//假设元素类型为int
//含标志位tag的循环队列
typedef struct{    
	ElemType data[maxsize];//存放队列元素
	int front,rear,tag;//队头指针 队尾指针
}SqQueue; 
 
 //含标志位tag的循环队列的初始化
void InitQueue(SqQueue &Q){
	Q.front=Q.rear=Q.tag=0;//初始状态下,队首指针指向0,队尾指针指向第一个准备入队的位置,也是0,初始状态下队列为空,用tag=0标记
	printf("含标志位的循环队列初始化完成......\n");
}
//入队操作
bool EnQueue(SqQueue &Q,ElemType y){
	printf("%d准备入队>>> ",y);
	if(Q.front==Q.rear&&Q.tag==1){//两个条件均满足,说明队满,无法入队
		printf("队满,无法入队!\n");
		return false;
	}
	Q.data[Q.rear]=y;
	Q.rear=(Q.rear+1)%maxsize;
	Q.tag=1;
	printf("入队成功\n");
	return true;
}
//出队操作
bool DeQueue(SqQueue &Q,ElemType &x){
//注意出队的元素不同于入队的元素,出队的元素本身已存在于队列中;
//如果后续要对出队的元素无任何操作,可以直接用ElemType x保存出队元素的值;
//但是如果后续要对出队的元素做出一系列的操作则必须将队列元素的引用赋值给x,而不是ElemType x
//针对引用问题,主函数部分有举例
	if(Q.front==Q.rear&&Q.tag==0){//两个条件均满足,说明队空,无法出队
		printf("队空,无法出队!\n");
		return false;
	}
	x=Q.data[Q.front];
	Q.front=(Q.front+1)%maxsize;
	Q.tag=0;
	printf(" 准备出队>>> %d 已经出队\n",x);
	return true;

}


 
int main(){
	SqQueue S;
	int e;
	InitQueue(S);
	EnQueue(S,1);
	EnQueue(S,2);
	EnQueue(S,3);
	EnQueue(S,4);
	DeQueue(S,e);
	printf(" 出队元素加1的结果为:%d\n",e+1);
	DeQueue(S,e);
	printf(" 出队元素加1的结果为:%d\n",e+1);
	return 1;
	
}

2.

代码与书中的稍有不同,队列的front和rear指针在出队进栈之后,出栈进队之前做了初始化处理,是为了实现队列元素顺序的逆置。

至于为何不重新初始化front,rear指针来实现逆置,是因为暂时没有想到合适的办法,核心代码按照书中代码来写,不需要注意太多细节,所以应该很容易就能够写出来。


#include<stdio.h>  
#include<stdlib.h>  
#define maxsize 5
#define ElemType int//假设元素类型为int
//含标志位tag的循环队列
typedef struct{    
	ElemType data[maxsize];//存放队列元素
	int front,rear,tag;//队头指针 队尾指针
}SqQueue; 

typedef struct{    
	ElemType stack[maxsize];    
	int top;//top含有两个指针
}stk; 

void InitSTK(stk &S){
	S.top=-1;//此情况下,栈中元素入栈时需要先将top++
	printf("栈初始化完成......\n");
}

void InitQueue(SqQueue &Q){
	Q.front=Q.rear=Q.tag=0;
	printf("队列初始化完成......\n");
}
//入队操作
bool EnQueue(SqQueue &Q,ElemType y){
	printf("%d准备入队>>> ",y);
	if(Q.rear==Q.front&&Q.tag==1){
		printf("队满,无法入队!\n");
		return false;
	}
	Q.data[Q.rear]=y;
	Q.rear=(Q.rear+1)%maxsize;
	Q.tag=1;
	printf("入队成功\n");
	return true;
}
//出队操作
bool DeQueue(SqQueue &Q,ElemType &x){
//注意出队的元素不同于入队的元素,出队的元素本身已存在于队列中;
//如果后续要对出队的元素无任何操作,可以直接用ElemType x保存出队元素的值;
//但是如果后续要对出队的元素做出一系列的操作则必须将队列元素的引用赋值给x,而不是ElemType x
	if(Q.rear==Q.front&&Q.tag==0){
		printf("队空,无法出队!\n");
		return false;
	}
	x=Q.data[Q.front];
	Q.front=(Q.front+1)%maxsize;
	Q.tag=0;
	printf(" 准备出队>>> %d 已经出队\n",x);
	return true;

}

//入栈操作
bool push(stk &S,ElemType &x){
	if(S.top==maxsize-1){
		printf("栈满了,无法继续入栈\n");
		return false;
	}
	S.stack[++S.top]=x;
	printf("元素%d已经入栈\n",x);
	return true;
}
//出栈操作
bool pop(stk &S,ElemType &x){
	if(S.top==-1){
		printf("栈已经空了,无法出栈");
		return false;
	}
	x=S.stack[S.top--];
	printf("元素%d已经出栈 \n",x);
	return true;
}

//
void Inverser(stk &S,SqQueue &Q){
	int c;
	while (Q.front!=Q.rear){
		DeQueue(Q,c);
		printf("使当前出队的元素入栈 \n");
		push(S,c);
	}
	Q.front=Q.rear=Q.tag=0;
	while(S.top!=-1){
		pop(S,c);

		EnQueue(Q,c);
	}
}
 
int main(){
	SqQueue Q;
	stk S;
	int e;
	
	InitQueue(Q);
	InitSTK(S);
	EnQueue(Q,1);
	EnQueue(Q,2);
	EnQueue(Q,3);
	EnQueue(Q,4);


	printf("*******************************************************\n");
	printf("* ");
	for(int i=0;i<maxsize-1;i++){
		printf("Q.data[%d]:%d  ",i,Q.data[i]);
	}
	printf("*\n");
	printf("*******************************************************\n");
	printf("\n");

	Inverser(S,Q);
	
	printf("*******************************************************\n");
	printf("* ");
	for(int j=0;j<maxsize-1;j++){
		printf("Q.data[%d]:%d  ",j,Q.data[j]);
	}
	printf("*\n");
	printf("*******************************************************\n");
	return 1;
	
}

3.

完整代码出问题了,本题只放入核心代码

//两个栈模拟入队操作
bool EnQueue(stk &S1,stk &S2,ElemType x){
	if(!StackOverflow(S1)){
		printf("S1没有满,可以入\n");
		push(S1,x);
		return true;
	}
	if(!StackOverflow(S1)&&!StackEmpty(S2)){
		printf("队列满,无法入队");
		return false;
	}
	if(StackOverflow(S1)&&StackEmpty(S2)){
		pop(S1,x);
		push(S2,x);
	}
	else{
	push(S1,x);
	return true;}
}
//两个栈模拟出队操作
bool DeQueue(stk &S1,stk &S2,ElemType &x){
	if(!StackEmpty(S2)){
		pop(S2,x);
		return true;
	}
	if(StackEmpty(S2)&&StackEmpty(S1)){
		printf("队列为空,无法出队!");
		return false;
	}
	if(StackEmpty(S2)&&!StackEmpty(S1)){
		while(!StackEmpty(S1)){
		pop(S1,x);
		push(S2,x);
		}
	}
	pop(S2,x);
	return true;

}

//两个栈模拟队列判空
bool QueueEmpty(stk S1,stk S2){
	if(StackEmpty(S1)&&StackEmpty(S2))
		return true;
	else 
		return false;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值