利用栈实现队列(C语言实现)

在上一篇优化后队列的实现(C语言实现)  中,虽然我们对队列的时间复杂度进行了优化,但是却让代码的可读性变差了,代码显得略微臃肿(当然,这些话你看看就好,主要是为了奉承这篇博文的)。

这里主要实现的是:利用栈来实现队列

基本思路:

1,创建两个栈

2,两个栈合并起来组装成一个队列,分别取名为instack,outstack,用于进队列,出队列

3,比如有1,2,3,4,5 需要进入队列,先将这一串数压入instack栈中,假设压入顺序为1,2,3,4,5(1为栈底),再将instack中的数据移入outstack中,出栈顺序为:5,4,3,2,1.  那么入outsatck的时候,进栈的顺序同样为 : 5,4,3,2,1(5为栈底),那么出outstack的时候,顺序即为:1,2,3,4,5  这样就做到了入是1,2,3,4,5
 出也是1,2,3,4,5  这样就跟队列是一样一样的了。

代码实现思路:

 实现思路

 准备两个栈用于实现队列:inStack和outStack

 当有新元素入队时: :将其压入 将其压入inStack中

 当需要出队时:

当outStack为空时:

1. 将inStack中的元素逐一弹出并压入outStack中

2. 将outStack的栈顶元素弹出

当outStack不为空时:

– 直接将outStack的栈顶元素弹出

源代码入下:

这里用到了栈的代码,具体可以参阅:栈的实现与操作(C语言实现)

头文件:

#ifndef _SPQueue_H_
#define _SPQueue_H_

typedef void SPQueue;

SPQueue* SPQueue_Create();

void SPQueue_Destroy(SPQueue* queue);

void SPQueue_Clear(SPQueue* queue);

int SPQueue_Append(SPQueue* queue, void* item);

void* SPQueue_Retrieve(SPQueue* queue);

void* SPQueue_Header(SPQueue* queue);

int SPQueue_Length(SPQueue* queue);

#endif

源文件:

// 栈实现队列.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "SPQueue.h"
#include "LinkStack.h"
#include <malloc.h>
#include <stdlib.h>

typedef struct
{
	LinkStack * instack;
	LinkStack * outstack;
} TSPQueue;

int _tmain(int argc, _TCHAR* argv[])
{
	 SPQueue* queue = SPQueue_Create();
    int a[10] = {0};
    int i = 0;

    for(i=0; i<10; i++)
    {
        a[i] = i + 1;

        SPQueue_Append(queue, a + i);
    }
    printf("第一次进队列:");
    printf("Header: %d\n", *(int*)SPQueue_Header(queue));
    printf("Length: %d\n", SPQueue_Length(queue));

    for(i=0; i<5; i++)
    {
        printf("%d\t出队列了\n", *(int*)SPQueue_Retrieve(queue));
    }
     printf("\n第二次进队列:\n");
    printf("Header: %d\n", *(int*)SPQueue_Header(queue));
    printf("Length: %d\n", SPQueue_Length(queue));

    for(i=0; i<10; i++) //继续尾加10个节点
    {
        a[i] = i + 1;

        SPQueue_Append(queue, a + i);
    }

    while( SPQueue_Length(queue) > 0 )
    {
        printf("%d\t出队列了\n", *(int*)SPQueue_Retrieve(queue));
    }

    SPQueue_Destroy(queue);

	system("pause");
	return 0;
}

//创建
SPQueue* SPQueue_Create()
{
	TSPQueue* ret = (TSPQueue*)malloc(sizeof(TSPQueue));
	if (NULL != ret)
	{
		ret->instack = LinkStack_Create();
		ret->outstack = LinkStack_Create();

		if ((NULL == ret->instack) && (NULL == ret->outstack))
		{
			LinkStack_Destroy(ret->instack);
			LinkStack_Destroy(ret->outstack);
			free(ret);
			ret = NULL;
		}
	}
	return ret;
}

//销毁
void SPQueue_Destroy(SPQueue* queue)
{
	SPQueue_Clear(queue);
	free(queue);
}

//清空
void SPQueue_Clear(SPQueue* queue)
{
	TSPQueue* SPQueue = (TSPQueue*)queue;
	if (NULL != SPQueue)
	{
		LinkStack_Clear(SPQueue->instack);
		LinkStack_Clear(SPQueue->outstack);
	}
}

//尾加
int SPQueue_Append(SPQueue* queue, void* item)
{
	TSPQueue* SPQueue = (TSPQueue*)queue;
	int ret = 0;
	if (NULL != SPQueue)
	{
		ret = LinkStack_Push(SPQueue->instack,item);
	}
	return ret;
}

//删除头部
void* SPQueue_Retrieve(SPQueue* queue)
{
	TSPQueue* SPQueue = (TSPQueue*)queue;
	void * ret = NULL;
	if (NULL != SPQueue)
	{
		//当outstack长度为0时,把instack中的数据移入outstack
		if (LinkStack_Size(SPQueue->outstack) == 0)
		{
			while (LinkStack_Size(SPQueue->instack) > 0)
			{
				LinkStack_Push(SPQueue->outstack,LinkStack_Pop(SPQueue->instack));
			}
		}
		//取出outstack的栈顶
		ret = LinkStack_Pop(SPQueue->outstack);
	}
	return ret ;
}

//获得头部
void* SPQueue_Header(SPQueue* queue)
{
	TSPQueue* SPQueue = (TSPQueue*)queue;
	void * ret = NULL;
	if (NULL != SPQueue)
	{
		if (LinkStack_Size(SPQueue->outstack) == 0)
		{
			while (LinkStack_Size(SPQueue->instack) > 0)
			{
				LinkStack_Push(SPQueue->outstack,LinkStack_Pop(SPQueue->instack));
			}
		}
		ret = LinkStack_Top(SPQueue->outstack);
	}
	return ret ;
}

//长度
int SPQueue_Length(SPQueue* queue)
{
	TSPQueue* SPQueue = (TSPQueue*)queue;
	int ret = 0;
	if (NULL != SPQueue)
	{
		ret = LinkStack_Size(SPQueue->instack) + LinkStack_Size(SPQueue->outstack);
	}
	return ret;
}

运行结果:

第一次进队列:Header: 1
Length: 10
1       出队列了
2       出队列了
3       出队列了
4       出队列了
5       出队列了

第二次进队列:
Header: 6
Length: 5
6       出队列了
7       出队列了
8       出队列了
9       出队列了
10      出队列了
1       出队列了
2       出队列了
3       出队列了
4       出队列了
5       出队列了
6       出队列了
7       出队列了
8       出队列了
9       出队列了
10      出队列了
请按任意键继续. . .

如有错误,望不吝指出。

利用栈实现队列(C语言实现)

时间: 2024-10-31 20:09:51

利用栈实现队列(C语言实现)的相关文章

C语言中堆、栈、队列

C语言中堆.栈和队列: 1.堆和栈 (1)数据结构的堆和栈 堆栈是两种数据结构. 栈(栈像装数据的桶或箱子):是一种具有后进先出性质的数据结构,也就是说后存放的先取,先存放的后取.这就如同要取出放在箱子里面底下的东西(放入的比较早的物体),首先要移开压在它上面的物体(放入的比较晚的物体). 堆(堆像一棵倒过来的树):是一种经过排序的树形数据结构,每个结点都有一个值.通常所说的堆的数据结构,是指二叉堆.堆的特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆.由于堆的这个特性,常用来实现优

《数据结构与算法分析:C语言描述_原书第二版》CH3表、栈和队列_reading notes

表.栈和队列是最简单和最基本的三种数据结构.基本上,每一个有意义的程序都将明晰地至少使用一种这样的数据结构,比如栈在程序中总是要间接地用到,不管你在程序中是否做了生命. 本章学习重点: 理解抽象数据类型(ADT)的概念 学习如何对表进行有效的操作 熟悉栈ADT及其在实现递归方面的应用 熟悉队列ADT及其在操作系统和算法设计中的应用 ADT 抽象数据类型(abstract data type)是一个操作的集合,是数学的抽象,在ADT中不涉及如何实现操作的集合,这可以看作是模块化设计的扩充. 对于每

&lt;2014 05 16&gt; 线性表、栈与队列——一个环形队列的C语言实现

栈与队列都是具有特殊存取方式的线性表,栈属于先进后出(FILO),而队列则是先进先出(FIFO).栈能够将递归问题转化为非递归问题,这是它的一个重要特性.除了FILO.FIFO这样的最普遍存取方式外,还有一些扩展的数据结构,如双端队列.双栈.超队列.超栈等,它们是一种扩展与变异结构. 线性表有顺序存储和链接存储两类,这是针对计算机的线性存储空间作出的分类.前者可以是数组,后者可以是链表.字符串是线性表最常见的应用. 这里我用C语言实现了一个基于数组环形队列,它具有固定的队列空间.相比于链表实现,

C语言数据结构——第三章 栈和队列

三.栈和队列 栈和队列是两种重要的线性结构.从数据结构的角度来看,栈和队列也是线性表,它的特殊性在于栈和队列的基本操作是线性表操作的子集,它们的操作相对于线性表来说是受到限制的,因此,可以称其为限定性的数据结构. 从数据类型的角度看,它们是和线性表大不相同的两种重要的抽象数据类型,在面向对象的程序设计中,它们是多型数据类型. 3.1-栈 3.1.1-抽象数据类型栈的定义 栈:是限定仅在表尾进行插入或删除操作的线性表,又可以称为后进先出的线性表. 栈顶:栈的表尾端 栈底:栈的表头端 空栈:不含元素

算法 - 栈与队列(C 语言实现)

目标: 理解 栈 与 队列 这两种数据结构, 并且知道如何应用. 算法 + 数据结构 = 程序 一.堆栈 堆栈是一组元素的集合,类似于数组,但数组可以按下标访问,堆栈的访问规则只能为push 与 pop 两种操作. 堆栈只能访问或者移出栈顶的元素.

利用两个栈模拟队列

/************************************************** 题目:用两个栈模拟队列的基本操作1入队2,出队3判断队空4判断队满 s1做为输入栈的元素,一个个压栈相当于入队 s2作为输出队列的元素, 一个个出栈相当于出队 *************************************************/ #include <iostream> #include <cstdio> using namespace std; c

LeetCode 232题用栈实现队列(Implement Queue using Stacks) Java语言求解

题目链接 https://leetcode-cn.com/problems/implement-queue-using-stacks/ 题目描述 使用栈实现队列的下列操作: push(x) -- 将一个元素放入队列的尾部.pop() -- 从队列首部移除元素.peek() -- 返回队列首部的元素.empty() -- 返回队列是否为空. 示例: MyQueue queue = new MyQueue();queue.push(1);queue.push(2); queue.peek(); //

数据结构之栈和队列

数据结构学习继续向前推进,之前对线性表进行了学习,现在我们进入栈和队列的学习.同样我们先学习一些基本概念以及堆栈的ADT. 栈和队列是两种中重要的线性结构.从数据结构角度看,栈和队列也是线性表,只不过是受限的线性表.因此可以称为限定性数据结构.但从数据类型来看,他们是和线性表大不相同的两类重要的抽象数据类型. 栈:(stack)是限定仅在表尾进行相应插入和删除操作的线性表.因此,对栈来说,表尾有其特殊含义,称为栈顶,表头称为栈底,不含元素的空表称为空栈.栈一个重要特性就是后进先出.OK,我们来看

数据结构和算法分析(9)表栈和队列的实际应用(一)

    在接下来的几篇博文中,将介绍表.栈.队列在编程实践中的应用.     (1)表达式求值:     输入一个中缀表达式,操作符包括(+ - * / ^).转化为后缀表达式之后并计算表达式的值: 要求: 1.输入的中缀表达式必须是一个完整的字符串: 2.不限制数字的位数和正负,负数用()括起来: 代码如下: 1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 #define EmptyT