数据结构 学习笔记 栈

首先明确,栈和队列 是特殊的线性表。

 

栈(STL : STACK)

一、定义

栈是只能在一端进行插入和删除操作的线性表

日常例子:

洗碗摞一堆; 书摞成一堆; 一些枪支子弹夹中子弹的操作方式等。

1.1一些基本概念

栈顶(top)  进行插入和删除操作的一端

栈底(bottom) 相对栈顶的另一端

入栈(push) 插入操作

出栈(pop) 出栈操作

空栈:无元素的栈

1.2栈的特性

后进先出 ( LIFO-- Last In  First Out ),或 先进后出 ( FILO-- First In  Last Out )

 

二、顺序栈

2.1基本运算函数

#define MAXLEN 105
typedef struct {            //结构体定义顺序栈
    int data[MAXLEN];
    int top;
}seqStack;
void initStack(seqStack *S) {        //初始化栈,将栈顶置于-1,这样开始时从0插入
    S->top = -1;
}
bool stackEmpty(seqStack &S){        //判断栈是否为空
    if(S.top == -1) return true;
    else return  false;

    //return(S->top==-1);
}
bool stackFull(seqStack *S) {        //判断栈是否为满
    if(S->top == MAXLEN - 1) return true;
    else return false;
}
void stackTop(seqStack *S, int *x) { //X取为栈顶元素
    if(S->top == -1) {cout << "EMPTY ERROR" <<endl;return;}
    else *x = S->data[S->top];
}
void push(seqStack *S, int x) {       //插入
    if(S->top == MAXLEN - 1) {
        cout <<"ERROR"<<endl;
        return;
    }else {
        S->top++;
        S->data[S->top] = x;
    }
}
void pop(seqStack *S,int &x) {   //弹栈同时取到弹出元素
    if(stackEmpty(*S)) {cout <<"ERROR" <<endl; return;}
    else {
        x = S->data[S->top--];
    }
}

 

2.2 顺序栈的特点

所有运算的时间复杂度均为O(1); 通常一次性申请空间,只能按最大空间需求分配,容易造成空间浪费。-- 使用链式栈。

 

三、链栈

 

 

(以下运算为不带头结点的运算)

typedef struct {
    int data[MAXLEN];
    int top;
}seqStack;
typedef struct listNode{
    int data;
    struct listNode *next;
}node;
void initStack_1(node *&top) {
    top = NULL;
}
bool stackEmpty_1(node *top) {
    return (top == NULL);
}
bool stackTop(node *top, int x) { //由于头插法top仅跟着栈顶
    if(!top) return false;
    else {
        x = top -> data;
        return true;
    }
}
void push_1(node *& top, int x) { //头插
    node *s;
    s = new node;
    s->data = x;
    s->next = top;
    top = s;
}
bool pop_1(node *& top, int &x) {
    node *u;
    if(!top) return false;
    else {
        x = top->data;          //取弹出元素
        u = top;                //临时指针指到top
        top = top->next;        //top 后移
        delete(u);              //删除结点
        return true;
    }
}
void DeleteStack(node *&top) {
    node *p, *u;
    p = top;
    while(p) {
        u = p;
        p = p->next;
        delete(u);
    }
    top = NULL;
}

时间复杂度上,销毁链栈是O(N),其余均为O(1)

链栈的特点
·使用连续或不连续的储存空间
·各数据元素独立储存,依靠指针链接逻辑相邻关系
·对每个数据元素都单独申请结点
·不会存在栈满溢出的问题
·每个栈顶指针top唯一确定一个链栈

 

栈的应用举例

一、单链表的就地逆置

方法一、使用中间结点头插法建立新表

void reverse(node *&L) {        //STACK APPLICATION-1
    node *P = NULL;     //P指向i-1
    node *u;            //u指向i
    while(L) {
        u = L;          //u指向待分离的表头
        L = L->next;    //未逆置部分的表头指针L后移指向i+1
        u->next = P;    //新分离的i结点的next指向P 形成逆置
        P = u;          //已逆置部分的头指针P指向i
    }
    L = P;              //原表头指针指向新表头
}

方法二、使用栈

将元素结点存在栈中,依次弹栈后用尾插法建立链表

void reverse1(node *&L) {       //STACK APPLICATION-2
    node *R, *u;
    seqStack S;
    initStack(&S);
    u = L;
    while(u) {
        push(S,u);              //结点压入栈
        u = u->next;
    }
    if(stackEmpty(S)) {
        return;
    }
    stackTop(&S,u);             //取栈顶元素
    L = u;                      //新的表头元素
    R = u;                      //表尾指针
    u->next = NULL;
    pop(S,u);
    while(!stackEmpty(S)) {
        stackTop(S,u);
        R->next = u;
        u->next = NULL;
        R = u;
        pop(S,u);
    }
}

 

逆波兰表达式

#include <iostream>
#include <stack>
using namespace std;
const int MAXN = 1000 + 5;
char s[MAXN];
int pos;        //数组下标
int trans(int &pos) {
    int ans = 0;
    while(s[pos] >= '0' &&s[pos] <= '9') {
        ans *= 10;
        ans += (s[pos] -'0');
        pos++;
    }
    return ans;
}
int Level(char ch) {
    switch (ch) {
        case '+':
        case '-':
            return 1;
        case '*':
        case '/':
            return 2;
        case '(':
            return 0;
        case '#':
            return -1;
    }
}
int Op(int a1, char op, int a2) {
    switch (op) {
        case '+':
            return a1 + a2;
        case '-':
            return a1 - a2;
        case '*':
            return a1 * a2;
        case '/':
            return a1 / a2;
    }
}
int Computer() {
    stack<int> op1;
    stack<char> op2;
    op2.push('#');
    int len = strlen(s);
    bool minus = true;
    for(pos = 0; pos < len;) {
        if(s[pos] == '-' && minus) {
            op1.push(0);
            op2.push('-');
            pos++;
        }
        else if (s[pos] == ')') {
            minus = false;
            pos++;
            while(op2.top() != '(') {
                int a2 = op1.top();
                op1.pop();
                int a1 = op1.top();
                op1.pop();
                char op = op2.top();
                op2.pop();

                int res = Op(a1,op,a2);
                op1.push(res);
            }
            op2.pop();
        }
        else if(s[pos] >= '0' && s[pos] <= '9') {
            minus = false;
            op1.push(trans(pos));
        }
        else if (s[pos] == '(') {
            minus = false;
            op2.push(s[pos]);
            pos++;
        }
        else {
            while(Level(s[pos]) <= Level(op2.top())) {
                int a2 = op1.top();
                op1.pop();
                int a1 = op1.top();
                op1.pop();
                char op = op2.top();
                op2.pop();

                int res = Op(a1,op,a2);
                op1.push(res);
            }
            op2.push(s[pos]);
            pos++;
        }
    }
    while(op2.top()!='#') {
        int a2 = op1.top();
        op1.pop();
        int a1 = op1.top();
        op1.pop();
        char op = op2.top();
        op2.pop();

        int res = Op(a1,op,a2);
        op1.push(res);
    }
    return op1.top();
}
int main() {
    cin >> s;
    cout << "The Result is that:" << Computer() << endl;
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你好!关于学习数据结构的C语言笔记,我可以给你一些基本的指导和概念。数据结构是计算机科学中非常重要的一门课程,它涉及存储和组织数据的方法。C语言是一种常用的编程语言,很适合用于实现各种数据结构。 下面是一些数据结构的基本概念,你可以在学习笔记中包含它们: 1. 数组(Array):一种线性数据结构,可以存储相同类型的元素。在C语言中,数组是通过索引访问的。 2. 链表(Linked List):也是一种线性数据结构,但不需要连续的内存空间。链表由节点组成,每个节点包含数据和指向下一个节点的指针。 3. (Stack):一种后进先出(LIFO)的数据结构,类似于装满物品的箱子。在C语言中,可以使用数组或链表来实现。 4. 队列(Queue):一种先进先出(FIFO)的数据结构,类似于排队等候的队伍。同样可以使用数组或链表来实现队列。 5. 树(Tree):一种非线性数据结构,由节点和边组成。每个节点可以有多个子节点。二叉树是一种特殊的树结构,每个节点最多有两个子节点。 6. 图(Graph):另一种非线性数据结构,由节点和边组成。图可以用来表示各种实际问题,如社交网络和地图。 这只是数据结构中的一些基本概念,还有其他更高级的数据结构,如堆、哈希表和二叉搜索树等。在学习笔记中,你可以介绍每个数据结构的定义、操作以及适合使用它们的场景。 希望这些信息对你有所帮助!如果你有任何进一步的问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值