了解数据结构的都清楚,堆栈操作很重要,堆栈存储数据与取出数据是先进后出,就像一个垃圾桶,最先倒进去的垃圾最后倒出来,而堆栈有两种操作方式:
1、基于顺序表的堆栈:初始化空间,通过栈顶指针表示当前可以接受新数据的位置。
2、基于链式表的堆栈:每个节点随压入随创建,随弹出随销毁,通过栈顶指针标识出最后压入的元素。
堆栈的操作主要是压入和弹出,下面针对上面两种操作方式给出相关程序。
基于顺序表
/********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: stack.h
* Description: This head file
*
* Version: 1.0.0(06/11/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "06/11/2017 09:06:52 PM"
*
********************************************************************************/
#ifndef _STACK_H
#define _STACK_H
#include <stdio.h>
#include <stdbool.h>
/* 堆栈 */
typedef struct Stack{
int* arr; //数组
size_t cap; //容量
size_t top; //栈顶
} STACK;
/* 分配内存并初始化为空堆栈 */
void stack_init (STACK* stack, size_t cap);
/* 释放内存并恢复到初始状态 */
void stack_deinit(STACK* stack);
/* 判断是否满 */
bool stack_full(STACK* stack);
/* 判断是否空 */
bool stack_empty(STACK* stack);
/* 压入 */
void stack_push(STACK* stack, int data);
/* 弹出 */
int stack_pop(STACK* stack);
/* 栈顶 */
int stack_top(STACK* stack);
/* 大小 */
size_t stack_size(STACK* stack);
#endif /* _STACK_H */
/********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: stack.h
* Description: This head file
*
* Version: 1.0.0(06/11/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "06/11/2017 09:06:52 PM"
*
********************************************************************************/
/* 基于顺序表的堆栈 */
#include <stdlib.h>
#include "stack.h"
/* 分配内存并初始化为空堆栈 */
void stack_init (STACK* stack, size_t cap)
{
stack->arr = malloc(cap* sizeof(stack->arr[0]));
stack->cap = cap;
stack->top = 0;
}
/* 释放内存并恢复到初始状态 */
void stack_deinit(STACK* stack)
{
free(stack->arr);
stack->arr = NULL;
stack->cap = 0;
stack->top = 0;
}
/* 判断是否满 */
bool stack_full(STACK* stack)
{
return stack->top >= stack->cap;
}
/* 判断是否空 */
bool stack_empty(STACK* stack)
{
return !stack->top;
}
/* 压入 */
void stack_push(STACK* stack, int data)
{
stack->arr[stack->top++] = data;
}
/* 弹出 */
int stack_pop(STACK* stack)
{
return stack->arr[--stack->top];
}
/* 栈顶 */
int stack_top(STACK* stack)
{
return stack->arr[stack->top - 1];
}
/* 大小 */
size_t stack_size(STACK* stack)
{
return stack->top;
}
/*********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: stack.c
* Description: This file
*
* Version: 1.0.0(06/11/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "06/11/2017 09:13:51 PM"
*
********************************************************************************/
/* 基于顺序表的堆栈 */
#include "stack.h"
#include <stdio.h>
/* 测试用例 */
int main(void)
{
STACK stack;
stack_init(&stack, 10);
int i = 0;
while (!stack_full(&stack))
{
stack_push(&stack, i++);
}
while (!stack_empty(&stack))
{
printf("%d\n", stack_pop(&stack));
}
stack_deinit(&stack);
return 0;
}
结果
[tangyanjun@VM_216_80_centos stack]$ a.out
9
8
7
6
5
4
3
2
1
0
基于链式表
/********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: sl.h
* Description: This head file
*
* Version: 1.0.0(06/15/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "06/15/2017 09:40:34 PM"
*
********************************************************************************/
#ifndef _SL_H
#define _SL_H
#include <sys/types.h>
#include <stdbool.h>
/* 节点 */
typedef struct StackNode{
int data; /* 数据 */
struct StackNode* next; /* 后指针,结构体中可以定义同名指针,但是不可以定义同名变量,因为不影响同类型的类型大小计算 */
} STACK_NODE;
/* 堆栈 */
typedef struct Stack{
STACK_NODE* top; /* 栈顶 */
} STACK;
/* 初始化为空堆栈 */
void stack_init(STACK* stack);
/* 释放剩余节点并恢复到初始状态 */
void stack_deinit(STACK* stack);
/* 判断是否为空 */
bool stack_empty(STACK* stack);
/* 压入 */
int stack_push(STACK* stack, int data);
/* 弹出 */
int stack_pop(STACK* stack);
/* 栈顶 */
int stack_top(STACK* stack);
/* 大小 */
size_t stack_size(STACK* stack);
#endif /* _SL_H */
/********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: sl.h
* Description: This head file
*
* Version: 1.0.0(06/15/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "06/15/2017 09:40:34 PM"
*
********************************************************************************/
#include <stdlib.h>
#include "sl.h"
/* 创建节点 */
static STACK_NODE* create_node(int data, STACK_NODE* next)
{
STACK_NODE* node = malloc(sizeof(STACK_NODE));
node->data = data;
node->next = next;
return node;
}
/* 销毁节点 */
static STACK_NODE* destroy_node(STACK_NODE* node)
{
STACK_NODE* next = node->next;
free(node);
return next;
}
/* 初始化为空堆栈 */
void stack_init(STACK* stack)
{
stack->top = NULL;
}
/* 释放剩余节点并恢复到初始状态 */
void stack_deinit(STACK* stack)
{
while(stack->top)
{
stack->top = destroy_node(stack->top);
}
}
/* 判断是否为空 */
bool stack_empty(STACK* stack)
{
return !stack->top;
}
/* 压入 */
int stack_push(STACK* stack, int data)
{
stack->top = create_node(data, stack->top);
}
/* 弹出 */
int stack_pop(STACK* stack)
{
int data = stack->top->data;
stack->top = destroy_node(stack->top);
return data;
}
/* 栈顶 */
int stack_top(STACK* stack)
{
return stack->top->data;
}
/* 大小 */
size_t stack_size(STACK* stack)
{
size_t size = 0;
STACK_NODE* node = NULL;
for (node = stack->top; node; node = node->next)
{
++size;
}
return size;
}
/*********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: si_test.c
* Description: This file
*
* Version: 1.0.0(06/24/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "06/24/2017 04:50:48 PM"
*
********************************************************************************/
#include <stdio.h>
#include "sl.h"
int main(int argc, char **argv)
{
printf("整数:");
unsigned int num;
scanf("%d", &num);
printf("进制:");
int base;
scanf("%d", &base);
STACK stack;
stack_init(&stack);
do {
stack_push(&stack, num % base);
} while(num /= base);
printf("结果:");
while(!stack_empty(&stack))
{
int digit = stack_pop(&stack);
printf("%d", digit);
}
printf("\n");
stack_deinit(&stack);
return 0;
}
结果
[tangyanjun@VM_216_80_centos stack_list]$ a.out
整数:50
进制:2
结果:110010
下面是一个基于链式表的老鼠走迷宫的程序
/*********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: maze.c
* Description: This file
*
* Version: 1.0.0(07/08/2017)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "07/08/2017 03:50:37 PM"
*
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include "sl.h"
/* environment */
#define SPACE_MOUSE '*' /* mouse */
#define SPACE_WAY ' ' /* passage */
#define SPACE_WALL '@' /* wall */
#define SPACE_PASS '.' /* track */
#define SPACE_IMPASSE 'X' /* impasse */
/* direction */
#define DIR_RIGHT 0 /* right */
#define DIR_DOWN 1 /* down */
#define DIR_LEFT 2 /* left */
#define DIR_UP 3 /* up */
/* The mouse */
const char* g_mouse = ">V<^";
typedef struct Mouse{
int x; /* horizontal */
int y; /* vertical */
int dir; /* direction */
int total; /* total number steps*/
int valid; /* effective steps */
STACK brain; /* brain */
} MOUSE;
/* initialization */
void mouse_init(MOUSE* mouse, int x, int y, int dir)
{
mouse->x = x;
mouse->y = y;
mouse->dir = dir;
mouse->total = 0;
mouse->valid = 0;
stack_init(&mouse->brain);
}
/* finalization */
void mouse_deinit(MOUSE* mouse)
{
stack_deinit(&mouse->brain);
}
/* memory of mouse */
void mouse_remember(MOUSE* mouse, int dir)
{
stack_push(&mouse->brain, dir);
}
/* recall/reminiscence */
int mouse_recall(MOUSE* mouse)
{
return stack_pop(&mouse->brain);
}
/* advance */
void mouse_go(MOUSE* mouse, int dir)
{
switch(dir)
{
case DIR_RIGHT:
++mouse->x;
break;
case DIR_DOWN:
++mouse->y;
break;
case DIR_LEFT:
--mouse->x;
break;
case DIR_UP:
--mouse->y;
break;
}
mouse_remember(mouse, mouse->dir = dir);
++mouse->total;
++mouse->valid;
}
/* retreat */
void mouse_back(MOUSE* mouse)
{
switch (mouse_recall(mouse))
{
case DIR_RIGHT:
--mouse->x;
mouse->dir = DIR_LEFT;
break;
case DIR_DOWN:
--mouse->y;
mouse->dir = DIR_UP;
break;
case DIR_LEFT:
++mouse->x;
mouse->dir = DIR_RIGHT;
break;
case DIR_UP:
++mouse->y;
mouse->dir = DIR_DOWN;
break;
}
++mouse->total;
--mouse->valid;
}
/* maze */
typedef struct Maze{
int cx; /* width */
int cy; /* height */
char* space; /* space */
MOUSE mouse; /* mouse */
}MAZE;
/* maze initialization */
void maze_init(MAZE* maze, int cx, int cy)
{
maze->cx = cx;
maze->cy = cy;
maze->space = malloc(cx * cy * sizeof(char));
mouse_init(&maze->mouse, 0, 1, DIR_RIGHT);
srand(time(NULL));
char (*space)[cx] = (char(*)[cx])maze->space;
int y;
int x;
for (y = 0; y <cy; ++y)
{
for (x = 0; x < cx; ++x)
{
if (x == maze->mouse.x && y == maze->mouse.y)
{
space[y][x] = SPACE_MOUSE;
}
else if((y == 1 && x < 4) || (y == cy - 2 && x > cx - 5))
{
space[y][x] = SPACE_WAY;
}
else if(y == 0 || y == cy -1 || x == 0 || x == cx - 1)
{
space[y][x] = SPACE_WALL;
}
else
{
space[y][x] = rand() % 4 ? SPACE_WAY : SPACE_WALL;
}
}
}
}
/* maze finalization */
void maze_deinit(MAZE* maze)
{
free(maze->space);
mouse_deinit(&maze->mouse);
}
/* show the maze */
void maze_show(MAZE* maze)
{
char(*space)[maze->cx] = (char(*)[maze->cx])maze->space;
int y;
int x;
for (y = 0; y < maze->cy; ++y)
{
for (x = 0; x < maze->cx; ++x)
{
switch(space[y][x])
{
case SPACE_MOUSE:
printf("\033[;;31m"); //color control red
break;
case SPACE_WALL:
printf("\033[;;34m"); //color control bule
break;
case SPACE_PASS:
printf("\033[;;32m"); //color control green
break;
case SPACE_IMPASSE:
printf("\033[;;35m"); //color control pruple
break;
}
printf("%c\033[0m", space[y][x] == SPACE_MOUSE ? g_mouse[maze->mouse.dir] : space[y][x]);
}
printf("\n");
}
printf("a total of go %d steps, %d effective.\n", maze->mouse.total, maze->mouse.valid);
}
/* read a char from standard input, no echo, no Enter */
int getch(void)
{
struct termios old;
ioctl(STDIN_FILENO, TCGETS, &old);
struct termios new = old;
new.c_lflag &= ~(ECHO | ICANON);
ioctl(STDIN_FILENO, TCSETS, &new);
int ch = getchar();
ioctl(STDIN_FILENO, TCSETS, &old);
return ch;
}
/* quit? */
bool maze_quit(void)
{
printf("press Q to quit, press others to continue...");
int ch = getch();
printf("\n");
return strchr("Qq", ch) != NULL;
}
/* next steps */
bool maze_step(MAZE* maze)
{
char(*space)[maze->cx] = (char(*)[maze->cx])maze->space;
int y = maze->mouse.y;
int x = maze->mouse.x;
space[y][x] = SPACE_PASS;
if (x + 1 <= maze->cx - 1 && space[y][x + 1] == SPACE_WAY)
{
mouse_go(&maze->mouse, DIR_RIGHT);
}
else if(y + 1 <= maze->cy - 1 && space[y + 1][x] == SPACE_WAY)
{
mouse_go(&maze->mouse, DIR_DOWN);
}
else if(x - 1 >= 0 && space[y][x - 1] == SPACE_WAY)
{
mouse_go(&maze->mouse, DIR_LEFT);
}
else if(y - 1 >= 0 && space[y - 1][x] == SPACE_WAY)
{
mouse_go(&maze->mouse, DIR_UP);
}
else
{
space[y][x] = SPACE_IMPASSE;
mouse_back(&maze->mouse);
}
y = maze->mouse.y;
x = maze->mouse.x;
space[y][x] = SPACE_MOUSE;
maze_show(maze);
if (y == maze->cy - 2 && x == maze->cx - 1)
{
printf("succeed!\n");
return false;
}
if (y == 1 && x == 0)
{
printf("not to go!\n");
return false;
}
return true;
}
/* run */
void maze_run(MAZE* maze)
{
for (maze_show(maze); !maze_quit() && maze_step(maze););
}
/* main */
int main(int argc, char **argv)
{
if (argc < 3)
{
printf("%s <width> <height>\n", argv[0]);
return -1;
}
MAZE maze;
maze_init(&maze, atoi(argv[1]), atoi(argv[2]));
maze_run(&maze);
maze_deinit(&maze);
return 0;
}
这个代码结合前面的sl.h和sl.c一起编译,结果如下:
[tangyanjun@VM_216_80_centos stack_list]$ a.out 50 20
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
> @ @ @@ @ @ @@ @@ @
@ @ @@ @ @ @@ @ @ @@ @
@@@ @ @ @@@ @ @@@ @@ @@
@ @ @@ @ @ @ @@ @ @ @ @ @@ @
@@ @ @ @ @ @@ @@@ @ @ @@ @
@@ @ @ @ @ @@ @@ @ @
@@ @ @ @ @@ @ @@@@ @ @
@ @@ @ @ @ @@ @ @ @ @
@ @@ @ @ @ @ @ @ @@ @
@ @ @@@@ @ @@ @ @ @ @
@ @@ @@@ @ @ @ @ @@
@ @ @@@ @ @ @ @ @ @@ @ @
@@ @@ @ @ @ @ @
@@ @ @ @ @ @@ @ @ @ @@ @
@ @ @ @ @ @ @ @@
@@@ @ @@@ @ @ @ @ @ @ @@ @@ @ @
@ @ @ @ @ @@ @ @ @ @ @
@ @ @ @ @ @ @ @ @ @ @@ @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
a total of go 0 steps, 0 effective.
press Q to quit, press others to continue...