栈
栈的概念: 一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。
栈顶: 进行数据插入和删除操作的一端
栈底: 与栈顶相对的另一端
栈的基本操作需要遵守的原则:
栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈: 栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈: 栈的删除操作叫做出栈。出数据也在栈顶。
图示
功能实现
实现栈(基于支持动态扩展的顺序表)
//Sysutil.h
ifndef __SYSUTIL_H___
#define __SYSUTIL_H___
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdbool.h>
#pragma warning(disable:4996)
#endif
//Stack.h
#ifndef __STACK_H__
#define __STACK_H__
#include "Sysutil.h"
#define ElemType int
///动态增长的顺序栈
#define DEFAULT_SIZE 8
typedef struct SeqStack
{
ElemType* base;
int capacity;
int top;
}SeqStack;
void SeqStackInit(SeqStack* ps,int size);
void SeqStackPush(SeqStack* ps,ElemType x);
void SeqStackPop(SeqStack* ps);
ElemType SeqStackTop(SeqStack* ps);
int SeqStackSize(SeqStack* ps);
int SeqStackEmpty(SeqStack* ps);
void SeqStackDestroy(SeqStack* ps);
void SeqStackShow(SeqStack* ps);
static int IsFull(SeqStack* ps);
static void SeqStackInc(SeqStack* ps);
static int IsFull(SeqStack* ps)
{
return ps->top >= ps->capacity;
}
int SeqStackEmpty(SeqStack* ps)
{
return 0 == ps->top;
}
static void SeqStackInc(SeqStack** pps)
{
ElemType* q = (ElemType*)realloc((*pps)->base,sizeof(ElemType)* ((*pps)->capacity) * 2);
if (q)
(*pps)->base = q;
else
printf("扩容失败!\n");
}
void SeqStackInit(SeqStack* sp,int size)
{
size = size > DEFAULT_SIZE ? size : DEFAULT_SIZE;
if (sp && size > 0) {
sp->base = (ElemType*)malloc(sizeof(ElemType) * size);
sp->capacity = size;
sp->top = 0;
}
else
printf("栈不存在!\n");
}
void SeqStackPush(SeqStack* ps,ElemType x)
{
if (ps) {
if (IsFull(ps))
SeqStackInc(&ps);
ps->base[ps->top++] = x;
}
else
printf("栈不存在!\n");
}
void SeqStackShow(SeqStack* ps)
{
if (ps) {
if (SeqStackEmpty(ps))
printf("空栈!\n");
else {
printf("栈底:");
for (int i = 0; i < ps->top; i++)
printf("%d-->", ps->base[i]);
printf("栈顶\n");
}
}
else
printf("栈不存在!\n");
}
void SeqStackDestroy(SeqStack* ps)
{
free(ps->base);
ps->capacity = ps->top = 0;
}
void SeqStackPop(SeqStack* ps)
{
if (!SeqStackEmpty(ps))
ps->top--;
}
int SeqStackSize(SeqStack* ps)
{
if (!SeqStackEmpty(ps))
return ps->top;
else
return 0;
}
ElemType SeqStackTop(SeqStack* ps)
{
assert(ps && !SeqStackEmpty(ps));
return ps->base[ps->top - 1];
}
void SeqStackMenu()
{
printf("##############动态顺序表栈#############\n");
printf("##########[1]入栈 [2]出栈##########\n");
printf("##########[3]验空 [4]计数##########\n");
printf("##########[5]栈顶 [6]展示##########\n");
printf("##########[7]摧毁 [0]退出##########\n");
printf("#######################################\n");
}
#endif
//StackMain.c
#include "Stack.c"
int main()
{
SeqStack stack;
SeqStackInit(&stack,DEFAULT_SIZE);
ElemType item;
int choice = 0;
int quit = 1;
while (quit) {
SeqStackMenu();
printf("请输入想要执行的操作#");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("请输入将入栈元素(-1结束)#");
while (scanf("%d", &item), item != -1) {
SeqStackPush(&stack, item);
}
SeqStackShow(&stack);
break;
case 2:
SeqStackPop(&stack);
SeqStackShow(&stack);
break;
case 3:
if (!SeqStackEmpty(&stack))
printf("非空栈!\n");
else
printf("空栈!\n");
break;
case 4:
printf("栈目前共有[%d]个元素!\n",SeqStackSize(&stack));
break;
case 5:
item = SeqStackTop(&stack);
if(-1!= item)
printf("栈顶元素为[%d]\n", SeqStackTop(&stack));
else
printf("空栈!\n");
break;
case 6:
SeqStackShow(&stack);
break;
case 7:
SeqStackDestroy(&stack); break;
case 0:
printf("再见!\n"); quit = 0; break;
}
system("pause");
system("cls");
}
return 0;
}
队列
队列: 只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表
队头: 进行删除操作的一端
队尾: 进行插入操作的一端
队列的基本操作需要遵守的原则:
栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则,即元素进入队列需要从队尾进入,元素出队列需要从队头出去。
出队: 栈的插入操作叫做入队,入队在队尾。
入队: 队的删除操作叫做出栈,出队在队头。
图示
基本功能
实现队(基于无头单向链表实现)
//Queue.h
#ifndef __QUEUE_H__
#define __QUEUE_H__
#include "Sysutil.h"
//#define QDataType int
struct BTNode;
#define QDataType struct BTNode*
单向链表队列///
typedef struct QListNode
{
struct QListNode* _next;
QDataType _data;
}QNode;
typedef struct Queue
{
QNode* _front;
QNode* _rear;
}Queue;
void QueueInit(Queue* q);
void QueuePush(Queue* q, QDataType data);
void QueuePop(Queue* q);
QDataType QueueFront(Queue* q);
QDataType QueueBack(Queue* q);
int QueueSize(Queue* q);
int QueueEmpty(Queue* q);
void QueueDestroy(Queue* q);
void QueueMenu();
static QNode* BuyNode(QDataType x);
void QueueShow();
static QNode* BuyNode(QDataType x)
{
QNode* p = (QNode*)malloc(sizeof(QNode));
p->_data = x;
p->_next = NULL;
return p;
}
void QueueInit(Queue* q)
{
if (q) {
q->_front = NULL;
q->_rear = NULL;
}
else
printf("队列不存在!\n");
}
void QueuePush(Queue* q, QDataType data)
{
if (!q) {
printf("队列不存在!\n");
return;
}
else {
QNode* s = BuyNode(data);
if (QueueEmpty(q))
q->_front = q->_rear = s;
else {
q->_rear->_next = s;
q->_rear = s;
}
}
}
void QueuePop(Queue* q)
{
if (q) {
if (q->_front)
{
QNode* p = q->_front;
q->_front = q->_front->_next;
free(p);
p = NULL;
}
else
printf("空队列!\n");
}
else
printf("队列不存在!\n");
}
QDataType QueueFront(Queue* q)
{
assert(q&&q->_front);
return q->_front->_data;
}
QDataType QueueBack(Queue* q)
{
assert(q&&q->_rear);
return q->_rear->_data;
}
int QueueSize(Queue* q)
{
int size = 0;
if (q) {
QNode* p = q->_front;
while (p) {
size++;
p = p->_next;
}
}
else {
printf("队列不存在!\n");
}
return size;
}
int QueueEmpty(Queue* q)
{
if (q)
return !q->_front;
else {
printf("队列不存在!\n");
return 1;
}
}
void QueueDestroy(Queue* q)
{
if (q) {
QNode* p = q->_front;
QNode* pre = p;
while (pre) {
p = p->_next;
free(pre);
pre = p;
}
q->_front = q->_rear = NULL;
}
}
void QueueShow(Queue* q)
{
if (q->_front == q->_rear && !q->_front)
printf("空队列!\n");
else {
QNode* p = q->_front;
printf("队头:");
while (p) {
printf("%d<--", p->_data);
p = p->_next;
}
printf("队尾\n");
}
}
void QueueMenu()
{
printf("##############单向链表队列#############\n");
printf("##########[1]入队 [2]出队##########\n");
printf("##########[3]验空 [4]计数##########\n");
printf("##########[5]队头 [6]队尾##########\n");
printf("##########[7]摧毁 [8]展示##########\n");
printf("########## [0]退出 ##########\n");
printf("#######################################\n");
}
#endif
//QueueMain.c
#include "Queue.h"
int main()
{
Queue Q;
QueueInit(&Q);
QDataType item;
int choice = 0;
int quit = 1;
while (quit) {
QueueMenu();
printf("请输入想要执行的操作#");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("请输入将入队列元素(-1结束)#");
while (scanf("%d", &item), item != -1) {
QueuePush(&Q, item);
}
QueueShow(&Q);
break;
case 2:
QueuePop(&Q);
QueueShow(&Q);
break;
case 3:
if (!QueueEmpty(&Q))
printf("非空队列!\n");
else
printf("空队列!\n");
break;
case 4:
printf("队列目前共有[%d]个元素!\n", QueueSize(&Q));
break;
case 5:
printf("队头元素为[%d]\n", QueueFront(&Q));
break;
case 6:
printf("队尾元素为[%d]\n", QueueBack(&Q));
break;
case 7:
QueueDestroy(&Q); break;
case 8:QueueShow(&Q); break;
case 0:
printf("再见!\n"); quit = 0; break;
}
system("pause");
system("cls");
}
return 0;
}