堆栈操作

了解数据结构的都清楚,堆栈操作很重要,堆栈存储数据与取出数据是先进后出,就像一个垃圾桶,最先倒进去的垃圾最后倒出来,而堆栈有两种操作方式:

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.hsl.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...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值