栈和队列之间的互相实现

第一部分、两个队列实现一个栈

本来想画图,可实在没这时间,且理解起来相对容易

主要思想是,先将 所有数先导入一个队列A中去,另一个队列B此刻为空。将队列A中除了最后一个数其他都导入B中,然后将A中仅剩的一个数输出,这样循环下去,就造成了栈的假象。

实现如下:

//队列实现
#ifndef QUEUE_H
#define QUEUE_H
#include <stdio.h> 
#include <stdlib.h>
#include <malloc.h>

typedef struct NODE
{
	int n;
	struct NODE *pnext;
}nod, * pnod;


typedef struct S
{
	pnod phead;
	pnod ptail;
}ss, * pss;


void init(pss);
void en_queue(pss,int );
void out_queue(pss,int &);
bool is_empty(pss);
int nodes_remain(pss);




void init(pss Y)
{
	Y->phead=(pnod)malloc(sizeof(nod));
	if(Y->phead == NULL)
		exit(-1);
	Y->phead->pnext=NULL;
	Y->ptail=Y->phead;
}


void en_queue(pss Y,int val)
{
	pnod new_x=(pnod)malloc(sizeof(nod));
	if(new_x == NULL)
		exit(-1);
	new_x->n=val;
	new_x->pnext=NULL;
	Y->ptail->pnext=new_x;
	Y->ptail=new_x;
}


bool is_empty(pss Y)
{
	if(Y->phead == Y->ptail)
		return true;
	else
		return false;
}


void out_queue(pss Y,int & T)
{
	if(is_empty(Y))
		return;
	else
	{
		pnod r=Y->phead->pnext;
		Y->phead->pnext=r->pnext;
		if(Y->phead->pnext==NULL)         //我就觉得这里需要注意一下  就是只剩下一个没有val的头结点和一个尾节点指向的节点的时候   没有这一步的话无法判断 is_empty
			Y->ptail=Y->phead;
		T = r->n;
		free(r);
	}
}

int nodes_remain(pss Y)
{
	int count=0;
	pnod p = Y->phead->pnext;
	while(p)
	{
		count++;
		p = p->pnext;
	}
	return count;
}

#endif


//main
#include <stdio.h>				//与两个栈实现一个队列相对应
#include "queue.h"

int main()
{
	int a[] = {1,2,3,4,5,6,7};
	pss Queue_A,Queue_B;
	Queue_A = (pss)malloc(sizeof(ss));
	Queue_B = (pss)malloc(sizeof(ss));
	init(Queue_A);
	init(Queue_B);
	int i;
	for(i=0;i<7;i++)
		en_queue(Queue_A,a[i]);
	printf("Datas stored in Queue_A:\n");					//输出存储在A中的数据
	for(i=0;i<7;i++)
		printf("%d%c",a[i],(i+1)%7==0?'\n':' ');
	int temp;
	//以下为按照栈的形式输出第一个数
	for(i=0;i<6;i++)										//将队列A中数据逐个导入B中,但是 最后一个数不导 而是直接输出out_queue  这样就把最后一个数第一个输出了
	{
		out_queue(Queue_A,temp);
		en_queue(Queue_B,temp);
	}
	printf("Output the first data as Stack-style : \n");
	out_queue(Queue_A,temp);
	printf("%d\n",temp);
	//以上是输出一个数 那如果要连续输出呢
	//以下就是连续输出   为了避免只将一个栈作为存储 而另一个作为临时的浪费 利用两个指针
	pss p, q;
	if(is_empty(Queue_A))
	{
		p = Queue_B;
		q = Queue_A;
	}
	else
	{
		p = Queue_A;
		q = Queue_B;
	}
	while(!is_empty(p))						//将p作为有数的那个栈 q作为空栈
	{
		while(nodes_remain(p)>1)					//使队列中仅剩一个数
		{
			out_queue(p,temp);
			en_queue(q,temp);
		}
		out_queue(p,temp);
		printf("%d ",temp);
		if(is_empty(Queue_A))				//有数的队列已经变成了另一个 此刻将p指针指向这个队列
		{
			p = Queue_B;
			q = Queue_A;
		}
		else
		{
			p = Queue_A;
			q = Queue_B;
		}
	}
	puts("");
	return 0;
}



第二部分:两个栈实现一个队列

简单的设想是将所有元素导入A,再倒入B,之后直接输出。这里考虑了如果需要新增元素该怎么处理,并不需要因为新元素来回倒腾

//栈实现
#ifndef STACK_H
#define STACK_H
#include <stdio.h>                  
#include <malloc.h>
#include <stdlib.h>



typedef struct subject 
{
	int data;
	struct subject *pnext;
}node,* pnode;



typedef struct First 
{
	pnode ptop;
	pnode pbottom;
}s,* ps;




void init(ps S)               
{
	S->ptop=(pnode)malloc(sizeof(node));
	if(NULL == S->ptop)
	{
		printf("FALE\n");
		exit(1);
	}
	S->ptop->pnext=NULL;
	S->pbottom=S->ptop;
}


void push(ps S,int val)						           
{
	pnode newx=(pnode)malloc(sizeof(node));
	if(NULL == newx)
	{
		printf("FALE\n");
		exit(1);
	}
	newx->data=val;
	newx->pnext=S->ptop;
	S->ptop=newx;
}

bool empty(ps S)            
{
	if(S->ptop==S->pbottom)
		return true;
	else
		return false;
}






void pop(ps S,int &e)				         
{
	if(empty(S))
		return;
	else
	{
	pnode r;
	r=S->ptop;
	S->ptop=r->pnext;
	e = r->data;
	free(r);
	}
}

void traverse(ps S)					
{
	if(empty(S))
		return;
	else
	{
		pnode p;
		p=S->ptop;
		while(p!=S->pbottom)
		{
			printf("%d  ",p->data);
			p=p->pnext;
		}
		putchar('\n');
	}
}

void clear(ps S)                 
{
	pnode p;
	pnode q;
	p=S->ptop;
	while(p != S->pbottom)
	{
		q=p->pnext;
		free(p);
		p=q;
	}
	S->ptop=S->pbottom;
}


#endif


//main
#include <stdio.h>				//实现 出队列操作
#include <malloc.h>
#include "stack.h"
//不难理解  只是在看到问题时候是否想得到是否有思路  将两个栈一起来实现队列的出队
int main()
{
	ps Stack_A = (ps)malloc(sizeof(s));
	ps Stack_B = (ps)malloc(sizeof(s));
	init(Stack_A);
	init(Stack_B);
	int i;
	int a[] = {1,2};
	printf("The origin order of the array:\n");
	for(i=0;i<2;i++)
		printf("%d ",a[i]);
	puts("");
	for(i=0;i<2;i++)
		push(Stack_A,a[i]);
	printf("Datas in Stack_A:\n");
	traverse(Stack_A);
	int temp;
	while(!empty(Stack_A))				//此处可以优化	可以计数  不必将所有都导入B 而是留下A中的最后一个 继而直接输出 而不是导入B后由B输出
	{
		pop(Stack_A,temp);
		push(Stack_B,temp);
	}
	printf("Datas in Stack_B:\n");
	traverse(Stack_B);
	pop(Stack_B,temp);
	printf("Output the first number as the Queue-style :\n");
	printf("%d\n",temp);
	//以上实现的是一次性  若是需要反复加入新元素同时能够按队列形式输出呢
	//一种方式是在按需输出元素后,将所有元素导入A如果需要入队则直接入A  之后再入B,输出,按需重复上述步骤

	//还有一种方式如下:
	//如果需要入队 则直接进A  (为什么不需要来回倒腾一番呢?因为我要入队的数全都暂时存在A中 一旦B中的数消耗掉了 就将A中的数字导入B)
	push(Stack_A,10);					//不空的话 说明数全在A中 直接将此数入A
	//这种方式如果要出队 并不会在上一次出队后将B中所有数全倒回A 而是将计就计(当然 这得需要没有新增的入队操作) 
	if(empty(Stack_B))					//如果为空,即B中元素全都输出完了,则将A中的后来元素全部导入B
		while(!empty(Stack_A))
		{
			pop(Stack_A,temp);
			push(Stack_B,temp);
		}
	printf("Datas in Stack_B:\n");
	traverse(Stack_B);
	pop(Stack_B,temp);					//如果不空 则说明数全在B中(或者说并没有进行入队操作) 则直接将B中数据pop
	printf("Output the next number as the Queue-style :\n");
	printf("%d\n",temp);
	//当然 如果要继续的话 可以设循环
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值