目录
一,结构
1.栈结构
typedef char DataType;
typedef struct StackNode
{
DataType* data;
size_t top; //记录栈顶的后一个位置,如果初始化位0的话。
size_t capacity; //记录栈的容量。
}ST;
这里的数据类型可以动过改变typedef 中的char 来进行改变。
2.队列结构
//选择用单链表结构来实现队列
typedef int QDataType;
typedef struct QueueNode
{
QDataType data;
struct QueueNode* next;
}QueueNode;
//队列结构,在队列尾插入,在队列头部删除。头->->->->=NULL; 实现先插入,先取出。先进先出的特性。
typedef struct Queue
{
QueueNode* tail;
QueueNode* head;
//size_t size; 如果要实现size接口不想遍历O(N)的话,可以在加一个参数。
}Queue;
二,函数接口
栈的队列的接口其实时差不多的,大差不差的。
1.栈的函数接口
void StackInit(ST* ps); //初始化
void StackDestory(ST* ps); //销毁
void StackPush(ST* ps, DataType x); //插入数据
void StackPop(ST* ps); //删除数据
bool StackEmpty(ST* ps); //判断栈是否为空
int StackSize(ST* ps); //返回队列中数据个数
DataType StackTop (ST* ps); //返回栈顶数据
2.队列的函数接口
//想改变这个结构体,那就要传结构体的指针。
void QueueInit(Queue* pq); //初始化队列
void QueueDestory(Queue* pq); //销毁队列
void QueuePush(Queue* pq, QDataType x); //插入数据
void QueuePop(Queue* pq); //删除数据
bool QueueEmpty(Queue* pq); //判空
size_t QueueSize(Queue* pq); //返回队列中元素个数
QDataType QueueFront(Queue* pq); //取队头数据
QDataType QueueBack(Queue* pq); //取队尾数据
三,函数接口的实现
1.栈的接口实现
(1) 初始化
void StackInit(ST* ps)
{
assert(ps);
ps->capacity = 0;
ps->top = 0; //这里初始化位0.那么yop代表栈顶元素的下一个位置。
ps->data = NULL;
}
(2)销毁
void StackDestory(ST* ps)
{
assert(ps);
free(ps->data);
ps->capacity = 0;
ps->top = 0;
ps->data = NULL;
}
(3)插入数据
void StackPush(ST* ps, DataType x)
{
assert(ps);
if (ps->capacity == ps->top)
{
//需要扩容:
size_t newlen = ps->capacity == 0 ? 4 : ps->capacity * 2;
DataType* tmp = (DataType*)realloc(ps->data,sizeof(DataType) * newlen);
//if (ps->data == NULL)
//{
// printf("malloc fail\n");
// exit(-1);
//}
//走到这里那就是开空间成功了。
if(tmp==NULL)
{
}
else
{
ps->data = tmp;
ps->capacity = newlen;
}
}
ps->data[ps->top++] = x;
}
(4)删除数据
void StackPop(ST* ps)
{
assert(ps);
--ps->top;
}
(5)判空
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
(6)返回栈元素个数
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
(7)返回栈顶数据
DataType StackTop(ST* ps)
{
assert(ps);
//assert(ps->top > 0); t多余,我们这里用的是size_t
return ps->data[ps->top - 1];
}
2.队列的接口实现
(1)初始化队列
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
}
(2)销毁队列
void QueueDestory(Queue* pq)
{
assert(pq);
QueueNode* head = pq->head;
while (head)
{
QueueNode* next = head->next;
free(head);
head = next;
}
//释放完一点要记得置NULL;
pq->head = pq->tail = NULL;
}
(3)插入数据
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
if (newnode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
if (pq->tail == NULL)
{
assert(pq->head == NULL);
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
//链接起来之后,一点不要忘记更新尾。
pq->tail = newnode;
}
//这俩句放到前面更好一点,不容易忘记。
newnode->data = x;
newnode->next = NULL;
}
(4)删除数据
void QueuePop(Queue* pq)
{
//实现头删就ok了
assert(pq);
assert(pq->head && pq->tail);
//考虑的不完善哦。 因为这里如果只有一个的话,删除完之后,tail没有被置NULL,再次插入就会发生野指针的问题。
//QueueNode* next = pq->head->next;
//free(pq->head);
//pq->head = next;
if (pq->head->next == NULL)
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QueueNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
}
(5)判空
bool QueueEmpty(Queue* pq)
{
assert(pq);
//return pq->head == NULL && pq->head == NULL; 没必要。
return pq->tail == NULL;
}
(6)返回队列元素个数
size_t QueueSize(Queue* pq)
{
assert(pq);
QueueNode* cur = pq->head;
size_t n = 0;
while (cur)
{
n++;
cur = cur->next;
}
return n;
}
(7)返回队头数据
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(pq->head);
return pq->head->data;
}
(8)返回队尾数据
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(pq->tail);
return pq->tail->data;
}