1.栈
1.1栈的概念和结构
一种特殊的线性表,只允许在某一端插入或删除数据,这一端被称为栈顶,另一端称为栈底,
由于这种特征,所以栈具有先进后出的性质.
因为栈的操作只有入栈和出栈,都是都是在栈顶操作,并不需要挪动数据,所以采用顺序表结构比较合适
1.2栈的功能实现
1.2.1栈的结构定义
typedef int STData;
typedef struct Stack {
STData* _a;
size_t _top;//栈顶的下一个元素下标,也是栈里的元素数量
size_t _capacity;
}Stack;
1.2.2初始化栈
//初始化栈
void StackInit(Stack* ps) {
assert(ps);
ps->_capacity = 4;
ps->_a = (STData*)malloc(sizeof(STData) * ps->_capacity);
ps->_top = 0;
}
1.2.3销毁栈
//销毁栈
void StackDestroy(Stack* ps) {
assert(ps);
free(ps->_a);
ps->_a = NULL;
ps->_capacity = ps->_top = 0;
}
1.2.4入栈
//入栈
void StackPush(Stack* ps, STData x) {
assert(ps);
//如果栈满了需要增加容量
if (ps->_top == ps->_capacity) {
ps->_capacity *= 2;
STData* tmp = realloc(ps->_a, sizeof(STData) * ps->_capacity);
if (tmp == NULL) {
perror("realloc");
exit(-1);
}
ps->_a = tmp;
}
ps->_a[ps->_top] = x;
ps->_top++;
}
1.2.5出栈
//出栈
void StackPop(Stack* ps) {
assert(ps && ps->_top > 0);
ps->_top--;
}
1.2.6获取栈顶元素
//获取栈顶元素
STData StackTop(Stack* ps) {
assert(ps);
return ps->_a[ps->_top - 1];
}
1.2.7判断栈是否为空
//判断栈是否为空
bool StackEmpty(Stack* ps) {
assert(ps);
return ps->_top == 0;
}
1.2.8获取栈的长度
//获取栈的长度
size_t StackSize(Stack* ps) {
assert(ps);
return ps->_top;
}
1.3栈的实现代码
1.3.1Stack.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include<string.h>
typedef int STData;
typedef struct Stack {
STData* _a;
size_t _top;
size_t _capacity;
}Stack;
//初始化栈
void StackInit(Stack* ps);
//销毁栈
void StackDestroy(Stack* ps);
//入栈
void StackPush(Stack* ps, STData x);
//出栈
void StackPop(Stack* ps);
//获取栈顶元素
STData StackTop(Stack* ps);
//判断栈是否为空
bool StackEmpty(Stack* ps);
//获取栈的长度
size_t StackSize(Stack* ps);
1.3.2Stack.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"
//初始化栈
void StackInit(Stack* ps) {
assert(ps);
ps->_capacity = 4;
ps->_a = (STData*)malloc(sizeof(STData) * ps->_capacity);
ps->_top = 0;
}
//销毁栈
void StackDestroy(Stack* ps) {
assert(ps);
free(ps->_a);
ps->_a = NULL;
ps->_capacity = ps->_top = 0;
}
//入栈
void StackPush(Stack* ps, STData x) {
assert(ps);
if (ps->_top == ps->_capacity) {
ps->_capacity *= 2;
STData* tmp = realloc(ps->_a, sizeof(STData) * ps->_capacity);
if (tmp == NULL) {
perror("realloc");
exit(-1);
}
ps->_a = tmp;
}
ps->_a[ps->_top] = x;
ps->_top++;
}
//出栈
void StackPop(Stack* ps) {
assert(ps && ps->_top > 0);
ps->_top--;
}
//获取栈顶元素
STData StackTop(Stack* ps) {
assert(ps);
return ps->_a[ps->_top - 1];
}
//判断栈是否为空
bool StackEmpty(Stack* ps) {
assert(ps);
return ps->_top == 0;
}
//获取栈的长度
size_t StackSize(Stack* ps) {
assert(ps);
return ps->_top;
}
1.3.3Test.c
#include "Stack.h"
void TestStack() {
Stack s;
StackInit(&s);
StackPush(&s, 1);
StackPush(&s, 2);
StackPush(&s, 3);
StackPush(&s, 4);
StackPop(&s);
printf("%d\n", StackTop(&s));
printf("%d\n ", StackSize(&s));
StackDestroy(&s);
}
int main() {
TestStack();
return 0;
}
2.队列
2.1队列的概念和结构
队列也是一种也是的线性表结构,它只允许在一端插入数据,在另一端删除数据,插入元素的一端称为队尾,删除元素的一段称为队头,由于这种特性,它具有先进先出的特点。
由于队列需要在队头删除数据,如果用线性表结构删除数据时,需要将后面的数据往前挪,时间复杂度时O(N),而用链表只需要把头释放掉即可,所以链表更合适。
2.2队列的功能实现
2.2.1队列的结构定义
由于队列需要对头尾进行操作,一个队列保存队头和队尾指针。
typedef int QData;
typedef struct QueueNode {
QData _a;
struct QueueNode* _next;
}QueueNode;
typedef struct Queue {
QueueNode* _head;
QueueNode* _tail;
}Queue;
2.2.2初始化队列
//初始化队列
void QueueInit(Queue* pq) {
assert(pq);
pq->_head = pq->_tail = NULL;
}
2.2.3销毁队列
//销毁队列
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;
}
2.2.4入队
//入队
void QueuePush(Queue* pq, QData x) {
assert(pq);
QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));
node->_a = x;
node->_next = NULL;
//如果队列里没有数据
if (pq->_head == NULL) {
pq->_head = pq->_tail = node;
}
//如果队列里有数据
else {
pq->_tail->_next = node;
pq->_tail = node;
}
}
2.2.5出队
//出队
void QueuePop(Queue* pq) {
assert(pq);
//当队列为空时不能出队
assert(pq->_head != NULL);
//如果队列只有一个数据时
if (pq->_head->_next == NULL) {
free(pq->_tail);
pq->_head = pq->_tail = NULL;
}
//如果队列不只有一个数据时
else {
QueueNode* newHead = pq->_head->_next;
free(pq->_head);
pq->_head = newHead;
}
}
2.2.6获取队头
//获取队头
QData QueueFront(Queue* pq) {
assert(pq);
assert(pq->_head != NULL);
return pq->_head->_a;
}
2.2.7获取队尾
//获取队尾
QData QueueBack(Queue* pq) {
assert(pq);
assert(pq->_tail);
return pq->_tail->_a;
}
2.2.8判断队列是否为空
//判断队列是否为空
bool QueueEmpty(Queue* pq) {
assert(pq);
return pq->_head == NULL;
}
2.2.9获取队列长度
//获取队的长度
size_t QueueSize(Queue* pq) {
assert(pq);
size_t size = 0;
QueueNode* cur = pq->_head;
while (cur) {
size++;
cur = cur->_next;
}
return size;
}
2.3队列的实现代码
2.3.1Queue.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include<string.h>
typedef int QData;
typedef struct QueueNode {
QData _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, QData x);
//出队
void QueuePop(Queue* pq);
//获取队头
QData QueueFront(Queue* pq);
//获取队尾
QData QueueBack(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);
//获取队的长度
size_t QueueSize(Queue* pq);
2.3.2Queue.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Queue.h"
//初始化队列
void QueueInit(Queue* pq) {
assert(pq);
pq->_head = 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;
}
//入队
void QueuePush(Queue* pq, QData x) {
assert(pq);
QueueNode* node = (QueueNode*)malloc(sizeof(QueueNode));
node->_a = x;
node->_next = NULL;
if (pq->_head == NULL) {
pq->_head = pq->_tail = node;
}
else {
pq->_tail->_next = node;
pq->_tail = node;
}
}
//出队
void QueuePop(Queue* pq) {
assert(pq);
assert(pq->_head != NULL);
if (pq->_head->_next == NULL) {
free(pq->_tail);
pq->_head = pq->_tail = NULL;
}
else {
QueueNode* newHead = pq->_head->_next;
free(pq->_head);
pq->_head = newHead;
}
}
//获取队头
QData QueueFront(Queue* pq) {
assert(pq);
assert(pq->_head != NULL);
return pq->_head->_a;
}
//获取队尾
QData QueueBack(Queue* pq) {
assert(pq);
assert(pq->_tail);
return pq->_tail->_a;
}
//判断队列是否为空
bool QueueEmpty(Queue* pq) {
assert(pq);
return pq->_head == NULL;
}
//获取队的长度
size_t QueueSize(Queue* pq) {
assert(pq);
size_t size = 0;
QueueNode* cur = pq->_head;
while (cur) {
size++;
cur = cur->_next;
}
return size;
}
2.3.3Test.c
#include "Queue.h"
void TestQueue() {
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
QueuePop(&q);
printf("%d\n", QueueFront(&q));
printf("%d\n", QueueBack(&q));
printf("%d\n ", QueueSize(&q));
QueueDestroy(&q);
}
int main() {
TestQueue();
return 0;
}