1 栈的两种物理结构实现
堆栈基本特征: 先进后出,后进先出(类似垃圾箱)
栈顶指针用来记录最后进入数据的位置。
1.1 栈的顺序结构实现
/*栈练习,顺序存储结构实现*/
#include<stdio.h>
#include<stdbool.h>
int stack[10];
int size;//表示栈中有效数据个数
//判断是否为空
bool is_empty(){
return !size;
}
//判断是否为满
bool is_full(){
return size == 10;
}
//初始化
void init(){
}
//销毁
void destroy(){
size = 0;
}
//加入数据(压入)
void push(int num){
stack[size] = num;
size++;
}
//拿出数据(弹出)
void pop(){
size--;
}
//获取数据
int peak(){
return stack[size - 1];
}
int main(){
push(1);
push(2);
push(3);
printf("%-3d",peak());
pop();
printf("%-3d",peak());
pop();
push(4);
printf("%-3d",peak());
pop();
printf("%-3d",peak());
pop();
printf(is_empty()?"空\n":"非空\n");
return 0;
}
1.2 栈的链式结构实现
/*栈练习,链式存储结构实现*/
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
typedef struct node{
int num;
struct node *p_next;
}node;
void pop();
node head;//头结点
//判断是否为空
bool is_empty(){
return !head.p_next;
}
//判断是否为满
bool is_full(){
return false;
}
//初始化
void init(){
}
//销毁
void destroy(){
while (head.p_next){
pop();
}
}
//加入数据(压入)
void push(int num){
node *p_node = (node *)malloc(sizeof(node));
if (!p_node){
return;
}
p_node->num = num;
p_node->p_next = head.p_next;
head.p_next = p_node;
}
//拿出数据(弹出)
void pop(){
if (head.p_next){
node *p_tmp = head.p_next;
head.p_next = p_tmp->p_next;
free(p_tmp);
p_tmp = NULL;
}
}
//获取数据
int peak(){
if (head.p_next){
return head.p_next->num;
}
else {
return -1;
}
}
int main(){
push(1);
push(2);
push(3);
printf("%d ",peak());
pop();
printf("%d ",peak());
pop();
push(4);
printf("%d ",peak());
pop();
printf("%d ",peak());
pop();
printf(is_empty()?"空\n":"非空\n");
destroy();//必须释放内存,否则就会造成内存泄漏
return 0;
}
2 队列的两种物理结构实现
队列的基本特征:先进先出(FIFO)。
所有数据有两个端点,一端输入数字另一端输出数字。
2.1 队列的顺序结构实现
/*顺序结构实现队列*/
#include<stdio.h>
#include<stdbool.h>
int queue[10];
int head,tail;//head记录下一个要拿的数据的下标,tail记录下一个要放的数据的下标
bool is_empty(){
return head == tail;
}
bool is_full(){
return tail > 9;
}
void init(){
head = 0;
tail = 0;
}
void destroy(){
head = 0;
tail = 0;
}
void push(int num){
queue[tail] = num;
tail++;
}
void pop(){
head++;
}
int peak(){
return queue[head];
}
int main(){
int num = 1;
while (!is_full()){
push(num);
num++;
}
while (!is_empty()){
printf("%d ",peak());
pop();
}
printf("\n");
printf(is_full() ? "满\n" : "不满\n");
return 0;
}
这个队列的实现,还存在缺陷,head和tail都只能加,不能减,不能实现现实中的真正的队列,像这里最后明明是空的,但是却判断为满,而不能再用,怎么改一下呢?
/*顺序结构实现循环队列*/
#include<stdio.h>
#include<stdbool.h>
int queue[3];
int head,tail,size;//head记录下一个要拿的数据的下标,tail记录下一个要放的数据的下标
bool is_empty(){
return !size;
}
bool is_full(){
return size == 3;
}
void init(){
head = 0;
tail = 0;
size = 0;
}
void destroy(){
head = 0;
tail = 0;
size = 0;
}
void push(int num){
queue[tail] = num;
tail = (tail + 1) % 3;
size++;
}
void pop(){
head = (head + 1) % 3;
size--;
}
int peak(){
return queue[head];
}
int main(){
int num = 1;
while (!is_full()){
push(num);
num++;
}
while (!is_empty()){
printf("%d ",peak());
pop();
}
printf("\n");
printf(is_full() ? "满\n" : "不满\n");
for (num = 1;num <= 3;num++){
push(num);
}
while (!is_empty()){
printf("%d ",peak());
pop();
}
printf("\n");
return 0;
}
2.2 队列的链式结构实现
/*队列练习,链式结构实现*/
#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
typedef struct node{
int num;
struct node *p_next;
}node;
node head;
void pop();
bool is_empty(){
return !head.p_next;
}
bool is_full(){
return false;
}
void init(){
}
void destroy(){
while (head.p_next){
pop();
}
}
void push(int num){
node *p_tmp = &head;
node *p_node = (node *)malloc(sizeof(node));
p_node->num = num;
p_node->p_next = NULL;
while (p_tmp->p_next){
p_tmp = p_tmp->p_next;
}
p_tmp->p_next = p_node;
}
void pop(){
if (head.p_next){
node *p_tmp = head.p_next;
head.p_next = p_tmp->p_next;
free(p_tmp);
p_tmp = NULL;
}
}
int peak(){
if (head.p_next){
return head.p_next->num;
}
else {
return -1;
}
}
int main(){
init();
push(1);
push(2);
push(3);
printf("%d ",peak());
pop();
printf("%d ",peak());
pop();
printf("%d\n",peak());
printf(is_empty() ? "空\n" : "非空\n");
destroy();
return 0;
}
最后,还有个好玩的,就是用堆栈来实现队列,这个怎么做呢?
我们可以申请两个堆栈,堆栈1用于输入,堆栈2用于输出。压入时只管往堆栈1中push,弹出的时候,就要注意了。在堆栈2为NULL时,倒数据,并把堆栈1中的数据倒空,然后直至弹空后,可再往堆栈2中倒数据。