目录
1.栈
1.1栈的概念及结构
1.2栈的实现
1.2.1具体实现
Stack.h
栈初始化
栈销毁
入栈
出栈
取栈顶数据
判空
栈中有效元素的个数
全部Stack.c的代码
测试Test.c代码
2.队列
2.1队列的概念及结构
2.2队列的实现
Queue.h
队列初始化
队列销毁
队尾入队列(尾插)
队头出队列(头删 )
获取队头元素
获取队尾元素
判空
获取队列有效元素个数
完整的Queue.c代码
测试代码Test.c
1.栈
1.1栈的概念及结构
栈:一种特殊的线性表,它只允许在固定的一端(栈顶
1.2
栈的实现
栈的实现一般可以使用
数组或者链表实现
,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的
代价比较小。
)进行插入和删除元素的操作。进行插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵循后进先出(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈
,入数据在栈顶。
出栈:栈的删除操作叫做出栈。
出数据也在栈顶。
1.2栈的实现
栈的实现一般可以使用
数组或者链表实现
,
相对而言
数组的结构实现更优一些
。因为数组在尾上插
入数据的代价比较小。
1.2.1具体实现
Stack.h
从如下的几个方面实现栈的功能,看代码。
#pragma once
#include <stdbool.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int STDatatype;
typedef struct Stack//栈
{
STDatatype* a;
int capacity;
int top; // 初始为0,表示栈顶位置下一个位置的下标
}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);
栈初始化
void StackInit(ST* ps)
{
assert(ps);
//方法1
//ps->a = NULL;
//ps->top = 0;
//ps->capacity = 0;
//方法2
ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
if (ps->a == NULL)
{
perror("malloc fail");
exit(-1);
}
ps->top = 0;
ps->capacity = 4;
}
栈销毁
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->top == ps->capacity)
{
STDatatype* tmp = (STDatatype*)realloc(ps->a, ps->capacity * 2 * sizeof(STDatatype));
if (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}
ps->a = tmp;
ps->capacity *= 2;
}
//先放数据,top再++
ps->a[ps->top] = x;
ps->top++;
}
出栈
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
取栈顶数据
STDatatype StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->a[ps->top - 1];
}
判空
bool StackEmpty(ST* ps)
{
assert(ps);
/*if (ps->top == 0)
{
return true;
}
else
{
return false;
}*/
return ps->top == 0;
}
栈中有效元素的个数
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
全部Stack.c的代码
void StackInit(ST* ps)
{
assert(ps);
//ps->a = NULL;
//ps->top = 0;
//ps->capacity = 0;
ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
if (ps->a == NULL)
{
perror("malloc fail");
exit(-1);
}
ps->top = 0;
ps->capacity = 4;
}
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->top == ps->capacity)
{
STDatatype* tmp = (STDatatype*)realloc(ps->a, ps->capacity * 2 * sizeof(STDatatype));
if (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}
ps->a = tmp;
ps->capacity *= 2;
}
//先放数据,top再++
ps->a[ps->top] = x;
ps->top++;
}
//
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
STDatatype StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->a[ps->top - 1];
}
bool StackEmpty(ST* ps)
{
assert(ps);
/*if (ps->top == 0)
{
return true;
}
else
{
return false;
}*/
return ps->top == 0;
}
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
测试Test.c代码
#include "Stack.h"
void TestStack1()
{
ST st;
StackInit(&st);
StackPush(&st, 1);
StackPush(&st, 2);
StackPush(&st, 3);
StackPush(&st, 4);
StackPush(&st, 5);
printf("size:%d\n", StackSize(&st)); // 不关心底层实现
//printf("size:%d\n", st.top); // 关心
printf("size:%d\n", st.top + 1); // 关心
StackPop(&st);
StackPop(&st);
StackPop(&st);
StackPop(&st);
StackPop(&st);
//StackPop(&st);
//printf("%d\n", StackTop(&st));
StackDestroy(&st);
}
int main()
{
TestStack1();
return 0;
}
2.队列
2.1队列的概念及结构
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。
队列具有先进先出 FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
PS:队列和栈几乎是相反的。
2.2队列的实现
实现队列更适合选择用单链表,而不是用数组,数组不适合头插尾插,效率低。
Queue.h
#pragma once
#include <stdbool.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int QDataType;
//链式结构:表示队列
typedef struct QueueNode
{
QDataType data;
struct QueueNode* next;
}QNode;
//队列的结构
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}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);
//判空
bool QueueEmpty(Queue* pq);
//获取队列有效元素个数
int QueueSize(Queue* pq);
队列初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
pq->size = 0;
}
队列销毁
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* del = cur;
cur = cur->next;
free(del);
//del = NULL;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
队尾入队列(尾插)
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
if (pq->tail == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
pq->size++;
}
队头出队列(头删 )
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* del = pq->head;
pq->head = pq->head->next;
free(del);
}
pq->size--;
}
获取队头元素
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
获取队尾元素
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
判空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL && pq->tail == NULL;
}
获取队列有效元素个数
int QueueSize(Queue* pq)
{
assert(pq);
//方法1
/*int size = 0;
QNode* cur = pq->head;
while (cur)
{
cur = cur->next;
++size;
}
return size;*/
//方法2
return pq->size;
}
完整的Queue.c代码
#include "Queue.h"
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = NULL;
pq->tail = NULL;
pq->size = 0;
}
void QueueDestroy(Queue* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* del = cur;
cur = cur->next;
free(del);
//del = NULL;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
if (pq->tail == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
pq->size++;
}
void QueuePop(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* del = pq->head;
pq->head = pq->head->next;
free(del);
}
pq->size--;
}
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->head == NULL && pq->tail == NULL;
}
// 1G = 1024MB
// 1024MB = 1024*1024KB
// 1024*1024KB = 1024*1024*1024Byte
int QueueSize(Queue* pq)
{
assert(pq);
//方法1
/*int size = 0;
QNode* cur = pq->head;
while (cur)
{
cur = cur->next;
++size;
}
return size;*/
//方法2
return pq->size;
}
测试代码Test.c
#include "Queue.h"
void TestQueue()
{
//Queue q1;
//Queue q2;
//QueueInit(&q1);
//QueueInit(&q2);
//QueueDestroy(&q1);
//QueueDestroy(&q2);
Queue q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
printf("%d ", QueueFront(&q));
QueuePop(&q);
QueuePush(&q, 3);
QueuePush(&q, 4);
printf("%d\n", QueueSize(&q));
printf("%d\n", QueueEmpty(&q));
printf("%d\n", QueueFront(&q));
printf("%d\n", QueueBack(&q));
while (!QueueEmpty(&q))
{
printf("%d ", QueueFront(&q));
QueuePop(&q);
}
printf("\n");
printf("%d\n", QueueSize(&q));
printf("%d\n", QueueEmpty(&q));
//printf("%d\n", QueueFront(&q));
//printf("%d\n", QueueBack(&q));
QueueDestroy(&q);
}
int main()
{
//TestStack1();
TestQueue();
return 0;
}