栈的相关操作
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操
作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。不含任
何元素的栈称为空栈,栈又称为后进先出的线性表。
栈功能:将数据从一种序列改变到另一种序列
Stack.h
typedef struct Stack
{
DataType* _array;
size_t _top;//栈顶
size_t _end;//栈底
}Stack;
//栈的实现接口
void StackInit(Stack *s);
void StackPush(Stack* s,DataType x);
void StackPop(Stack* s);
DataType StackTop(Stack* s);
size_t StackSize(Stack* s);
int StackEmpty(Stack* s);
//栈的初始化
void StackInit(Stack *s)
{
assert(s);
s->_array = NULL;
s->_end = 0;
s->_top = 0;
}
//入栈
void StackPush(Stack* s, DataType x)
{
if (s->_top == s->_end)//栈中只有一个元素
{
//开辟空间
size_t size = s->_end > 0 ? s->_end * 2 : 3;
s->_array = (DataType*)realloc(s->_array, size*sizeof(DataType));
assert(s->_array);
s->_end = size;
}
s->_array[s->_top++] = x;
}
//出栈
void StackPop(Stack* s)
{
assert(s);
if (s->_top > 0)
(--s)->_top;
}
//获得栈顶元素
DataType StackTop(Stack* s)
{
assert(s);
return s->_array[s->_top - 1];
}
//栈的大小
size_t StackSize(Stack* s)
{
assert(s);
return s->_top;
}
//栈是否为空
int StackEmpty(Stack* s)
{
assert(s);
return s->_top;//返回0则栈为空
}
//测试用例
void TestStack()
{
Stack s;
StackInit(&s);
StackPush(&s, 1);
StackPush(&s, 2);
StackPush(&s, 3);
StackPush(&s, 4);
StackPush(&s, 6);
StackPush(&s, 7);
StackPush(&s, 8);
while(StackEmpty(&s))//栈不为空时
{
printf("%d ", StackTop(&s));
StackPop(&s);
}
printf("\n");
}
Test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include <assert.h>
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include "Stack.h"
int main()
{
//TestStack();
system("pause");
return 0;
}
队列的相关操作
只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性
表 ,进行插入操作的一端称为队尾(入队列) ,进行删除操作的一端称为队头(出队列),遵循先入先出的原则
Queue.h
#pragma once
typedef int DataType;
typedef struct QueueNode
{
DataType _data;
struct QueueNode* _next;
}QueueNode;
typedef struct Queue
{
QueueNode* _head;//队头
QueueNode* _tail;//队尾
}Queue;
void QueueInit(Queue* q);
void QueuePush(Queue* q, DataType x);
void QueuePop(Queue* q);
DataType QueueFront(Queue* q);
DataType QueueBack(Queue* q);
size_t QueueSize(Queue* q);
int QueueEmpty(Queue* q);
//队列初始化
void QueueInit(Queue* q)
{
assert(q);
q->_head = q->_tail = NULL;
}
//入队列
void QueuePush(Queue* q, DataType x)
{
QueueNode* node = NULL;
assert(q);
node = (QueueNode*)malloc(sizeof(QueueNode));
node->_next = NULL;
node->_data = x;
//判断q->_tail
if (q->_tail == NULL)
{
q->_head = q->_tail = node;
}
else
{
q->_tail->_next = node;
q->_tail = node;
}
}
//出队列
void QueuePop(Queue* q)
{
assert(q);
if (q->_head==q->_tail)
{
if (q->_head)
{
free(q->_head);
q->_head = q->_tail = NULL;
}
}
else
{
//多个节点
QueueNode* next = q->_head->_next;
free(q->_head);
q->_head = next;
}
}
//队头
DataType QueueFront(Queue* q)
{
assert(q);
return q->_head->_data;
}
//队尾
DataType QueueBack(Queue* q)
{
assert(q);
return q->_tail->_data;
}
//队列大小
size_t QueueSize(Queue* q)
{
assert(q);
QueueNode* cur = NULL;
size_t size = 0;
cur = q->_head;
while (cur != NULL)
{
size++;
cur = cur->_next;
}
return size;
}
//队列是否为空
int QueueEmpty(Queue* q)
{
assert(q);
return q->_head==NULL ? 0 : 1;
}
//测试用例
void TestQueue()
{
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
QueuePush(&q, 5);
while (QueueEmpty(&q))//队列不为空时
{
printf("%d ", QueueFront(&q));
QueuePop(&q);
}
printf("\n");
}
Test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <windows.h>
#include "Queue.h"
int main()
{
TestQueue();
system("pause");
return 0;
}
这里补充一下,队列容易产生溢出:
假溢出:顺序队列因多次入队列和出队列操作后出现的尚有存储空间但不
能再进行入队列操作的溢出
真溢出:顺序队列最大存储空间已经存满而又要求进行入队列操作所引起
的溢出。
解决假溢出的办法就是循环队列,即将头尾相接的顺序存储队列。
那么循环队列如何判断队列空和满呢?
- 少用一个存储单元
- 设置一个标志位
- 设置一个计数器