数据结构——栈和队列

栈(Stack)

一、栈的基本概念

:栈是只允许在一端插入和删除数据的线性表,允许插入和删除的一端称作栈顶,另一端称作栈底。我们将插入数据称作压栈/入栈/进栈,删除数据称作出栈。
在这里插入图片描述
栈的基本操作

  • 对栈的初始化
  • 对栈的判空
  • 对栈的插入删除
  • 读取栈顶元素
  • 获取栈内元素个数
  • 销毁栈

二、栈的基本功能和实现

1.栈的结构

用数组和链表都可以实现栈,但是数组在删除数据时优于链表。下面我们将实现数组栈。

typedef int STDataType;//元素的类型

typedef struct stack
{
	STDataType* a;//存放数据的数组
	int top;//栈顶
	int capacity;//数组最大容量
}ST;

2.对栈的初始化

在对栈的初始化时,我们可以选着在开始就给一些空间,也可以在插入数据时再扩容。这里选择初始化时扩容。

void STinit(ST* p)
{
	assert(p);//防止对空指针解引用
	STDataType* p->a = (STDataType*)malloc(sizeof(STDataType) * 4);
	if(p->a == NULL)
	{
		perror("malloc file");
		exit(-1);
	 }
	p->capacity = 4;
	p->top = 0;
}

3.对栈的插入和删除

入栈时注意是否还有空间,没空间时需要扩容,而出栈时要注意是否还有数据可以删除。

//入栈
void STpush(ST* p, STDataType data)
{
	assert(p);//防止对空指针解引用
	if (p->top == p->capacity)//判断数据是否满了,满了则扩容
	{
		STDataType* newa = (STDataType*)realloc(p->a, sizeof(STDataType) * 2 * p->capacity);	
		if (!newa)
		{
			perror("malloc file");
			exit(-1);
		}
		p->a = newa;
		p->capacity *= 2;
	}
	p->a[p->top] = data;
	p->top++;
}
//出栈
void STpop(ST* p)
{
	assert(p);//防止对空指针解引用
	assert(!STEmpty(p));//STEmpty函数是判断栈内是否为空,之后会有介绍
	p->top--;
}

4.判断栈是否为空、返回栈顶元素和获取栈内元素个数

这三个函数非常简单,我就放在一起了

//栈是否为空
bool STEmpty(ST* p)
{
	assert(p);
	return p->top == NULL;
}
//读取栈顶元素
STDataType STtop(ST* p)
{
	assert(p);
	assert(!STEmpty(p));
	return p->a[p->top-1];
}
//栈内元素个数
int STsize(ST* p)
{
	assert(p);
	return p->top;
}

虽然这三个函数很简单,但其他使用者在使用这个栈时可能并不清楚底层是这么实现的。有了这些函数,使用者就可以不用了解底层实现从而对栈操作。

5.销毁栈

void STDestory(ST* p)
{
	assert(p);
	assert(p->a);
	free(p->a);
	p->a = NULL;
	p->capacity = 0;
	p->top = 0;
}

队列(Queue)

一、队列的基本概念

队列:只允许在一段插入数据,在另一端删除数据。插入数据的一段称作队头,另一端称作队尾。
在这里插入图片描述
队列的基本操作

  • 队列的初始化
  • 队列的插入删除数据
  • 查询队列元素个数
  • 获取队头队尾元素
  • 对队列的判空
  • 队列的销毁

二、队列的基本功能和实现

1.队列的结构

和栈一样,数组和链表都可以实现队列,但是队列的删除放在头部,使用数组的话效率太低了,所以一般我们使用链表实现。

typedef int QueueDataType;//元素的类型

typedef struct Data//链表的节点
{
	QueueDataType data;
	struct Data* next;
}Data;

typedef struct Queue//队列
{
	Data* head;//指向链表头元素
	Data* tail;//指向链表尾元素
	unsigned int size;//链表中元素的个数
}Queue;

2.队列的初始化

void QueueCreate(Queue* p)//创建队列
{
	p = (Queue*)malloc(sizeof(Queue));
	if (p == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	p->head = NULL;
	p->tail = NULL;
	p->size = 0;
}

3.对队列的插入和删除

//插入数据
void QueuePush(Queue* p, QueueDataType data)
{
	assert(p);
	Data* newdata = (Data*)malloc(sizeof(Data));
	if (newdata == NULL)
	{
		perror("malloc file");
		exit(-1);
	}
	newdata->data = data;
	newdata->next = NULL;
	if (p->head == NULL)//判断是不是第一次插入数据,第一次插入数据时,头指针等于尾指针
	{
		p->head = newdata;
		p->tail = newdata;
	}
	else
	{
		p->tail->next = newdata;
		p->tail = newdata;
	}
	p->size++;
}
//删除数据
void QueuePop(Queue* p)
{
	assert(p);
	assert(p->head);
	Data* def = p->head;
	p->head = p->head->next;
	if (p->head == NULL)
	{
		p->tail = NULL;
	}
	free(def);
	p->size--;
}

4.查询队列元素个数

unsigned int QueueSize(Queue* p)//返回数据个数
{
	assert(p);
	return p->size;
}

5.获取队头,队尾元素

QueueDataType QueueFront(Queue* p)//返回队首数据
{
	assert(p);
	assert(p->head);
	return p->head->data;
}

QueueDataType QueueBack(Queue* p)//返回队尾数据
{
	assert(p);
	assert(p->tail);
	return p->tail->data;
}

6.对队列的判空

bool QueueEmpty(Queue* p)//数据是否为空
{
	assert(p);
	return p->size == 0;
}

7.队列的销毁

void QueuePop(Queue* p)//删除数据
{
	assert(p);
	assert(p->head);
	Data* def = p->head;

	p->head = p->head->next;
	if (p->head == NULL)
	{
		p->tail = NULL;
	}
	free(def);
	p->size--;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值