栈
1 定义
一种特殊的线性表,只允许固定的一端插入或删除元素,这一端称为栈顶,另一端是栈底。栈中的数据元素遵守后进先出原则。
2 栈的实现
使用数组和链式结构实现都可以
(1)数组栈:
数据表尾插尾删效率高
(2)链式栈:
①尾作为栈顶,尾插尾删,单向链表效率低,双向链表适用
②头作为栈顶,头插头删,单向链表也适用
3 实现代码
// Stack.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int STDataType;
typedef struct Stack {
STDataType *a;
int top;
int capacity;
}ST;
// 初始化栈
void StackInit(ST* ps);
// 销毁栈
void StackDestroy(ST* ps);
// 入栈
void StackPush(ST* ps, STDataType x);
// 出栈
void StackPop(ST* ps);
// 返回栈顶元素
STDataType StackTop(ST* ps);
// 判断栈是否为空
bool StackEmpty(ST* ps);
// 查询栈数据个数
int StackSize(ST* ps);
// Stack.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"
//typedef int STDataType;
//typedef struct Stack {
// STDataType* a;
// int top;
// int capacity;
//}ST;
// 初始化栈
void StackInit(ST* ps) {
assert(ps);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
// 销毁栈
void StackDestroy(ST* ps) {
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
// 入栈
void StackPush(ST* ps, STDataType x) {
assert(ps);
if (ps->capacity == ps->top) {
int newcapa = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* tmp = realloc(ps->a, sizeof(STDataType) * newcapa);
if (tmp == NULL) {
printf("realloc fail\n");
exit(-1);
}
ps->a = tmp;
ps->capacity = newcapa;
}
ps->a[ps->top] = x;
ps->top++;
}
// 出栈
void StackPop(ST* ps) {
assert(ps);
assert(ps->top > 0);
ps->top--;
}
// 返回栈顶元素
STDataType StackTop(ST* ps) {
assert(ps);
assert(!StackEmpty(ps));
return ps->a[ps->top - 1];
}
// 判断栈是否为空
bool StackEmpty(ST* ps) {
assert(ps);
return ps->top == 0;
}
// 查询栈数据个数
int StackSize(ST* ps) {
assert(ps);
return ps->top;
}
// Test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"
void TestStack1()
{
ST st;
StackInit(&st);
StackPush(&st, 1);
StackPush(&st, 2);
StackPush(&st, 3);
StackPush(&st, 4);
StackPop(&st);
StackPop(&st);
StackPop(&st);
//StackPop(&st);
//StackPop(&st);
printf("%d", StackTop(&st));
StackDestroy(&st);
}
void TestStack2()
{
ST st;
StackInit(&st);
StackPush(&st, 1);
StackPush(&st, 2);
StackPush(&st, 3);
StackPush(&st, 4);
printf("%d ", StackTop(&st));
StackPop(&st);
printf("%d ", StackTop(&st));
StackPop(&st);
StackPush(&st, 5);
StackPush(&st, 6);
while (!StackEmpty(&st))
{
printf("%d ", StackTop(&st));
StackPop(&st);
}
StackDestroy(&st);
}
int main()
{
TestStack1();
printf("\n");
TestStack2();
return 0;
}
4 运行结果
队列
1 定义
只允许在一端进行插入数据操作(入队列),在另一端进行删除数据操作(出队列)的特殊线性表,进行插入操作的一端称为队尾,进行删除操作的一端称为队头。队列中的数据遵守先进先出原则。
2 队列的实现
使用链式结构实现效率较高
(1)数组队列
入队列或出队列一项在数组尾进行,则另一项操作在数组头进行,一定要移动数组所有数据,时间复杂度为O(n2)
(2)链式队列
头插尾删或头删尾插,时间复杂度为O(n)
增加一个尾指针,时间复杂度O(1)
3 实现代码
// Queue.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int QDataType;
typedef struct QueueNode {
QDataType a;
struct QueueNode* next;
}QueueNode;
typedef struct Queue {
QueueNode* head;
QueueNode* tail;
}Queue;
// 初始化
void QueueInit(Queue* pq);
// 销毁
void QueueDestroy(Queue* pq);
// 入队列
void QueuePush(Queue* pq, QDataType x);
// 出队列
void QueuePop(Queue* pq);
// 查询队头
QDataType QueueFront(Queue* pq);
// 查询队尾
QDataType QueueBack(Queue* pq);
// 队列数据个数
int QueueSize(Queue* pq);
// 判空
bool QueueEmpty(Queue* pq);
// Queue.c
#include "Queue.h"
//typedef int QDataType;
//typedef struct QueueNode {
// QDataType a;
// QueueNode* next;
//}QueueNode;
//
//typedef struct Queue {
// QueueNode* head;
// QueueNode* tail;
//}Queue;
// 初始化
void QueueInit(Queue* pq) {
assert(pq);
pq->head = NULL;// 队头,删除
pq->tail = NULL;// 队尾,插入
}
// 销毁
void QueueDestroy(Queue* pq) {
assert(pq);
QueueNode* cur = pq->head;
while (cur) {
QueueNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
//free(pq->head);
//free(pq->tail);
}
// 入队列
void QueuePush(Queue* pq, QDataType x) {
assert(pq);
QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));
if (newNode) {
newNode->a = x;
newNode->next = NULL;
// 插入分空链和非空
if (!pq->head) {
pq->head = pq->tail = newNode;
}
else {
//newNode->next = pq->head;
//pq->head = newNode;
pq->tail->next = newNode;
pq->tail = newNode;
}
}
}
// 出队列
void QueuePop(Queue* pq) {
assert(pq);
assert(!QueueEmpty(pq));
QueueNode* next = pq->head->next;
free(pq->head);
pq->head = next;
if (pq->head == NULL)
{
pq->tail = NULL;
}
}
// 查询队头
QDataType QueueFront(Queue* pq) {
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->a;
}
// 查询队尾
QDataType QueueBack(Queue* pq) {
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->a;
}
// 队列数据个数
int QueueSize(Queue* pq) {
assert(pq);
QueueNode* node = pq->head;
int n = 0;
while (node) {
node = node->next;
n++;
}
return n;
}
// 判空
bool QueueEmpty(Queue* pq) {
assert(pq);
return pq->head == NULL;
}
// Test.c
#include "Queue.h"
void QueueTest1() {
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
printf("队头:%d\n", QueueFront(&q));
printf("队尾:%d\n", QueueBack(&q));
printf("队列长度:%d\n", QueueSize(&q));
QueuePop(&q);
printf("队头:%d\n", QueueFront(&q));
printf("队尾:%d\n", QueueBack(&q));
printf("队列长度:%d\n", QueueSize(&q));
QueuePop(&q);
QueuePop(&q);
printf("队列长度:%d\n", QueueSize(&q));
QueueDestroy(&q);
}
void QueueTest2() {
Queue q;
QueueInit(&q);
QueuePush(&q, 4);
QueuePush(&q, 5);
QueuePush(&q, 6);
printf("队头:%d\n", QueueFront(&q));
printf("队尾:%d\n", QueueBack(&q));
printf("队列长度:%d\n", QueueSize(&q));
while (!QueueEmpty(&q)) {
printf("%d\n", QueueFront(&q));
QueuePop(&q);
}
QueueDestroy(&q);
}
int main() {
QueueTest1();
printf("\n");
QueueTest2();
return 0;
}