1.栈的模拟实现
1.1变量和函数接口声明
#ifndef _STACK_H_
#define _STACK_H_
#include <windows.h>
#include <stdio.h>
#include <assert.h>
typedef int STDataType;
typedef struct Stack
{
STDataType *arr;
int _top;
int _capacite;
}stack;
void StackInit(stack *ps);//初始化
void StackDestory(stack *ps);//销毁
void StackPush(stack *ps,STDataType data);//入栈
STDataType StackTop(stack *ps);//获取栈顶元素
void StackPop(stack *ps);//出栈
int StackSize(stack *ps);//获取栈内元素个数
int StackEmpty(stack *ps);//判断是否为空
#endif
1.2初始化
栈的特性是先进后出,即在栈顶操作,因此我们可以利用顺序表进行实现,因为顺序表的尾插尾删的复杂度都为O(1);
void StackInit(stack *ps)//初始化
{
assert(ps);
STDataType *node = (STDataType*)malloc(sizeof(STDataType)* 2);
assert(node);
ps->arr = node;
ps->_top = 0;
ps->_capacite = 2;
}
1.3销毁
直接释放我们的顺序表,这是传1级指针的原因是为了保持接口的一致性,至于外部的野指针问题,我觉得既然调用了销毁接口就应该明白不能再次引用;
void StackDestory(stack *ps)//销毁
{
assert(ps);
free(ps->arr);
ps->arr = NULL;
ps->_top = ps->_capacite = 0;
}
1.4入栈
栈是由顺序表进行实现的,入栈很简单,直接在数组的尾端加入元素即可,只是需要判定下空间的容量是否足够;
void StackPush(stack *ps,STDataType data)//入栈
{
assert(ps);
if (ps->_top == ps->_capacite)
{
ps->_capacite *= 2;
ps->arr = (STDataType*)realloc(ps->arr, sizeof(STDataType)*ps->_capacite);
}
ps->arr[ps->_top++] = data;
}
1.5获取栈顶元素、出栈、获取栈内元素个数、判空
我们给定的栈的结构体中函数有顺序表的元素个数,因此实现这些结接口是非常方便的;
STDataType StackTop(stack *ps)//获取栈顶元素
{
assert(ps);
assert(ps->_top != 0);
return ps->arr[ps->_top-1];
}
void StackPop(stack *ps)//出栈
{
assert(ps);
assert(ps->_top != 0);
ps->_top--;
}
int StackSize(stack *ps)//获取栈内元素个数
{
assert(ps);
return ps->_top;
}
int StackEmpty(stack *ps)//判断是否为空
{
assert(ps);
if (ps->_top == 0)
return 1;
else
return 0;
}
2.队列的实现
2.1 变量和函数接口声明
#ifndef _QUEUE_H_
#define _QUEUE_H_
#include <stdio.h>
#include <windows.h>
#include <assert.h>
typedef BTNode* QDataType;
typedef struct QListNode
{
QDataType _data;
struct QListNode* _next;
}QNode;
typedef struct Queue
{
QNode *_front;
QNode *_rear;
}Queue;
void QueueInit(Queue *q);//初始化
void QueueDestory(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);//判断是否为空
#endif
2.2初始化
队列的性质是先进先出,因此我们用给定尾指针的单向链表来实现。因为数组的头插和头删的时间复杂度都为O(1),相对来说用链表来实现更佳;
初始化时,头尾指针都指向NULL,此时的队列为空
void QueueInit(Queue *q)//初始化
{
assert(q);
q->_front = q->_rear = NULL;
}
2.3销毁
由于队列是链表结构,因此我们需要利用循环对其进行销毁,销毁后尾指针的位置需要进行更新;
void QueueDestory(Queue *q)//销毁
{
assert(q);
QNode *cur = q->_front;
QNode *next = NULL;
while (cur)
{
next = cur->_next;
free(cur);
cur = next;
}
q->_front = q->_rear = NULL;
}
2.4入队
入队即在链表的位段链接一个节点,此时需要判定下当前队列的头尾指针是否都指向空;
void QueuePush(Queue *q, QDataType data)//入队
{
QNode *node = (QNode*)malloc(sizeof(QNode));
assert(node);
node->_data = data;
node->_next = NULL;
if (q->_front == NULL)//第一个
{
q->_front = q->_rear = node;
}
else
{
q->_rear->_next = node;
q->_rear = node;
}
}
2.5出队
出队即通过操作头指针向后一个节点进行移动,释放前面一个节点,如果全部释放完了,尾指针需要置空;
void QueuePop(Queue *q)//出队
{
assert(q);
assert(q->_front);
QNode *next = q->_front->_next;
free(q->_front);
q->_front = next;
if (q->_front == NULL)
q->_rear = NULL;//队为空
}
2.6获取队首队尾元素
判空后直接通过首尾指针进行获取;
QDataType QueueFront(Queue *q)//获取队首元素
{
assert(q);
assert(q->_front);
return q->_front->_data;
}
QDataType QueueBack(Queue *q)//获取队尾元素
{
assert(q);
assert(q->_rear);
return q->_rear->_data;
}
2.7获取元素的个数
给一个计数器变量,通过循环的方式获取节点的个数;
int QueueSize(Queue *q)//获取元素个数
{
assert(q);
QNode *cur = q->_front;
int size = 0;
while (cur)
{
cur = cur->_next;
size++;
}
return size;
}
2.8判断是否为空
判断是否为空,即头指针是否指向NULL;
int QueueEmpty(Queue *q)//判断是否为空
{
assert(q);
if (q->_front == NULL)
return 1;
else
return 0;
}