码迷,mamicode.com
首页 > 其他好文 > 详细

数据结构入门——栈与队列

时间:2015-08-05 13:04:36      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:数据结构   编程      队列   

    栈与队列是两种重要的数据结构,有着广泛的应用,他们可以通过对链表功能加以限制改造而来。栈是一种先进后出(FILO)的数据结构,只能在一头进行加入删除,而队列是一种先进先出(FIFO)的数据结构,一头只能加入,另一头只能删除。


栈的实现:

# include <stdio.h>
# include <malloc.h>
# include <stdlib.h>

typedef struct Node
{
	int data;
	struct Node * pNext;
}NODE, * PNODE;

typedef struct Stack
{
	PNODE pTop;
	PNODE pBottom;
}STACK, * PSTACK;

//函数声明
void init_stack(PSTACK);  //创建一个空栈
void push_stack(PSTACK, int);  //压栈
void traverse_stack(const PSTACK);  //遍历输出
bool empty_stack(PSTACK);  //判断栈是否为空
bool pop_stack(PSTACK, int *);  //出栈
bool clear_stack(PSTACK);  //将栈清空

int main(void)
{
	STACK s;
	int val;

	init_stack(&s);
	push_stack(&s, 1);
	push_stack(&s, 2);
	push_stack(&s, 78);
	push_stack(&s, 499);
	push_stack(&s, 97);
	push_stack(&s, 134);
	traverse_stack(&s);
	pop_stack(&s, &val);
	/*
	if( pop_stack(&s, &val) )  //如果将if语句写在这里,if中的判断式已经执行过一次,即出栈一次,会造成bug。
	{
		printf("出栈成功,出栈的元素值为:%d\n", val);
	}
	else
	{
		printf("出栈失败!\n");
	}
	*/

	traverse_stack(&s);
	printf("清空栈!\n");
	clear_stack(&s);
	traverse_stack(&s);

	return 0;
}

void init_stack(PSTACK pS)
{
	pS->pTop = (PNODE)malloc(sizeof(NODE));
	if (NULL == pS->pTop)
	{
		printf("内存分配失败!\n");
		exit(-1);
	}
	else
	{
		pS->pBottom = pS->pTop;
		pS->pTop->pNext = NULL;
	}

	return;
}

void push_stack(PSTACK pS, int val)
{
	PNODE pNew = (PNODE)malloc(sizeof(NODE));
	if (NULL == pNew)
	{
		printf("压栈内存分配失败!\n");
		return;
	}

	pNew->data = val;
	pNew->pNext = pS->pTop;
	pS->pTop = pNew;

	return;
}

void traverse_stack(const PSTACK pS)
{
	PNODE p = pS->pTop;
	if ( empty_stack(pS) )
	{
		printf("输出失败,栈为空!\n");
	}
	else
	{
		printf("栈中的元素为:\n");

		while (p != pS->pBottom)
		{
			printf("%d\t", p->data);
			p = p->pNext;
		}
		printf("\n");
	}

	return;
}

bool empty_stack(PSTACK pS)
{
	if(pS->pTop == pS->pBottom)
		return true;
	else
		return false;
}

bool pop_stack(PSTACK pS, int * pVal)
{
	if ( empty_stack(pS) )
	{
		printf("栈为空,出栈失败!\n");
		return false;
	}
	else
	{
		PNODE p = pS->pTop;
		*pVal = p->data;
		pS->pTop = p->pNext;
		printf("出栈成功,出栈的元素值为:%d\n", p->data);
		free(p);
	
		p = NULL;


		return true;
	}
}

bool clear_stack(PSTACK pS)
{
	if ( empty_stack(pS) )
	{
		printf("栈为空,无法清空!\n");
		return false;
	}
	else
	{
		PNODE p, q;
		p = pS->pTop;

		while (pS->pBottom != p)
		{
			q = p->pNext;
			free(p);
			p = q;
		}
		pS->pTop = pS->pBottom;
	}

	return true;
}

循环队列

    顺序队列有一个先天不足, 那就是空间利用率不高, 会产生”假溢出”现象,即:其实队列中还有空闲的空间以存储元素, 但我们在判断队列是否还有空间时, 队列告诉我们队列已经满了, 因此这种溢出并不是真正的溢出, 在data数组中依然存在可以放置元素的空位置, 所以说这是一种”假溢出”;

    于是我们就引入了循环队列的概念, 将顺序队列臆造为一个环状的空间, 即把存储队列元素的表从逻辑上看成一个环, 称为循环队列,其示意图如下:

技术分享

注意:如图中所示,我们的循环队列为了在实现上的便利, 会有一个位置的空闲, m_front(如图中的front)指针总会指向一个元素值为空的位置,因此(m_front+1)%capacity才真正的指向队首元素, 而m_rear(图中为rear)才指向一个真实存在的队尾元素;

循环队列的实现:

# include <stdio.h>
# include <malloc.h>

typedef struct Queue
{
	int * pBase;
	int front;
	int rear;
}QUEUE;

void init(QUEUE *);  //队列初始化
bool en_queue(QUEUE *, int);  //入队
void traverse_queue(QUEUE *);  //遍历队列
bool is_full(QUEUE *);  //判断队列是否为满
bool is_empty(QUEUE *);  //判断队列是否为空
bool out_queue(QUEUE *, int *);  //出队

int main(void)
{
	QUEUE Q;
	int val;

	init(&Q);
	en_queue(&Q, 1);
	en_queue(&Q, 2);
	en_queue(&Q, 3);
	en_queue(&Q, 4);
	en_queue(&Q, 5);
	en_queue(&Q, 6);
	en_queue(&Q, 7);
	en_queue(&Q, 8);

	traverse_queue(&Q);

	out_queue(&Q, &val);
	out_queue(&Q, &val);

	traverse_queue(&Q);

	return 0;
}

void init(QUEUE * pQ)
{
	pQ->pBase = (int *)malloc(sizeof(int)*6);
	pQ->front = 0;
	pQ->rear = 0;
}

bool en_queue(QUEUE * pQ, int val)
{
	if (is_full(pQ))
	{
		printf("入队失败,队列已满!\n");
		return false;
	}
	else
	{
		pQ->pBase[pQ->rear] = val;
		pQ->rear = (pQ->rear+1)%6;

		return true;
	}
}

bool is_full(QUEUE * pQ)
{
	if ((pQ->rear+1)%6 == pQ->front)
		return true;
	else
		return false;
}

void traverse_queue(QUEUE *pQ)
{
	int i = pQ->front;
	
	printf("队列元素为:\n");
	while(i != pQ->rear)
	{
		printf("%d ", pQ->pBase[i]);
		i = (i+1)%6;
	}
	printf("\n");
}

bool out_queue(QUEUE * pQ, int * pVal)
{
	int val;

	if (is_empty(pQ))
	{
		printf("出队失败,队列为空!\n");
		return false;
	}
	else
	{
		*pVal = pQ->pBase[pQ->front];
		val = pQ->pBase[pQ->front];
		pQ->front = (pQ->front + 1) % 6;
		printf("出队成功,出队的元素是:%d\n", val);

		return true;
	}
}

bool is_empty(QUEUE * pQ)
{
	if (pQ->front == pQ->rear)
	{
		return true;
	}
	else
	{
		return false;
	}
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

数据结构入门——栈与队列

标签:数据结构   编程      队列   

原文地址:http://blog.csdn.net/lfhappypain/article/details/47292851

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!