栈与队列是两种重要的数据结构,有着广泛的应用,他们可以通过对链表功能加以限制改造而来。栈是一种先进后出(FILO)的数据结构,只能在一头进行加入删除,而队列是一种先进先出(FIFO)的数据结构,一头只能加入,另一头只能删除。
栈的实现:
# include <stdio.h> # include <malloc.h> # include <stdlib.h> typedef struct Node { int data; struct Node * pNext; }NODE, * PNODE; typedef struct Stack { PNODE pTop; PNODE pBottom; }STACK, * PSTACK; //函数声明 void init_stack(PSTACK); //创建一个空栈 void push_stack(PSTACK, int); //压栈 void traverse_stack(const PSTACK); //遍历输出 bool empty_stack(PSTACK); //判断栈是否为空 bool pop_stack(PSTACK, int *); //出栈 bool clear_stack(PSTACK); //将栈清空 int main(void) { STACK s; int val; init_stack(&s); push_stack(&s, 1); push_stack(&s, 2); push_stack(&s, 78); push_stack(&s, 499); push_stack(&s, 97); push_stack(&s, 134); traverse_stack(&s); pop_stack(&s, &val); /* if( pop_stack(&s, &val) ) //如果将if语句写在这里,if中的判断式已经执行过一次,即出栈一次,会造成bug。 { printf("出栈成功,出栈的元素值为:%d\n", val); } else { printf("出栈失败!\n"); } */ traverse_stack(&s); printf("清空栈!\n"); clear_stack(&s); traverse_stack(&s); return 0; } void init_stack(PSTACK pS) { pS->pTop = (PNODE)malloc(sizeof(NODE)); if (NULL == pS->pTop) { printf("内存分配失败!\n"); exit(-1); } else { pS->pBottom = pS->pTop; pS->pTop->pNext = NULL; } return; } void push_stack(PSTACK pS, int val) { PNODE pNew = (PNODE)malloc(sizeof(NODE)); if (NULL == pNew) { printf("压栈内存分配失败!\n"); return; } pNew->data = val; pNew->pNext = pS->pTop; pS->pTop = pNew; return; } void traverse_stack(const PSTACK pS) { PNODE p = pS->pTop; if ( empty_stack(pS) ) { printf("输出失败,栈为空!\n"); } else { printf("栈中的元素为:\n"); while (p != pS->pBottom) { printf("%d\t", p->data); p = p->pNext; } printf("\n"); } return; } bool empty_stack(PSTACK pS) { if(pS->pTop == pS->pBottom) return true; else return false; } bool pop_stack(PSTACK pS, int * pVal) { if ( empty_stack(pS) ) { printf("栈为空,出栈失败!\n"); return false; } else { PNODE p = pS->pTop; *pVal = p->data; pS->pTop = p->pNext; printf("出栈成功,出栈的元素值为:%d\n", p->data); free(p); p = NULL; return true; } } bool clear_stack(PSTACK pS) { if ( empty_stack(pS) ) { printf("栈为空,无法清空!\n"); return false; } else { PNODE p, q; p = pS->pTop; while (pS->pBottom != p) { q = p->pNext; free(p); p = q; } pS->pTop = pS->pBottom; } return true; }
循环队列
顺序队列有一个先天不足, 那就是空间利用率不高, 会产生”假溢出”现象,即:其实队列中还有空闲的空间以存储元素, 但我们在判断队列是否还有空间时, 队列告诉我们队列已经满了, 因此这种溢出并不是真正的溢出, 在data数组中依然存在可以放置元素的空位置, 所以说这是一种”假溢出”;
于是我们就引入了循环队列的概念, 将顺序队列臆造为一个环状的空间, 即把存储队列元素的表从逻辑上看成一个环, 称为循环队列,其示意图如下:
注意:如图中所示,我们的循环队列为了在实现上的便利, 会有一个位置的空闲, m_front(如图中的front)指针总会指向一个元素值为空的位置,因此(m_front+1)%capacity才真正的指向队首元素, 而m_rear(图中为rear)才指向一个真实存在的队尾元素;
循环队列的实现:
# include <stdio.h> # include <malloc.h> typedef struct Queue { int * pBase; int front; int rear; }QUEUE; void init(QUEUE *); //队列初始化 bool en_queue(QUEUE *, int); //入队 void traverse_queue(QUEUE *); //遍历队列 bool is_full(QUEUE *); //判断队列是否为满 bool is_empty(QUEUE *); //判断队列是否为空 bool out_queue(QUEUE *, int *); //出队 int main(void) { QUEUE Q; int val; init(&Q); en_queue(&Q, 1); en_queue(&Q, 2); en_queue(&Q, 3); en_queue(&Q, 4); en_queue(&Q, 5); en_queue(&Q, 6); en_queue(&Q, 7); en_queue(&Q, 8); traverse_queue(&Q); out_queue(&Q, &val); out_queue(&Q, &val); traverse_queue(&Q); return 0; } void init(QUEUE * pQ) { pQ->pBase = (int *)malloc(sizeof(int)*6); pQ->front = 0; pQ->rear = 0; } bool en_queue(QUEUE * pQ, int val) { if (is_full(pQ)) { printf("入队失败,队列已满!\n"); return false; } else { pQ->pBase[pQ->rear] = val; pQ->rear = (pQ->rear+1)%6; return true; } } bool is_full(QUEUE * pQ) { if ((pQ->rear+1)%6 == pQ->front) return true; else return false; } void traverse_queue(QUEUE *pQ) { int i = pQ->front; printf("队列元素为:\n"); while(i != pQ->rear) { printf("%d ", pQ->pBase[i]); i = (i+1)%6; } printf("\n"); } bool out_queue(QUEUE * pQ, int * pVal) { int val; if (is_empty(pQ)) { printf("出队失败,队列为空!\n"); return false; } else { *pVal = pQ->pBase[pQ->front]; val = pQ->pBase[pQ->front]; pQ->front = (pQ->front + 1) % 6; printf("出队成功,出队的元素是:%d\n", val); return true; } } bool is_empty(QUEUE * pQ) { if (pQ->front == pQ->rear) { return true; } else { return false; } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-29 01:56:37