一,栈
1、栈的定义
栈(Stack):是只允许在一端进行插入或删除的线性表。首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作。
栈顶(Top):线性表允许进行插入删除的那一端。
栈底(Bottom):固定的,不允许进行插入和删除的另一端。
空栈:不含任何元素的空表。
栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构
2、栈的常见基本操作
InitStack(&S):初始化一个空栈S。
StackEmpty(S):判断一个栈是否为空,若栈为空则返回true,否则返回false。
Push(&S, x):进栈(栈的插入操作),若栈S未满,则将x加入使之成为新栈顶。
Pop(&S, &x):出栈(栈的删除操作),若栈S非空,则弹出栈顶元素,并用x返回。
GetTop(S, &x):读栈顶元素,若栈S非空,则用x返回栈顶元素。
DestroyStack(&S):栈销毁,并释放S占用的存储空间(“&”表示引用调用)
3.代码
1.stack.h
#ifndef __STACK_H__
#define __STACK_H__
typedef int DataType;
typedef struct snode
{
DataType data;
struct snode *pnext;
}SNode_t;
typedef struct stack
{
SNode_t *ptop;
int clen;
}Stack_t;
extern Stack_t *create_stack();
extern int push_stack(Stack_t *, DataType );
extern int pop_stack(Stack_t *, DataType *);
extern int get_stack_top(Stack_t *, DataType *);
extern void clear_stack(Stack_t *);
extern void destroy_stack(Stack_t *);
extern int is_empty_stack(Stack_t *);
extern void stack_for_each(Stack_t *pstack);
#endif
2.stakck.c
#include "stack.h"
#include <stdio.h>
#include <stdlib.h>
Stack_t *create_stack()
{
Stack_t *pstack = malloc(sizeof(Stack_t));
if(NULL == pstack)
{
perror("fail malloc");
return NULL;
}
pstack->ptop = NULL;
pstack->clen = 0;
return pstack;
}
int push_stack(Stack_t *pstack, DataType data)
{
SNode_t *pnode = malloc(sizeof(SNode_t));
if (NULL == pnode)
{
perror("fail malloc");
return -1;
}
pnode->data = data;
pnode->pnext = NULL;
pnode->pnext = pstack->ptop;
pstack->ptop = pnode;
pstack->clen++;
return 0;
}
void stack_for_each(Stack_t *pstack)
{
SNode_t *p = pstack->ptop;
while (p)
{
printf("%d ", p->data);
p = p->pnext;
}
printf("\n");
}
int is_empty_stack(Stack_t *pstack)
{
return NULL == pstack->ptop;
}
int pop_stack(Stack_t *pstack, DataType *pdata)
{
if (is_empty_stack(pstack))
return 0;
SNode_t *pdel = pstack->ptop;
pstack->ptop = pdel->pnext;
if (pdata != NULL)
{
*pdata = pdel->data;
}
free(pdel);
pstack->clen--;
return 1;
}
int get_stack_top(Stack_t *pstack, DataType *pdata)
{
if (is_empty_stack(pstack))
return 0;
if (pdata != NULL)
{
*pdata = pstack->ptop->data;
return 1;
}
return 0;
}
void clear_stack(Stack_t *pstack)
{
while (!is_empty_stack(pstack))
{
pop_stack(pstack, NULL);
}
}
void destroy_stack(Stack_t *pstack)
{
clear_stack(pstack);
free(pstack);
}
3.主函数调用
#include "stack.h"
#include <stdio.h>
int main(int argc, const char *argv[])
{
DataType data;
Stack_t *pstack = create_stack();
if (NULL == pstack)
{
return -1;
}
push_stack(pstack, 1);
push_stack(pstack, 2);
push_stack(pstack, 3);
push_stack(pstack, 4);
stack_for_each(pstack);
pop_stack(pstack, &data);
printf("data = %d\n", data);
stack_for_each(pstack);
get_stack_top(pstack, &data);
printf("top = %d\n", data);
destroy_stack(pstack);
return 0;
}
二,队列
1、队列的定义
队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
队列是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头。
队头(Front):允许删除的一端,又称队首。
队尾(Rear):允许插入的一端。
空队列:不包含任何元素的空表。
假性溢出:
如图d,队列出现“上溢出”,然而却又不是真正的溢出,所以是一种“假溢出”。
2、队列的常见基本操作
InitQueue(&Q):初始化队列,构造一个空队列Q。
QueueEmpty(Q):判队列空,若队列Q为空返回true,否则返回false。
EnQueue(&Q, x):入队,若队列Q未满,将x加入,使之成为新的队尾。
DeQueue(&Q, &x):出队,若队列Q非空,删除队头元素,并用x返回。
GetHead(Q, &x):读队头元素,若队列Q非空,则将队头元素赋值给x
3、链队列
队列的链式存储结构表示为链队列,它实际上是一个同时带有队头指针和队尾指针的单链表,只不过它只能尾进头出而已。
空队列时,front和real都指向头结点。
3.代码
1.queue.h
#ifndef __QUEUE_H__
#define __QUEUE_H__
#include <pthread.h>
typedef int QDataType;
typedef struct qnode
{
QDataType data;
struct qnode *pnext;
}QNode_t;
typedef struct queue
{
QNode_t *pfront;
QNode_t *prear;
int clen;
pthread_mutex_t mutex;
}Queue_t;
Queue_t *create_queue();
int is_empty_queue(Queue_t *);
int push_queue(Queue_t *, QDataType );
int pop_queue(Queue_t *, QDataType *);
int get_queue_front(Queue_t *, QDataType *);
void clear_queue(Queue_t *);
void destroy_queue(Queue_t *);
extern void queue_for_each(Queue_t *pque);
#endif
2.queue.c
#include "queue.h"
#include <stdlib.h>
#include <stdio.h>
Queue_t *create_queue()
{
Queue_t *pque = malloc(sizeof(Queue_t));
if (NULL == pque)
{
perror("fail malloc");
return NULL;
}
pque->pfront = NULL;
pque->prear = NULL;
pque->clen = 0;
pthread_mutex_init(&(pque->mutex), NULL);
return pque;
}
int is_empty_queue(Queue_t *pque)
{
return NULL == pque->pfront;
}
int push_queue(Queue_t *pque, QDataType data)
{
QNode_t *pnode = malloc(sizeof(QNode_t));
if (NULL == pnode)
{
perror("fail malloc");
return -1;
}
pnode->data = data;
pnode->pnext = NULL;
if (is_empty_queue(pque))
{
pque->pfront = pnode;
pque->prear = pnode;
}
else
{
pque->prear->pnext = pnode;
pque->prear = pnode;
}
pque->clen++;
return 0;
}
void queue_for_each(Queue_t *pque)
{
QNode_t *p = pque->pfront;
while (p != NULL)
{
printf("%d ", p->data);
p = p->pnext;
}
printf("\n");
}
int pop_queue(Queue_t *pque, QDataType *pdata)
{
if (is_empty_queue(pque))
return 0;
QNode_t *pdel = pque->pfront;
pque->pfront = pdel->pnext;
if (pdata != NULL)
{
*pdata = pdel->data;
}
free(pdel);
if (NULL == pque->pfront)
{
pque->prear = NULL;
}
pque->clen--;
return 1;
}
int get_queue_front(Queue_t *pque, QDataType *pdata)
{
if (is_empty_queue(pque))
return 0;
if (NULL == pdata)
return 0;
*pdata = pque->pfront->data;
return 1;
}
void clear_queue(Queue_t *pque)
{
while (!is_empty_queue(pque))
{
pop_queue(pque, NULL);
}
}
void destroy_queue(Queue_t *pque)
{
clear_queue(pque);
free(pque);
}
3.主函数调用
#include "queue.h"
#include <stdio.h>
int main(int argc, const char *argv[])
{
QDataType data;
Queue_t *pque = create_queue();
if (NULL == pque)
{
return -1;
}
push_queue(pque, 1);
push_queue(pque, 2);
push_queue(pque, 3);
push_queue(pque, 4);
queue_for_each(pque);
pop_queue(pque, &data);
queue_for_each(pque);
int ret = get_queue_front(pque, &data);
if (ret != 0)
{
printf("front: %d\n", data);
}
destroy_queue(pque);
return 0;
}