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

栈与队列是两种重要的数据结构,有着广泛的应用,他们可以通过对链表功能加以限制改造而来。栈是一种先进后出(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;
	}
}

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

时间: 2024-08-23 09:10:35

数据结构入门——栈与队列的相关文章

【数据结构】栈和队列

栈和队列 容器数据结构是指一些包含了若干个其他相同或不同的数据结构的数据结构,被包含的这些每一个独立的数据结构都被称为一个元素,在一个容器中的元素往往支持相同的操作,具有类似的性质.之前说到过的线性表其实就是一种容器数据结构,本文中介绍的两种最常用的容器数据结构是栈和队列. 从功能上看,栈和队列大多用于计算过程中保存临时数据,这些数据是在计算过程中发现或产生的.在而后的计算中可能会用到这些数据.如果这些数据是固定的个数以及大小的话,可以构建几个变量来储存它们,但是如果这些数据不确定的话,就需要一

二、数据结构之栈、队列、循环队列

二.数据结构之栈.队列.循环队列 顺序栈 Stack.h 结构类型,函数声明: #ifndef _STACK_H_ #define _STACK_H_ typedef int SElementType; ///顺序栈 #define STACK_INIT_SIZE 20 #define STACK_INCREMENT 10 typedef struct { SElementType * base; SElementType * top; int stackSize;///当前栈的大小 }SqSt

数据结构之栈和队列

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

数据结构之栈与队列

数据结构的有一个重要结构栈,栈这种数据结构就是满足先进后出的这种规则的数据结构就是栈,引用<大话数据结构>中的一个形象例子就是,子弹的弹夹,最先压入弹夹的子弹最后一个出弹夹,正好往一个栈里添加一个元素叫压栈.入栈,从栈里出来一个元素叫弹栈,出栈.指示器就叫栈帧. 栈图 现在就贴上代码: 栈的几个基本操作: #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct node{

数组拷贝、数组函数、通过数组函数来模拟数据结构的栈和队列、回调的意义、数组函数的排序问题、算法以及寻找素数的筛选法

1.数组的拷贝数组拷贝时指针的指向问题. 数组在拷贝时,指针的位置随之复制[这一点拷贝是完全一样]但是如果拷贝的数组的指针是非法的,那么拷贝出新指针的位置进行初始化<?php$arr1=array('123');end($arr1);next($arr1);//这个指针非法$arr2 = $arr1;//这里进行数组的拷贝var_dump(current($arr2));//得到指向‘123’元素的指针var_dump(current($arr1));//此时这个数组的指针有问题?> 但是拷贝

[ACM训练] 算法初级 之 数据结构 之 栈stack+队列queue (基础+进阶+POJ 2442+1442)

再次面对像栈和队列这样的相当基础的数据结构的学习,应该从多个方面,多维度去学习. 首先,这两个数据结构都是比较常用的,在标准库中都有对应的结构能够直接使用,所以第一个阶段应该是先学习直接来使用,下一个阶段再去探究具体的实现,以及对基本结构的改造! C++标准库中 这里记录一个经典的关于栈和队列的面试题目: 题目:实现一个栈,带有出栈(pop),入栈(push),取最小元素(getMin)三个方法.要保证这三个方法的时间复杂度都是O(1). 思路:重点是getMin()函数的设计,普通思路是设计一

浅谈数据结构系列 栈和队列

计算机程序离不开算法和数据结构,在数据结构算法应用中,栈和队列应用你比较广泛,因为两者在数据存放和读取方面效率比较高,本章节重点讲解两者的基本概念和实现. 基本概念 栈:是一种先进后出,后进先出的数据结构,本质上是线性表,只是限制仅允许在表的一段进行插入和删除工作.此端为栈顶,这是在栈中应用很关键的概念.所有数据的处理都是在栈顶进行的,进栈时,栈中元素增加,栈顶上移一位,出栈时栈顶下移一位.应用中比如:洗碗,每次洗干净的碗放在上面-进栈,取碗,从顶上取出一个-出栈:装子弹-进栈,开枪-出栈. 队

python——python数据结构之栈、队列的实现

这个在官网中list支持,有实现. 补充一下栈,队列的特性: 1.栈(stacks)是一种只能通过访问其一端来实现数据存储与检索的线性数据结构,具有后进先出(last in first out,LIFO)的特征 2.队列(queue)是一种具有先进先出特征的线性数据结构,元素的增加只能在一端进行,元素的删除只能在另一端进行.能够增加元素的队列一端称为队尾,可以删除元素的队列一端则称为队首. 地址在 http://docs.python.org/2/tutorial/datastructures.

数据结构之栈和队列及其Java实现

栈和队列是数据结构中非常常见又非常基础的线性表,在某些场合栈和队列使用很多,因此本篇主要介绍栈和队列,并用Java实现基本的栈和队列,同时用两个栈实现队列和用两个队列实现栈. 栈:栈是一种基于"后进先出"策略的线性表.在插入时(入栈),最先插入的元素在栈尾,最后插入的元素在栈顶:在删除时(出栈),最后插入的元素先出栈,最先插入的元素最后出栈.由此可见,对栈的插入和删除操作都是在栈顶位置进行的. 在Java中,提供了一个类Stack<E>来实现栈的这些特性,并提供了一些常用的