C语言与数据结构笔记:25栈和队列

[声明]:此文档为本人学习小甲鱼C语言与数据结构课程时的笔记记录。仅供学习之用,转载请标明出处!感谢小甲鱼!
本文目录

后进先出,本质是一个线性表,只在表尾进行删除和插入操作。
两种存储方式:

  • 顺序存储结构
  • 链式存储结构

栈的顺序结构

栈头和栈底 指针 地址 线性表
栈头 s->top 大地址 表头
s->base 小地址 表尾

定义栈

typrdef struct
{
    ElemType *base;
    ElemType *top;
    int stackSize;   //当前可用最大容量
}sqStack;

创建一个空栈:

#define STACK_INIT_SIZE 100
initStack(sqStack *s)
{
    s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
    if(!s->base)
        exit(0);  //申请空间失败,则退出
    s->top = s->base;
    s->stackSize = STACK_INIT_SIZE
}

入栈操作

#include<stdlib.h>   //realloc操作
#define STACKINCREMENT 10
Push(sqStack *s, ElemType e)
{
    //如果栈满,则追加空间
    if(s->tpo - s->base >= s->stackSize)
    {
        s-base = (ElemType *)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(ElemType));
        if(!s->base)
            exit(0);
        s->top = s->base + s->stackSize;
        s->stackSize = s->stackSize + STACKINCREMENT;
    }
    *(s->tpo) = e;
    s->tpo++;
}

出栈

//  修改栈使用指针,不修改(测试)直接传入
Pop(sqStack *s, ElemType *e)
{
    if(s->top == s->base)
        return;
    *e = *--(s->top);  //先将指针s->top减一再取出内容赋值给*e
}

栈的链式存储结构

通常我们使用栈的顺序存储结构存储。栈只能在栈顶进行插入和删除操作,栈的链式存储结构比较好的方法就是将栈顶放在单链表的表头,栈顶指针和单链表的头指针合二为一。

栈的链式存储结构:初始化栈

typedef struct StackNode
{
    Elemtype data;       // 存放栈的数据
    struct StackNode *next;
}StackNode, *LinkStackPtr;
typedef struct LinkStack
{
    LinkStackPrt top;   //top指针
    int count;          //栈元素计数器
}

栈的链式存储结构:入栈

// 假设元素之为e的新结点是s,top 为栈顶指针。
Status Push(LinkStack *s, ElemType e)
{
    LinkStackPtr p = (LinkStackPtr) malloc (sizeof(StackNode));
    p->data = e;
    p->next = s->top;
    s->top = p;
    s->count++;
    return OK; 
}

栈的链式存储结构:出栈

Status Pop(LinkStack *s, ElemType *e)
{
    LinkStackPtr p;
    if(StackEmpty(*s))   //判断是否为空栈
        return ERROR;
    *e = s->top->data;
    p = s->top;
    s->top = s->top->next;
    free(p);
    s->count--;
    return OK;
}

示例

(一):二进制转换成十进制

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

#define STACK_INIT_SIZE 20
#define STACKINCREMENT  10

typedef char ElemType;
typedef struct
{
    ElemType *base;
    ElemType *top;
    int stackSize;
}sqStack;


void InitStack(sqStack *s)
{
    s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
    if(!s->base)
    {
        exit(0);
    }
    s->top = s->base;
    s->stackSize = STACK_INIT_SIZE;
}

void Push(sqStack *s, ElemType e)
{
    if(s->top -s->base >= s->stackSize)
    {
        s->base =(ElemType *)realloc(s->base, (s->stackSize + STACKINCREMENT)*sizeof(ElemType));
        if(!s->base)
        {
            exit(0);
        }
    }
    *(s->top) = e;
    s->top++;
}

void Pop(sqStack *s, ElemType *e)
{
    if(s->top == s->base)
    {
        return;
    }
    *e = *--(s->top);
}

int StackLen(sqStack s)    //传入非指针
{
    return (s.top - s.base);
}

int main()
{
    ElemType c;
    sqStack s;
    int len, i, sum=0;
    InitStack(&s);

    printf("请输入一个二进制数,输入#表示结束!\n");
    scanf("%c", &c);
    while(c != '#')
    {
        Push(&s, c);
        scanf("%c", &c);
    }

    getchar(); //清理键盘缓冲区回车'\n'

    len = StackLen(s);
    printf("当前栈的容量是:%d\n", len);
    for(i=0; i<len; i++)
    {
        Pop(&s, &c);
        sum = sum + (c-48) * pow(2, i);
    }

    printf("转换为十进制输出是:%d\n", sum);
    return 0;
}

(二):逆波兰计算器

输入逆波兰表达式(即后缀表达式),得出计算结果。

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>

#define STACK_INIT_SIZE 20
#define STACKINCREMENT  10
#define MAXBUFFER       10

typedef double ElemType;
typedef struct
{
    ElemType *base;
    ElemType *top;
    int stackSize;
}sqStack;

InitStack(sqStack *s)
{
    s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
    if(!s->base)
    {
        exit(0);
    }
    s->top = s->base;
    s->stackSize = STACK_INIT_SIZE;
}

Push(sqStack *s, ElemType e)
{
    if((s->top - s->base) >= s->stackSize) //检测栈,栈满追加空间
    {
        s->base = (ElemType *)realloc(s->base, (s->stackSize +
                            STACKINCREMENT) * sizeof(ElemType));
        if(!s->base)
        {
            exit(0);
        }
        s->top = s->base + s->stackSize;
        s->stackSize = s->stackSize + STACKINCREMENT;
    }
    *(s->top) = e;
    s->top++;
}
 Pop(sqStack *s, ElemType *e)
 {
     // 判断栈是否为空
     if(s->top == s->base)
     {
         return;
     }
     *e = *--(s->top);
 }

int StackLen(sqStack s)
{
    return (s.top - s.base);
}

int main()
{
    sqStack s;
    char c;
    double d,e;
    char str[MAXBUFFER];
    int i=0;

    InitStack(&s);  //初始化栈

    printf("请按逆波兰表达式输入数据,数据与运算符之间用空格隔开,以#结束!\n");
    scanf("%c", &c);
    while(c != '#')
    {
        while( isdigit(c) || c=='.')  //判断C是否为数字,头文件ctype.h
        {
            str[i++] = c;
            str[i] = '\0';  //数组是作为局部变量定义的,没有初始化为0。应为下一个数据自动填充0。
            if(i >= 10)
            {
                printf("\n出错:输入的单个数据过大!\n");
                return -1;
            }
            scanf("%c", &c);
            if(c == ' ')
            {
                d = atof(str); //  atof()字符串型->浮点数,atod()字符串->整型。
                Push(&s, d);
                i = 0;
                break;
            }
        }
        switch( c )
        {
            case '+':
                Pop(&s, &e);
                Pop(&s, &d);
                Push(&s, d+e);
                break;
            case '-':
                Pop(&s, &e);
                Pop(&s, &d);
                Push(&s, d-e);
                break;
            case '*':
                Pop(&s, &e);
                Pop(&s, &d);
                Push(&s, d*e);
                break;
            case '/':
                Pop(&s, &e);
                Pop(&s, &d);
                if(e != 0)
                {
                    Push(&s, d/e);
                }
                else
                {
                    printf("\n出错:除数为0!!!");
                    return -1;
                }
                break;
        }
        scanf("%c", &c);
    }

    Pop(&s, &d);
    printf("\n最终的计算结果为:%f\n", d);

    return 0;
}


//逆波兰表达式示例
//(1-2)*(4+5)        ->    1 2 - 4 5 + *#          结果:(-9)
//5-(6+7)*8+9/4      ->    5 6 7 + 8 * - 9 4 / +   结果:(-96.75)

(三):中缀表达式转换为后缀表达式

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

#define STACK_INIT_SIZE 20
#define STACKINCREMENT  10

typedef char ElemType;
typedef struct
{
    ElemType *base;
    ElemType *top;
    int stackSize;
}sqStack;


void InitStack(sqStack *s)
{
    s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
    if(!s->base)
    {
        exit(0);
    }
    s->top = s->base;
    s->stackSize = STACK_INIT_SIZE;
}

void Push(sqStack *s, ElemType e)
{
    if(s->top -s->base >= s->stackSize)
    {
        s->base =(ElemType *)realloc(s->base, (s->stackSize + STACKINCREMENT)*sizeof(ElemType));
        if(!s->base)
        {
            exit(0);
        }
    }
    *(s->top) = e;
    s->top++;
}

void Pop(sqStack *s, ElemType *e)
{
    if(s->top == s->base)
    {
        return;
    }
    *e = *--(s->top);
}

int StackLen(sqStack s)
{
    return (s.top - s.base);
}

int main()
{
    sqStack s;
    char c, e;

    InitStack(&s);

    printf("请输入中坠表达式,输入#表示结束!\n");
    scanf("%c", &c);
    while(c != '#')
    {
        while(c >= '0' && c <= '9')  //输入为数字直接打印
        {
            printf("%c", c);
            scanf("%c", &c);
            if(c < '0' || c >= '9')
            {
                printf(" ");
            }
        }
        if(')' == c)         //输入为 ')',弹栈,打印
        {
            Pop(&s, &e);
            while('(' != e)
            {
                printf("%c ", e);
                Pop(&s, &e);
            }
        }
        else if('+' == c || '-' == c)
        {
            if(!StackLen(s))
            {
                Push(&s, c);
            }
            else
            {
                do
                {
                    Pop(&s, &e);
                    if('(' == e)
                    {
                        Push(&s, e);
                    }
                    else
                    {
                        printf("%c ", e);
                    }
                }while(StackLen(s) && '(' != e);
                Push(&s, c);
            }
        }
        else if('*' == c || '/' == c || '(' == c)
        {
            Push(&s, c);
        }
        else if('#' == c)
        {
            break;
        }
        else
        {
            printf("\n出错:输入格式错误!\n");
            return -1;
        }
        scanf("%c", &c);
    }


   while(StackLen(s))
   {
       Pop(&s, &e);
       printf("%c ", e);
   }
    return 0;
}

// 输入:1+(2-3)*4+10/5#

猜你喜欢

转载自blog.csdn.net/X13031007077/article/details/80781890