数据结构---栈与队列

参照<<大话数据结构>> 仅做学习记录

  • 1.1栈

定义:栈是仅限定在表尾进行插入和删除的线性表。

          先进后出,类似子弹的弹夹的子弹,对应相关操作。

允许插入和删除数据的一端叫栈顶(top),不能修改数据的地方叫栈底(bottom)

栈的插入数据叫入栈(push),删除数据叫出栈(pop)。

  • 栈的顺序存储结构

定义栈长度为stacksize, 栈顶的位置用top参数记录,可定义如下结构体

typedef int Element;
typedef struct {
    Element data[stacksize];
    int top;  //栈顶的位置
}SqStack;
  • 两栈共享空间

数据结构---栈与队列_第1张图片

栈顶:数组的开始,下标为0处。

栈尾:数组的结尾,下标为n-1处。(n代表两个栈的元素个数之和)

  • 栈1和栈2之间的数量关系

栈1------(1)空栈:top1 = -1, (2)有一个元素:top1 = 0;

栈2------(1)空栈:top2 = n;  (2)有一个元素:top2 = n-1;

  • 栈满

(1)top1 = n-1; top2 = n;    栈1-栈满

(2)top1 = -1; top2 = 0;   栈2-栈满

(3)top1 + 1 = top2;   栈1和栈2在中间碰上了(4-5-1第三张图),栈满。

  •  根据两栈的图可定义如下的结构体
typedef int Element;
typedef struct {
    Element data[stacksize];
    int top1;  //top1栈顶的位置
    int top2;  //top2栈顶的位置
}DoubleStack;
  • 栈的push或者pop

需要传入参数:定义是操作栈1还是栈2

  • 栈的链式存储结构

 首先定义一个链栈LinkStack,其中的Element是链式结构体(包含数据域+指针结点)

typedef struct {
    Element top; // 指向栈顶结点的指针
    int count; //计数
}LinkStack;

typedef struct {
    int data;  //数据域 
    struct StackNode *next; //指向下一个结点
}StackNode, *Element; // 由于是链式结构,需要定义一个”数据域+指针域“的结构体

对应的出栈,入栈操作:

数据结构---栈与队列_第2张图片

 数据结构---栈与队列_第3张图片

  • 栈的应用

将一串带括号的操作,去掉括号来通过栈来运算操作。

比如 9+(3-1)*3+10/2(中缀表达式) -------->表示为(后缀表达式)9 3 1 -3 * + 10 2 / +

  • 顺序队列(类似排队,最前面的可以删,最后插入)

定义:只允许一端插入(队尾)操作,另外一端进行删除(队头)操作的线性表

           先进先出(FIFO),

数据结构---栈与队列_第4张图片

如果定义一个队列,front定义队首的位置,rear定义队尾的位置,如下图,队列的大小为5个字节,当a5被放入了队列,rear就变成了5,但是这个时候0 1是空的。但rear却以为溢出了,这就是假溢出。为了解决假溢出于是引出了循环队列

数据结构---栈与队列_第5张图片

  • 循环队列

循环队列:把队列首尾相接,这样的贵队列称为循环队列。解决了假溢出。

所以当下标为4的地方被占了,下个位置应该为0,

数据结构---栈与队列_第6张图片

 但这样带来了新的问题,当rear和front相等,我们不清楚此时队列是满了(4-12-7右图),还是空的(rear == front == 0),有如下两种办法解决(标志位和留空)

数据结构---栈与队列_第7张图片

  •  普通队列和循环队列的结构体定义
typedef Elemnt int; 
struct Quenen {
    Element val[Max];  //值
    int front;  // 队首
    int rear;  //队尾

};
  • 队列的链式结构

链队列:其实就是正常的单链表,不过仅仅允许头部数据被删除,尾部数据被插入。

结构体:

typedef Element int;

//节点
typedef struct {
    Element* val;
    Node* next;
}Node;

//队列链
struct Quen {
    Node* front; //头节点
    Node* rear;  //尾节点
};

应用:

线程A接收数据,利用队列tmp.push_back(); 来存储数据。 

线程B利用队列tmp的先入先出的特性来消费tmp.pop();收到的数据。

问题:1.是否需要设置最大的队列容量     2.是否需要用循环队列

你可能感兴趣的:(数据结构,栈和队列)