数据结构:栈和队列(Stack & Queue)

一,栈

1、栈的定义


栈(Stack):是只允许在一端进行插入或删除的线性表。首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作。

栈顶(Top):线性表允许进行插入删除的那一端。
栈底(Bottom):固定的,不允许进行插入和删除的另一端。
空栈:不含任何元素的空表。

栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构

2、栈的常见基本操作


InitStack(&S):初始化一个空栈S。
StackEmpty(S):判断一个栈是否为空,若栈为空则返回true,否则返回false。
Push(&S, x):进栈(栈的插入操作),若栈S未满,则将x加入使之成为新栈顶。
Pop(&S, &x):出栈(栈的删除操作),若栈S非空,则弹出栈顶元素,并用x返回。
GetTop(S, &x):读栈顶元素,若栈S非空,则用x返回栈顶元素。
DestroyStack(&S):栈销毁,并释放S占用的存储空间(“&”表示引用调用)

3.代码

1.stack.h

#ifndef __STACK_H__
#define __STACK_H__

typedef int DataType;

typedef struct snode
{
	DataType data;
	struct snode *pnext;
}SNode_t;

typedef struct stack
{
	SNode_t *ptop;
	int clen;
}Stack_t;


extern Stack_t *create_stack();
extern int push_stack(Stack_t *, DataType );
extern int pop_stack(Stack_t *, DataType *);
extern int get_stack_top(Stack_t *, DataType *);
extern void clear_stack(Stack_t *);
extern void destroy_stack(Stack_t *);
extern int is_empty_stack(Stack_t *);
extern void stack_for_each(Stack_t *pstack);


#endif

2.stakck.c

#include "stack.h"
#include <stdio.h>
#include <stdlib.h>


Stack_t *create_stack()
{
	Stack_t *pstack = malloc(sizeof(Stack_t));
	if(NULL == pstack)
	{
		perror("fail malloc");
		return NULL; 
	}
	pstack->ptop = NULL;
	pstack->clen = 0;

	return pstack;
}

int push_stack(Stack_t *pstack, DataType data)
{
	SNode_t *pnode = malloc(sizeof(SNode_t));
	if (NULL == pnode)
	{
		perror("fail malloc");
		return -1;
	}
	pnode->data = data;
	pnode->pnext = NULL;

	pnode->pnext = pstack->ptop;
	pstack->ptop = pnode;

	pstack->clen++;

	return 0;
}

void stack_for_each(Stack_t *pstack)
{
	SNode_t *p = pstack->ptop;
	while (p)
	{
		printf("%d ", p->data);
		p = p->pnext;
	}
	printf("\n");
}

int is_empty_stack(Stack_t *pstack)
{
	return NULL == pstack->ptop;
}


int pop_stack(Stack_t *pstack, DataType *pdata)
{
	if (is_empty_stack(pstack))
		return 0;
	
	SNode_t *pdel = pstack->ptop;
	pstack->ptop = pdel->pnext;
	if (pdata != NULL)
	{
		*pdata = pdel->data;
	}

	free(pdel);
	pstack->clen--;

	return 1;
}

int get_stack_top(Stack_t *pstack, DataType *pdata)
{
	if (is_empty_stack(pstack))
		return 0;
	
	if (pdata != NULL)
	{
		*pdata = pstack->ptop->data;
		return 1;
	}
	
	return 0;
}


void clear_stack(Stack_t *pstack)
{
	while (!is_empty_stack(pstack))
	{
		pop_stack(pstack, NULL);
	}
}

void destroy_stack(Stack_t *pstack)
{
	clear_stack(pstack);
	free(pstack);
}

3.主函数调用

#include "stack.h"
#include <stdio.h>


int main(int argc, const char *argv[])
{
	DataType data;
	Stack_t *pstack = create_stack();	
	if (NULL == pstack)
	{
		return -1;
	}
	
	push_stack(pstack, 1);
	push_stack(pstack, 2);
	push_stack(pstack, 3);
	push_stack(pstack, 4);
	
	stack_for_each(pstack);

	pop_stack(pstack, &data);
	printf("data = %d\n", data);

	stack_for_each(pstack);

	get_stack_top(pstack, &data);
	printf("top = %d\n", data);

	destroy_stack(pstack);

	return 0;
}

二,队列


1、队列的定义


队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
队列是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头。


队头(Front):允许删除的一端,又称队首。
队尾(Rear):允许插入的一端。
空队列:不包含任何元素的空表。

假性溢出:

在这里插入图片描述
如图d,队列出现“上溢出”,然而却又不是真正的溢出,所以是一种“假溢出”。

2、队列的常见基本操作


InitQueue(&Q):初始化队列,构造一个空队列Q。
QueueEmpty(Q):判队列空,若队列Q为空返回true,否则返回false。
EnQueue(&Q, x):入队,若队列Q未满,将x加入,使之成为新的队尾。
DeQueue(&Q, &x):出队,若队列Q非空,删除队头元素,并用x返回。
GetHead(Q, &x):读队头元素,若队列Q非空,则将队头元素赋值给x

3、链队列

队列的链式存储结构表示为链队列,它实际上是一个同时带有队头指针和队尾指针的单链表,只不过它只能尾进头出而已
在这里插入图片描述
空队列时,front和real都指向头结点。
在这里插入图片描述

3.代码

1.queue.h

#ifndef __QUEUE_H__
#define __QUEUE_H__

#include <pthread.h>
typedef int QDataType;

typedef struct qnode
{
	QDataType data;
	struct qnode *pnext;
}QNode_t;

typedef struct queue
{
	QNode_t *pfront;
	QNode_t *prear;
	int clen;
	pthread_mutex_t mutex;
}Queue_t;

Queue_t *create_queue();
int is_empty_queue(Queue_t *);
int push_queue(Queue_t *, QDataType );
int pop_queue(Queue_t *, QDataType *);
int get_queue_front(Queue_t *, QDataType *);
void clear_queue(Queue_t *);
void destroy_queue(Queue_t *);
extern void queue_for_each(Queue_t *pque);

#endif

2.queue.c

#include "queue.h"
#include <stdlib.h>
#include <stdio.h>

Queue_t *create_queue()
{
	Queue_t *pque = malloc(sizeof(Queue_t));
	if (NULL == pque)
	{
		perror("fail malloc");
		return NULL;
	}
	pque->pfront = NULL;
	pque->prear = NULL;
	pque->clen = 0;

	pthread_mutex_init(&(pque->mutex), NULL);

	return pque;
}

int is_empty_queue(Queue_t *pque)
{
	return NULL == pque->pfront;
}
int push_queue(Queue_t *pque, QDataType data)
{
	QNode_t *pnode = malloc(sizeof(QNode_t));
	if (NULL == pnode)
	{
		perror("fail malloc");
		return -1;
	}
	pnode->data = data;
	pnode->pnext = NULL;

	if (is_empty_queue(pque))
	{
		pque->pfront = pnode;
		pque->prear = pnode;
	}
	else
	{
		pque->prear->pnext = pnode;
		pque->prear = pnode;
	}
	pque->clen++;
	
	return 0;
}

void queue_for_each(Queue_t *pque)
{
	QNode_t *p = pque->pfront;
	while (p != NULL)
	{
		printf("%d ", p->data);
		p = p->pnext;
	}
	printf("\n");
}

int pop_queue(Queue_t *pque, QDataType *pdata)
{
	if (is_empty_queue(pque))
		return 0;
	
	QNode_t *pdel = pque->pfront;
	pque->pfront = pdel->pnext;
	if (pdata != NULL)
	{
		*pdata = pdel->data;
	}
	free(pdel);
	if (NULL == pque->pfront)
	{
		pque->prear = NULL;
	}
	
	pque->clen--;

	return 1;
}

int get_queue_front(Queue_t *pque, QDataType *pdata)
{
	if (is_empty_queue(pque))
		return 0;
	if (NULL == pdata)
		return 0;
	
	*pdata = pque->pfront->data;

	return 1;
}

void clear_queue(Queue_t *pque)
{
	while (!is_empty_queue(pque))
	{
		pop_queue(pque, NULL);
	}
}


void destroy_queue(Queue_t *pque)
{
	clear_queue(pque);
	free(pque);
}

3.主函数调用

#include "queue.h"
#include <stdio.h>

int main(int argc, const char *argv[])
{
	QDataType data;

	Queue_t *pque = create_queue();	
	if (NULL == pque)
	{
		return -1;
	}
	
	push_queue(pque, 1);
	push_queue(pque, 2);
	push_queue(pque, 3);
	push_queue(pque, 4);
	
	queue_for_each(pque);
		
	pop_queue(pque, &data);

	queue_for_each(pque);

	int ret = get_queue_front(pque, &data);
	if (ret != 0)
	{
		printf("front: %d\n", data);
	}

	destroy_queue(pque);

	return 0;
}

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值