数据结构-C语言实现:栈 和 栈的实例

用基础的C语言实现一个顺序栈:表尾做栈顶

1. 栈的操作

栈的操作主要有三个:
①push:元素入栈

②pop:元素出栈(此元素会从栈内删除) C++的pop无返回值,而Java的pop有返回值

③top(Java为peek):查看栈顶元素(仅查看)

具体实现方式如下:(详细描述请看注释)

 (1)创建Stack结构体存储数据:

struct Stack{
    int *data;  //数据,动态分配大小 
    int capacity;//栈容量 ,数组最高元素下标是capacity-1 
    int top;   //栈顶位置
}; 

(2)栈的初始化函数:栈顶top有两种初始化方式,这里我们选择ps->top = 0;

void init(struct Stack *ps,int capacity){
    ps->capacity = capacity;
    ps->data  = (int *)malloc(sizeof(int)*capacity);
    ps->top = 0; //top初始化可以是0或-1,栈内刚开始时是没有元素的,
//    所以可以用top初始化为-1来使之始终指向栈里最高位的元素
//    或者初始化为0来指向数组最高下标之后的空位
}

(3)下面是几个经常用到的函数,其中isEmpty()和isFull()是在push,pop,top操作中判断栈满栈空的,判断方式也可以直接写在这三个函数中,但是由于多次用到,就直接拿出来写成函数

destroy:销毁栈,释放空间

printStack:打印栈内元素

int isFull(const struct Stack *ps){//不会改变栈内元素,可以用const修饰 
//    最高元素下标是capacity-1
//判断栈满:top == capacity//因为刚开始top = 0,top(栈顶)指向最高下标的后一位 
    return  ps->top==ps->capacity; 
} 
int isEmpty(const struct Stack *ps){
    return ps->top ==0;
}
void printStack(struct Stack *ps){
    for(int i = 0;i<ps->top-1;i++){
        printf("%d->",ps->data[i]);
    }
    printf("%d\n",ps->data[ps->top-1]);
}
void destroy(struct Stack *ps){
    free(ps->data);
}

(4)三大操作的实现:

int push(struct Stack *ps,int x){
//    if()//将判断栈满写为一个函数 
        if(isFull(ps)) return 0;
        else{
            ps->data[ps->top]=x;//top是栈顶空位 
            ps->top++;
            return 1;
        }
}
int pop(struct Stack *ps,int *px){//这里的*px是为了得到pop删除的元素指,也可以直接使用top,将此函数改为int pop(struct Stack *ps)
    if(isEmpty(ps)) return 0;
    else{
        ps->top--;//top-1的位置即为栈顶元素所在位置 
        *px = ps->data[ps->top];
        return 1;
    }
}
int top(const struct Stack *ps)
{
    if(isEmpty(ps)) return 0;
    else{
        //top-1的位置即为栈顶元素所在位置 
        return ps->data[ps->top-1];
    }
}

整体代码:

//顺序栈:表尾做栈顶
#include<stdio.h>
#include<stdlib.h>
struct Stack{
    int *data;  //数据,用指针动态分配大小 
    int capacity;//栈容量 ,最高元素下标是capacity-1 
    int top;   //栈顶位置
     
}; 
void init(struct Stack *ps,int capacity){
    ps->capacity = capacity;
    ps->data  = (int *)malloc(sizeof(int)*capacity);
    ps->top = 0; //top初始化可以是0或-1,刚开始时是没用元素的,
//    所以可以用-1始终指向栈里最高位的元素
//    或者使用0来指向最高位之后的空位
     
}
int isFull(const struct Stack *ps){//不会改变栈内元素,可以用const修饰 
//    最高元素下标是capacity-1
//判断栈满:top == capacity//因为刚开始top = 0,栈顶指向最高下标的后一位 
    return  ps->top==ps->capacity; 
} 
int isEmpty(const struct Stack *ps){
    return ps->top ==0;
}
int push(struct Stack *ps,int x){
//    if()//将判断栈满写为一个函数 
        if(isFull(ps)) return 0;
        else{
            ps->data[ps->top]=x;//top是栈顶空位 
            ps->top++;
            return 1;
        }
}
int pop(struct Stack *ps,int *px){
    if(isEmpty(ps)) return 0;
    else{
        ps->top--;//top-1的位置即为栈顶元素所在位置 
        *px = ps->data[ps->top];
        return 1;
    }
}
int top(const struct Stack *ps)
{
    if(isEmpty(ps)) return 0;
    else{
        //top-1的位置即为栈顶元素所在位置 
        return ps->data[ps->top-1];
    }
}
void printStack(struct Stack *ps){
    for(int i = 0;i<ps->top-1;i++){
        printf("%d->",ps->data[i]);
    }
    printf("%d\n",ps->data[ps->top-1]);
}
void destroy(struct Stack *ps){
    free(ps->data);
}
int main()
{
    struct Stack st;
    init(&st,5);//改变st的内容//栈初始化 
    push(&st,22);//压栈,需要改变结构体内数据
    push(&st,33);
    push(&st,44);
    push(&st,55);
    push(&st,66);
    printStack(&st);
    int x; 
    //也可以写一个top函数返回栈顶元素; 
    pop(&st,&x);//弹出栈,栈空时不成功; 
    printf("%d\n",x);
    int y = top(&st);
    printf("%d\n",y);
    printStack(&st);
    //销毁栈
    destroy(&st);
    
    return 0; 
}
View Code

Stack应用:

例-2 后缀式求值 (25分)
 

我们人类习惯于书写“中缀式”,如 3 + 5 * 2 ,其值为13。 (p.s. 为什么人类习惯中缀式呢?是因为中缀式比后缀式好用么?)
而计算机更加习惯“后缀式”(也叫“逆波兰式”,Reverse Polish Notation)。上述中缀式对应的后缀式是: 3 5 2 * +
现在,请对输入的后缀式进行求值。

输入格式:

在一行中输入一个后缀式,运算数运算符之间用空格分隔,运算数长度不超过6位,运算符仅有+ - * / 四种。

输出格式:

在一行中输出后缀式的值,保留一位小数。

输入样例:

3 5.4 2.2 * +
 

输出样例:

14.9

数据输入时要注意的:

scanf("%s")....不接收空格,部分编译器可以使用gets(不建议,c++11,14已经被移除)

C++中可以用cin>>str 来获取输入的字符串,录入的字符串中如果包含空格,则会根据空格将字符串分割成多段,如果想要输入带空格的字符串,可以使用getline()

 cin函数是直接从缓冲区取数据的,所以有时候当缓冲区中有残留数据时,cin函数会直接取得这些残留数据而不会请求键盘输入。(比如用空格将两段数据隔开)

getchar/cin.get()接收的是输入str之后的回车,以此来判断输入是否结束:以便跳出循环

C++string的size函数就是其实际长度,和length函数无区别,且string中无'\0'

要考虑到负数的存在

#include<iostream>
#include<string>
#include<stack>
using namespace std;
int main()
{
    double a , b ;
    string str;
    stack<double> num;
    while (cin >> str) {
        char c = getchar();
        
//        负数和小数size>1,但是操作符的一定=1 ,C++string的size就是其实际长度,和length函数无区别
        if ((str[0]>='0'&&str[0]<='9')/*isdigit(str[0])*/||str.size()>1) {
            num.push(stod(str));
        }
        else {
            switch (str[0])
            {
            case '+': a = num.top();
                num.pop();
                 b = num.top();
                num.pop();
                num.push(a + b);
                break;
            case '-': a = num.top();
                num.pop();
                 b = num.top();
                num.pop();
                num.push(b-a);
                break;
            case '*': a = num.top();
                num.pop();
                 b = num.top();
                num.pop();
                num.push(b*a);
                break;
            case '/':a = num.top();
                num.pop();
                 b = num.top();
                num.pop();
                num.push(b / a);
                break;
            
            }
            
        }
            if (c == '\n') {
            break;
        }
        
    }
    printf("%.1f\n", num.top());

    return 0;

猜你喜欢

转载自www.cnblogs.com/ziggystardust-pop/p/12560420.html