栈和队列

栈的存储结构:

顺序栈

typedef struct SqStack
{
    int data[maxSize];
    int top;
}SqStack;

链式栈

typedef struct LNode
{
    int data;
    struct LNode *next;
}LNode;

::栈的本质是线性表::,和线性表的定义方式完全一样!

顺序栈

四要素:两状态+两操作

  • 几个状态

    1. 空栈:st.top == -1//top 代表栈顶元素的index
    2. 满栈:st.top == maxSize-1
    3. 非法上下溢
  • 两个基本操作

    1. 进栈:先移动指针,再进入元素
stack[++top] = x;
  1. 出栈:先取出元素,后移动指针
x = stack[top--];

::用前先判断,空时不出,满时不进!::

链栈

四要素:两状态+两操作

  • 两个状态

    1. 空栈:lst->next == NULL
    2. 满栈:不存在这种情况
  • 两个基本操作

    1. 进栈:头插法
      ::头结点原来是指向的栈顶啊!!!::

    2. 出栈:出栈元素保存到x中

p = lst->next;
x = p->data;
lst->next = p->next;
free(p);

::考试不用写栈的函数,直接写必要的语句!::

习题

  1. 编写算法,判断一个表达式中括号是否真确配对,表达式个数为n
int match(char exp[], int n){
    //初始化栈
    char stack[maxSize];
    int top = -1;

    for(int i = 0; i < n; ++i){
        if(exp[i] == '(')
        stack[++top] = '(';
        if(exp[i] == ')'){
            if(top == -1)
            return 0;
            else 
            --top;
        }
    }
    if(top == -1)
    return 1;
    else
    return 0;
}

::栈中只放左括号!然后看到右括号就出栈::

  1. 编写一个函数,求后缀式的数值,其中后缀式存于字符数组exp中,exp中最后一个‘/0’作为结束符,并假设后缀式中的数字都只有一位。
//先定义操作符
int op(int a, char op, int b){
    if(op == '+') return a + b;
    if(op == '-') return a - b;
    if(op == '*') return a * b;
    if(op == '/'){
        if(b == 0){
            std::cout<<"b不能为0!"<<endl;
            return 0;
        }
        else return a/b;
    }
}

//再定义后缀计算函数
int com(char exp[]){
    int stack[maxSize];
    int top == -1;
    int a, b, c;
    char op;
    for(int i = 0; exp[i] != '/0'; ++i){
        if(exp[i] >= '0' && exp[i] <= '9')
        stack[++top] = exp[i] - '0';
        else{
            op = exp[i];
            b = stack[top--];
            a = stack[top--];
            c = op(a, op, b);
            stack[++top] = c;
        }
    }
    return stack[top];
}

队列

队列的存储结构

顺序队

typedef struct SqQueue
{
    int data[maxSize];
    int front;
    int rear;
}SqQueue;

链队

//队结点类型定义
typedef struct QNode
{
    int data;
    struct QNode *next;
}QNode;

//队类型定义
typedef struct LiQueue
{
    QNode *front;
    QNode *rear;
}LiQueue;

顺序队

使用传统的顺序队列会产生“假溢出”情况,我们一般使用循环队列。
当元素进队时,rear指针向后移动;
当元素出队时,front指针向前移动。

  • 两状态

    1. 队空状态:qu.rear == qu.front
    2. 队满状态:(qu.rear + 1)%maxSize == front
  • 两操作

    1. 元素x进队:
qu.rear == (qu.rear + 1)%maxSize;
qu.data[qu.rear] = x;
  1. 元素x出队:
qu.front == (qu.front + 1)%maxSize;
x = qu.data[qu.front];

::都是先移动指针,后存取数据。::

链队

不存在“假溢出”。

  • 两状态

    1. 队空状态:lqu->rear == NULL || lqu->front == NULL
    2. 不存在队满状态
  • 两操作

    1. 入队:
lqu->rear->next = p;
lqu->rear = p;
  1. 出队:
p = lqu->front;
lqu->front = lqu->front->next;
x = p->data;
free(p);

::顺序队比链队简单多了,要尽量用顺序队。::

总习题

  1. 设循环队列的下标范围是0~n-1,其头、尾指针分别为f和r,则其元素个数为 (r - f + n)%n


    • 当r > f 时,队列内元素为r - f
    • 当r < f 时,队列内元素为n - ( f - r )
  2. 编写一个算法,将一个非负的十进制整数N转换为一个二进制数。

int BaseTrans(int N){
    int i, result = 0;
    int stack[maxSize], top = -1;
    while(N != 0){
        i = N % 2;
        N = N / 2;
        stack[++top] = i;
    }
    while(top != -1){
        i = stack[top--];
        result = result * 10 + i;
    }
    return result;
}
原文地址:https://www.cnblogs.com/endymion/p/9090413.html