嵌入式C语言那点事(二)栈与队列的实现

栈与队列的区别:

栈——先入后出,后入先出;

队列——先入先出,后入后出;


应用举例:

栈:函数调用时会将临时数据压栈;函数返回时再弹出来。

队列:一般,系统中的任务和消息经常使用队列。可以按任务或消息到来的先后顺序执行。


代码实现:

背景:使用C语言,在VS2008环境下,按栈与队列的原理,采用最简单易懂的方式,针对正整型(int)元素实现栈与队列。

原理:栈的存储空间使用数组构造,队列的空间又使用栈来构造,即,使用两个栈实现队列的功能。

文件:libStack.h/c;libQueue.h/c;


一、栈的源代码

libStack.h

#ifndef _LIBSTACK_H
#define _LIBSTACK_H

#ifdef __cplusplus
extern "C" {
#endif

#define STACK_MAX_LEN	2048

typedef struct tagstStack 
{
	int udwPc;				/* 栈顶所在位置,指向空闲位置 */
	int a[STACK_MAX_LEN];
}stStack;

/* 创建新的栈 */
extern stStack *stack_new();

/* 栈复位 */
extern void stack_reset(stStack *pstStack);

/* 入栈,栈满时忽略此次操作 */
extern void stack_push(stStack *pstStack,int udwTmp);

/* 出栈,栈空时返回-1 */
extern int stack_pop(stStack *pstStack);

/* 栈判空 1-空 0-非空 */
extern int stack_is_empty(stStack *pstStack);

/* 删除栈 */
extern void stack_delete(stStack *pstStack);

#ifdef __cplusplus
}
#endif

#endif

由于是C语言实现,所以必须添加extern "C"{};


libStack.c

#ifdef __cplusplus
extern "C" {
#endif

#include <malloc.h>
#include <stddef.h>
#include "libStack.h"

/* 创建新的栈 */
stStack *stack_new()
{
	stStack *p;
	p = (stStack *)malloc(sizeof(stStack));
	p->udwPc = 0;
	return p;
}

/* 栈复位 */
void stack_reset(stStack *pstStack)
{
	if (NULL == pstStack)
	{
		return;
	}
	pstStack->udwPc = 0;
}

/* 入栈,栈满时忽略此次操作 */
void stack_push(stStack *pstStack, int udwTmp)
{
	if (NULL == pstStack)
	{
		return;
	}

	if (STACK_MAX_LEN > pstStack->udwPc)
	{
		pstStack->a[pstStack->udwPc] = udwTmp;
		pstStack->udwPc++;
	}
}

/* 出栈,栈空时返回-1 */
int stack_pop(stStack *pstStack)
{
	if (NULL == pstStack)
	{
		return -1;
	}

	if (0 == pstStack->udwPc)
	{
		return -1;
	}
	return pstStack->a[--pstStack->udwPc];
}

/* 栈判空 1-空 0-非空 */
int stack_is_empty(stStack *pstStack)
{
	if (NULL == pstStack)
	{
		/* 空指针默认为空栈 */
		return 1;
	}

	return (0 < pstStack->udwPc)?0:1;
}

/* 删除栈 */
void stack_delete(stStack *pstStack)
{
	if (NULL != pstStack)
	{
		free(pstStack);
	}
}

#ifdef __cplusplus
}
#endif
本套实现只支持正整型数,负数被作为异常值处理。


二、队列的实现

这里队列完全是用上述栈实现的,目的只是练习。

libQueue.h

#ifndef _LIBQUEUE_H
#define _LIBQUEUE_H

#ifdef __cplusplus
extern "C" {
#endif

#include "libStack.h"

#define QUEUE_MAX_LEN STACK_MAX_LEN		/* 队列大小取决与栈的大小 */

typedef struct tagstQueue 
{
	int		udwCnt;
	stStack *pstStack1;				
	stStack *pstStack2;
}stQueue;

/* 创建新队列 */
extern stQueue *queue_new();

/* 入队,队列已满时忽略此次操作 */
extern void in_queue(stQueue *pstQueue, int udwTmp);

/* 出队,队列为空时返回-1 */
extern int out_queue(stQueue *pstQueue);

/* 删除队列 */
extern void queue_delete(stQueue *pstQueue);

/* 队列判空 1-空 0-非空 */
extern int queue_is_empty(stQueue *pstQueue);

#ifdef __cplusplus
}
#endif

#endif

libQueue.c

#ifdef __cplusplus
extern "C" {
#endif

#include <malloc.h>
#include <stddef.h>
#include "libQueue.h"

/* 创建新队列 */
stQueue *queue_new()
{
	stQueue *p;
	p = (stQueue *)malloc(sizeof(stQueue));
	if (NULL == p)
	{
		return NULL;
	}

	p->pstStack1 = stack_new();
	if (NULL == p->pstStack1)
	{
		free(p);
		return NULL;
	}

	p->pstStack2 = stack_new();
	if (NULL == p->pstStack2)
	{
		free(p);
		free(p->pstStack1);
		return NULL;
	}

	p->udwCnt = 0;

	return p;
}

/* 入队,队列已满时忽略此次操作 */
void in_queue(stQueue *pstQueue, int udwTmp)
{
	if (NULL == pstQueue)
	{
		return;
	}

	if (QUEUE_MAX_LEN <= pstQueue->udwCnt)
	{
		return;
	}

	stack_push(pstQueue->pstStack1, udwTmp);
	pstQueue->udwCnt++;
}

/* 出队,队列为空时返回-1 */
int out_queue(stQueue *pstQueue)
{
	int ret = -1;
	int tmp = 0;

	if (NULL == pstQueue)
	{
		return -1;
	}

	/* 队列为空 */
	if (stack_is_empty(pstQueue->pstStack1))
	{
		return -1;
	}

	/* 将栈1内容弹出并压入栈2 */
	while(0 != pstQueue->pstStack1->udwPc)
	{
		tmp = stack_pop(pstQueue->pstStack1);
		stack_push(pstQueue->pstStack2, tmp);
	}

	/* 取栈2顶元素出队 */
	ret = stack_pop(pstQueue->pstStack2);

	/* 将栈2内容压回栈1 */
	while(0 != pstQueue->pstStack2->udwPc)
	{
		tmp = stack_pop(pstQueue->pstStack2);
		stack_push(pstQueue->pstStack1, tmp);
	}

	pstQueue->udwCnt--;

	return ret;
}

/* 删除队列 */
void queue_delete(stQueue *pstQueue)
{
	if (NULL == pstQueue)
	{
		return;
	}

	if (NULL != pstQueue->pstStack2)
	{
		free(pstQueue->pstStack2);
	}

	if (NULL != pstQueue->pstStack1)
	{
		free(pstQueue->pstStack1);
	}

	free(pstQueue);
}

/* 队列判空 1-空 0-非空 */
int queue_is_empty(stQueue *pstQueue)
{
	return (0 < pstQueue->udwCnt)?0:1;
}

#ifdef __cplusplus
}
#endif


三、简单的测试函数

这里我只写了队列的测试:

// ListStackQueue.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "libStack.h"
#include "libQueue.h"

int _tmain(int argc, _TCHAR* argv[])
{
	int i,tmp;

	stQueue *pstQ1 = queue_new();
	stQueue *pstQ2 = queue_new();

	for (i = 0; i < 20; i++)
	{
		in_queue(pstQ1,i);
	}

	for (i = 0; i < 20; i++)
	{
		tmp = out_queue(pstQ1);
		printf("%d ",tmp);
	}

	printf("OK");
	getchar();
	return 0;
}

输出为:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 OK;实现了队列的先入先出功能。

如果试着将栈的大小调整为5,输出为:0 1 2 3 4 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 OK。满足超出空间上限不压栈不入队,出栈出队时若栈队为空则返回-1。




你可能感兴趣的:(嵌入式C语言那点事(二)栈与队列的实现)