数据结构学习记录DAY6 :栈和队列
栈和队列
内心OS:今天算是学的最轻松的一天了,有了之前的代码以及看了这么多天的“代码规范’总算是敲键盘翘起来轻松一点了,首先是我多少了解老师敲代码的顺序了,多少可以在老师开始之前做一点准备了。其次老师的命名方式我也大致了解了,这个对我来说是非常重要的一件事,因为我盲打的能力很差,所以命名看着键盘会让我轻松很多很多。终于不用在脑子和手之间做取舍拉!
今天的内容主要是两方面:栈和队列
首先讲的是栈:
栈的概念:从模型上来说,栈遵循先入后出FILO(first in last out)的原则,从操作上来说,只对栈顶元素进行操作
在使用上,栈的类型大致可分为以下两种
- 链式栈
- 顺序栈
从内存使用来分类,栈的类型有:
- 动态栈(链式
- 静态栈(顺序一般是
栈的实现
从学下来的角度说的话,代码太简单了,但是从记录的角度说的话,还是稍作copy吧
- 顺序静态栈
#define SUCCESS 0
#define FAILURE -1
typedef int ElemType
struct stack{
size_t size;//数量
size_t cap;//容量
Elemtype *elem;
}
typedef struct stack *ST;
//创建
ST create_stack();
//销毁
ST destroy_stack(ST list);
//容量及大小
size_t cap_stack(ST list);
size_t size_stack(ST list);
//判断空和满
bool empty_stack(ST list);
bool full_stack(ST list);
//向栈中压入元素
int push_stack(ST list, ElemType elem);
//弹出栈顶元素
int pop_stack(ST list, void* elem);
//查看栈顶元素
int peek_stack(ST list, ElemType *pelem);
//遍历栈
void foreach_stack(ST list, void (*foreach)(ElemType));
具体实现如下
ST create_stack(size_t cap)
{
ST list = (ST)malloc(sizeof(struct stack) + cap*sizeof(ElemType));
if(NULL != list)
{
list->cap = cap;
list->size = 0;
}
return list;
}
//销毁
int destroy_stack(ST list)
{
if(list != NULL)
free(list);
return SUCCESS;
}
//
size_t cap_stack(ST list)
{
assert(NULL != list);
return list->cap;
}
size_t size_stack(ST list)
{
assert(NULL != list);
return list->size;
}
//
bool empty_stack(ST list)
{
assert(NULL != list);
return list->size == 0;
}
bool full_stack(ST list)
{
assert(NULL != list);
return list->size == list->cap;
}
//向栈中压入元素
int push_stack(ST list, ElemType elem)
{
assert(NULL != list);
if(full_stack(list)){
return FAILURE;
}
list->elem[list->size++] = elem;
return SUCCESS;
}
int pop_stack(ST list, ElemType *elem)
{
assert(NULL != list);
if(empty_stack(list)){
return FAILURE;
}
list->size--;
if(elem != NULL)
*elem = list->elem[list->size];
return SUCCESS;
}
int peek_stack(ST list, ElemType *pelem)//查看栈顶元素
{
assert(NULL != list && NULL != pelem);
if(empty_stack(list)){
return FAILURE;
}
*pelem = list->elem[list->size-1];
return SUCCESS;
}
void foreach_stack(ST list, void (*foreach)(ElemType *pe))
{
assert(list != NULL && foreach != NULL);
int i;
for(i = 0; i < list->size; ++i){
foreach(&list->elem[i]);
}
}
链式栈:(逐渐变懒看看就好)
#define SUCCESS 0
#define FAILURE -1
struct _SNode{
struct _SNode *next;
char elem[];
};
#define _SNODESIZE sizeof(struct _SNode)
struct Stack{
size_t elemSize;
size_t size;
struct _SNode *top;
};
typedef struct Stack *ST;
ST create_link(size_t elemSize)
{
ST st = (ST)malloc(sizeof(struct Stack));
if(NULL != st)
{
st->elemSize = elemSize;
st->top = NULL;
st->size = 0;
}
return st;
}
//
size_t size_linkstack(ST st)
{
assert(NULL != st);
return st->size;
}
//
bool empty_linkstack(ST st)
{
assert(NULL != st);
return st->size == 0;
}
//向栈中压入元素
int push_linkstack(ST st, void *elem){
assert(NULL != st && elem != NULL);
struct _SNode *node = (struct _SNode *)malloc(_SNODESIZE + st->elemSize);
if(node == NULL)
{
return FAILURE;
}
node->next = st->top;
st->top = node;
memcpy(node->elem, elem, st->elemSize);
++st->size;
return SUCCESS;
}
int pop_linkstack(ST st, void *elem)
{
assert(NULL != st && elem != NULL);
if(empty_linkstack(st))
{
return FAILURE;
}
struct _SNode *node = st->top;
st->top = node->next;
if(elem != NULL)
{
memcpy(elem, node->elem, st->elemSize);
}
free(node);
--st->size;
return SUCCESS;
}
//销毁
int clear_linkstack(ST st)
{
assert(NULL != st);
while(!empty_linkstack(st))
{
pop_linkstack(st,NULL);
}
}
int destroy_linkstack(ST st)
{
assert(NULL != st);
clear_linkstack(st);
free(st);
}
int peek_linkstack(ST st, void *pelem)//查看栈顶元素
{
assert(NULL != st && pelem != NULL);
if(empty_linkstack(st))
{
return FAILURE;
}
memcpy(pelem, st->top->elem, st->elemSize);
return SUCCESS;
}
void foreach_linkstack(ST st, void (*foreach)(const void *p))
{
assert(NULL != st && foreach != NULL);
struct _SNode *node = st->top;
for(;node!=NULL;node=node->next){
foreach(&node->elem);
}
}
栈的应用
- 函数调用
- 函数调用即把函数入栈,每次执行的函数都是栈顶的函数,执行后出栈
- 走迷宫
- 算数表达式求解
- 前缀表达式: 运算符在操作数前面
- 中缀表达式:运算符在操作数中间(3 + 4)* (5+6*2)
- 后缀表达式:运算符在操作数后面 3 4 + 5 6 2 * + *
- 八皇后问题
- 回溯问题
- 拆解正整数
以上内容均未实现
队列
队列的概念:从模型上来说,队列遵循先入先出FIFO(first in first out)的原则。一般都是用食堂打饭来做类比的,从操作上来说,比较复杂。由于是在队尾添加元素而队首弹出元素,那么就需要保存队首和队尾。现实中,出队之后的填充操作很容易,但是在计算机里,如果让食堂窗口位置保持不动,那么当一个元素出队后,后面的元素需要被动的向前补,非常浪费时间,所以我们采用一个元素出队后,让窗口向前移动的方法,象形起来很恐怖,但是计算机里只是修改了队首的值,非常的快捷。
然后由于在定义时,头和尾都在同一位置,如果采用头加尾的双指示来做的话,当队满时必须在尾的后面空置一个单位的内存,否则就会出现头和尾重合的情况,这样的话就和空队的情况相同了。但是循环队列就可以解决这一个内存浪费的问题,实现如下
#define SUCCESS 0
#define FAILURE -1
typedef int ElemType;
struct Queue{
size_t cap;
size_t head;//队列头下标
size_t size;//(head+size-1)%cap 队尾
ElemType elems[];
};
QE create_queue(size_t cap)
{
QE queue = (QE)malloc(sizeof(struct Queue) + sizeof(ElemType)*cap);
if(queue != NULL)
{
queue->cap = cap;
queue->size = 0;
queue->head = 0;
}
return queue;
}
bool empty_queue(QE queue)
{
assert(NULL != queue);
return queue->head == queue->size;
}
bool full_queue(QE queue)
{
assert(NULL != queue);
return queue->size == queue->cap;
}
size_t cap_queue(QE queue)
{
assert(NULL != queue);
return queue->cap;
}
size_t size_queue(QE queue)
{
assert(NULL != queue);
return queue->size;
}
void destroy_queue(QE queue)
{
assert(NULL != queue);
free(queue);
}
int front_queue(QE queue, ElemType *elem)
{
assert(NULL != queue && elem != NULL);
if(empty_queue(queue))
{
return FAILURE;
}
*elem = queue->elems[queue->head];
return SUCCESS;
}
int push_queue(QE queue, ElemType elem)
{
assert(NULL != queue);
if(full_queue(queue))
{
return FAILURE;
}
queue->elems[(queue->size + queue->head) % queue->cap] = elem;
++queue->size;
return SUCCESS;
}
int pop_queue(QE queue, ElemType *elem)
{
assert(NULL != queue);
if(empty_queue(queue))
{
return FAILURE;
}
if(elem != NULL)
{
*elem = queue->elems[queue->head];
}
queue->head = (queue->head + 1)%queue->cap;
--queue->size;
return SUCCESS;
}
int back_queue(QE queue, ElemType *elem)
{
assert(NULL != queue && elem != NULL);
if(empty_queue(queue))
{
return FAILURE;
}
*elem = queue->elems[(queue->size + queue->head - 1) % queue->cap];
return SUCCESS;
}
void foreach_queue(QE queue, void (*foreach)(ElemType *pe))
{
assert(queue != NULL && foreach != NULL);
int i;
for(i = 0; i < queue->size; ++i){
foreach(&queue->elems[(queue->head + i) % queue->cap]);
}
}
#define SUCCESS 0
#define FAILURE -1
struct _Qnode
{
struct _Qnode *next;
char elems[];
};
#define _QNODESIZE sizeof(struct _Qnode)
struct Queue{
size_t elemSize;
struct _Qnode *head;//指向队首
struct _Qnode *tail;//指向队尾巴
size_t size;//(head+size-1)%cap 闃熷熬
};
QE create_queue(size_t elemsize)
{
QE queue = (QE)malloc(sizeof(struct Queue));
if(queue != NULL)
{
queue->elemSize = elemsize;
queue->head = NULL;
queue->tail = NULL;
queue->size = 0;
}
return queue;
}
bool empty_queue(QE queue)
{
assert(NULL != queue);
return queue->head == NULL;
}
bool full_queue(QE queue)
{
assert(NULL != queue);
return queue->tail == queue->head;
}
size_t size_queue(QE queue)
{
assert(NULL != queue);
return queue->size;
}
void clear_queue(QE queue)
{
assert(NULL != queue);
/*
while(empty_queue(queue))
{
pop_queue(queue);
}*/
struct _Qnode *node, *next;
for(node = queue->head; node != NULL; node = next)
{
next = node->next;
free(node);
}
queue->head = NULL;
queue->tail = NULL;
queue->size = 0;
}
void destroy_queue(QE queue)
{
assert(NULL != queue);
clear_queue(queue);
free(queue);
}
int front_queue(QE queue, void *elem)
{
assert(NULL != queue && elem != NULL);
if(empty_queue(queue))
{
return FAILURE;
}
memcpy(elem, queue->head->elems, queue->elemSize);
return SUCCESS;
}
int push_queue(QE queue, void *elem)
{
assert(NULL != queue && elem != NULL);
struct _Qnode *node = (struct _Qnode*)malloc(_QNODESIZE + queue->elemSize);
if(NULL == node)
{
return FAILURE;
}
node->next = NULL;
memcpy(node->elems, elem, queue->elemSize);
printf("88");
if(queue->tail != NULL)
{
queue->tail->next = node;
}
else
{
queue->head = node;
}
queue->tail = node;
++queue->size;
return SUCCESS;
}
int pop_queue(QE queue, void *elem)
{
assert(NULL != queue && elem != NULL);
if(empty_queue(queue))
{
return FAILURE;
}
struct _Qnode *node = queue->head;
if(NULL != elem)
{
memcpy(elem, node->elems, queue->elemSize);
}
queue->head = node->next;
if(node == queue->tail)
{
queue->tail = NULL;
}
free(node);
--queue->size;
return SUCCESS;
}
int back_queue(QE queue, void *elem)
{
assert(NULL != queue && elem != NULL);
if(empty_queue(queue))
{
return FAILURE;
}
memcpy(elem, queue->tail->elems, queue->elemSize);
return SUCCESS;
}
void foreach_queue(QE queue, void (*foreach)(const void *))
{
assert(NULL != queue && foreach != NULL);
struct _Qnode *node;
for(node = queue->head;node!=NULL;node=node->next){
foreach(node->elems);
}
}