栈和队列
一、栈
1.栈的定义
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素的操作。进行数据插入和删除的一端为栈顶,另一端为栈底。
2.栈的特点
栈中的元素遵守后进先出(Last In First Out)、先进后出(First In Last Out)的原则。
压栈:栈的插入操作叫进栈/压栈/入栈,入数据在栈顶
出栈:栈的删除的操作叫出栈,出数据也在栈顶
3.栈的实现以及分析
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上
插入数据的代价比较小。
代码如下:
Stack.h
#pragma once
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int Capacity;
}ST;
void StackInit(ST* ps);
void StackDestory(ST* ps);
void StackPush(ST* ps, STDataType x);
void StackPop(ST* ps);
void StackSize(ST* ps);
void StackTop(ST* ps);
void StackEmpty(ST* ps);
void StackPrint(ST*ps);
Stack.c
#include "Stack.h"
void StackInit(ST* ps)
{
assert(ps);
ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
if (ps->a == NULL)
{
printf("malloc fail.\n");
exit(-1);
}
ps->Capacity = 4;
ps->top = 0;
printf("初始化成功\n");
system("pause");
system("cls");
}
void StackDestory(ST* ps)
{
assert(ps);
free(ps->a);
ps->a =NULL;
printf("栈销毁成功\n");
system("pause");
system("cls");
}
void StackPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->Capacity)
{
STDataType* tep = realloc(ps->a, ps->Capacity * 2 * sizeof(STDataType));
if (tep == NULL)
{
printf("realloc fail.\n");
exit(-1);
}
else
{
ps->a = tep;
ps->Capacity *= 2;
}
}
ps->a[ps->top] = x;
ps->top++;
printf("入栈成功\n");
system("pause");
system("cls");
}
void StackPop(ST* ps)
{
assert(ps);
assert(ps->top > 0);
ps->top--;
printf("出栈成功\n");
}
void StackSize(ST* ps)
{
assert(ps);
printf("栈中有%d个数据\n", ps->top);
system("pause");
system("cls");
}
void StackTop(ST* ps)
{
assert(ps);
assert(ps->top > 0);
printf("栈顶元素是:%d\n", ps->a[ps->top - 1]);
system("pause");
system("cls");
}
void StackEmpty(ST* ps)
{
if (ps->top == 0)
printf("栈为空\n");
else
printf("栈中还有:%d个数据\n", ps->top);
system("pause");
system("cls");
}
void StackPrint(ST* ps)
{
assert(ps);
assert(ps->top>0);
while(ps->top!=0)
{
printf("%d ", ps->a[ps->top - 1]);
ps->top--;
}
printf("\n");
printf("打印成功\n");
system("pause");
system("cls");
}
Test.c
#include "Stack.h"
void WelcomeInfo()
{
printf("\n\n");
printf(" *******************************************\n");
printf(" * 欢迎使用栈操作系统 *\n");
printf(" *******************************************\n");
printf(" * 请选择功能列表 *\n");
printf(" *******************************************\n");
printf(" * 1:初始化栈内信息 *\n");
printf(" * 2:压栈 *\n");
printf(" * 3:出栈 *\n");
printf(" * 4:计算栈内数据个数 *\n");
printf(" * 5:栈顶元素 *\n");
printf(" * 6:判断栈是否为空 *\n");
printf(" * 7:销毁栈 *\n");
printf(" * 8:打印栈内信息 *\n");
printf(" * 0:退出栈操作系统 *\n");
printf(" *******************************************\n");
}
int main()
{
ST st;
while (1)
{
// 清除输出
system("cls");
WelcomeInfo();
printf("请输入数字:");
char ch = getchar();
switch (ch)
{
case '1':
//初始化栈内信息
StackInit(&st);
break;
case '2':
//压栈
{
STDataType x = 0;
printf("请输入进栈的数据:\n");
scanf("%d", &x);
StackPush(&st, x);
break;
}
case '3':
//出栈
StackPop(&st);
break;
case '4':
{
//计算栈内数据个数
StackSize(&st);
break;
}
case '5':
{
//栈顶元素
StackTop(&st);
break;
}
case '6':
{
//判断栈是否为空
StackEmpty(&st);
break;
}
case '7':
{
//销毁栈
StackDestory(&st);
printf("销毁成功\n");
break;
}
case '8':
{
//打印栈内信息
StackPrint(&st);
break;
}
case '0':
//退出栈操作系统
exit(0);
break;
default:
break;
}
}
return 0;
}
二、队列
1.什么是队列
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先
进先出FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
2.队列的特点(与栈对比)
特点:先进先出(First In First Out)
3.队列的实现以及分析
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,
出队列在数组头上出数据,效率会比较低。
代码如下:
Queue.h
#pragma once
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int QDataType;
typedef struct QueueNode
{
struct QNode* next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
}Queue;
void QueueInit(Queue* qp);
void QueueDestory(Queue* qp);
void QueuePush(Queue* qp,QDataType x);
void QueuePop(Queue* qp);
QDataType QueueFront(Queue* qp);
QDataType QueueBack(Queue* qp);
int QueueSize(Queue* qp);
bool QueueEmpty(Queue* qp);
Queue.c
#include "Queue.h"
void QueueInit(Queue* qp)
{
assert(qp);
qp->head = qp->tail = NULL;
}
void QueueDestory(Queue* qp)
{
assert(qp);
QNode* cur = qp->head;
while(cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
qp->head = qp->tail = NULL;
}
void QueuePush(Queue* qp, QDataType x)
{
assert(qp);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
printf("malloc fail.\n");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
if (qp->tail == NULL)
{
qp->head = qp->tail = newnode;
}
else
{
qp->tail->next = newnode;
qp->tail = newnode;
}
}
void QueuePop(Queue* qp)
{
assert(qp);
assert(qp->head);
if (qp->head->next == NULL)
{
free(qp->head);
qp->head = qp->tail = NULL;
}
else
{
QNode* next = qp->head->next;
free(qp->head);
qp->head = next;
}
}
QDataType QueueFront(Queue* qp)
{
assert(qp);
assert(qp->head);
return qp->head->data;
}
QDataType QueueBack(Queue* qp)
{
assert(qp);
assert(qp->head);
return qp->tail->data;
}
int QueueSize(Queue* qp)
{
assert(qp);
int size = 0;
QNode* cur = qp->head;
while (cur)
{
size++;
cur = cur->next;
}
return size;
}
bool QueueEmpty(Queue* qp)
{
assert(qp);
return qp->head == NULL;
}
Test.c
#include "Queue.h"
int main()
{
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
printf("%d ",QueueFront(&q));
QueuePop(&q);
printf("%d ", QueueFront(&q));
QueuePop(&q);
QueuePush(&q, 3);
QueuePush(&q, 4);
while (!QueueEmpty(&q))
{
printf("%d ", QueueFront(&q));
QueuePop(&q);
}
printf("\n");
QueueDestory(&q);
return 0;
}