栈(stack)

  • 仅限在表尾进行插入和删除操作的线性表
  • 表尾端称为栈顶(top)
  • 表头端称为栈底(bottom)
  • 后进先出(last in first out)的线性表(简称LIFO结构)
  • 入栈(Push)
  • 出栈(Pop)
  • 栈按存储结构可分为顺序栈和链式栈
  • 非法状态:上溢(栈满时继续入栈)、下溢(栈空时继续出栈)

顺序栈

//定义
typedef struct
{
    int data[maxSize];	//存放栈中元素
    int top;	//栈顶指针
} SqStack;
//初始化栈
void initStack(SqStack &st)
{
    st.top = -1;	//top为-1时,栈为空
}
//判断栈是否为空
int isEmpty(SqStack st)
{
 	if(st.top == -1)
        return 1;
    else
        return 0;
}
//进栈
int push(SqStack &st, int x)
{
	if(st.top == maxSize-1)	//栈满,不能进栈
        return 0;
    ++(st.top);
    st.data[st.top] = x;
    return 1;
}
//出栈
int pop(SqStack &st, int &x)
{
    if(st.top == -1) //栈空,不能出栈
        return 0;
    x = st.data[st.top];	//取出栈顶元素
    --(st.top);
    return 1;
}

链栈

//链栈结点定义
typedef struct LNode
{
    int data;	//数据域
    struct LNode *next;	//指针域
} LNode;
//初始化
void initStack(LNode *&lst)
{
    lst = (LNode*)malloc(sizeof(LNode));	//制造一个头结点
    lst->next = NULL;
}
//进栈
void push(LNode *lst, int x)
{
    LNode *p;
    p = (LNode*)malloc(sizeof(LNode));	//为进栈元素申请结点空间
    p->next = NULL;	
    
    //头插法
    p->data = x;
    p->next = lst->next;
    lst->next = p;
}
//出栈
void pop(LNode *lst, int &x)
{
    LNode *p;
    if(lst->next = NULL)	//判断栈是否为空
        return 0;
    p = lst->next;
    x = p->data;
    lst->next = p->next;
    free(p);
    return 1;
}

共享栈

  • 两个栈共享一片连续的存储空间,两个栈的栈底位于存储空间的两端,当两个栈的栈顶在栈空间的某处相遇时,产生上溢。

队列(queue)

  • 先进先出(first In first out,FIFO)的线性表
  • 队尾(rear):允许插入元素的一端,队尾元素
  • 队头(front):允许删除元素的一端,队头元素
  • 队列按存储结构可分为顺序队列和链队列

顺序队列

//定义
typedef struct
{
    int data[maxSize];
    int front;		//队首指针	
    int rear;		//队尾指针
}SqQueue;

链队列

//队列结点定义
typedef struct QNode
{
    int data;	//数据域
    struct QNode *next;	//指针域
}QNode;
//链队列类型定义
typedef struct
{
    QNode *front;	//队头指针
    QNode *rear;	//队尾指针
}LiQueue;
//初始化
void initQueue(LiQueue *&lqu)
{
    lqu=(LiQueue*)malloc(sizeof(LiQueue));
    lqu->front=lqu->rear=NULL;
}
//判断队空
int isQueueEmpty(LiQueue *lqu)
{
    if(lqu->rear==NULL||lqu->front==NULL)
        return 1;
    else
        return 0;
}
//入队
void enQueue(LiQueue *lqu,int x)
{
    QNode *p;
    p=(QNode*)malloc(sizeof(QNode));
    p->data=x;
    p->next=NULL;
    if(lqu->rear==NULL)	
        lqu->front=lqu->rear=p;
    else
    {
        lqu->rear->next=p;
        lqu->rear=p;
    }
}
int deQueue(LiQueue *lqu,int &x)
{
    QNode *p;
    if(lqu->rear==NULL)
        return 0;
    else
        p=lqu->front;
    if(lqu->front==lqu->rear)
        lqu->front=lqu->rear=NULL;
    else
        lqu->front=lqu->front->next;
    x=p->data;
    free(p);
    return 1;
}

循环队列

  • 队列为空:qu.front == qu.rear
  • 队列为满:(qu.rear+1)%maxSize == qu.front
  • 非空队列中,头指针始终指向队列头元素,而尾指针始终指向队列尾元素的下一个位置
  • 假溢出:普通顺序队列在一系列进队出队操作后,两个指针最终都会到达数组末端maxSize-1处,虽然队列中没有元素或元素未满,都不能让新元素入队。因此使用循环队列
//初始化
void initQueue(SqQueue &qu)
{
    qu.front=qu.rear=0;	//队首队尾指针重合,并指向0
}
//进队
int enQueue(SqQueue &qu, int x)
{
    if((qu.rear+1)%maxSize==qu.front)	//判断队满
        return 0;
    qu.rear=(qu.rear+1)%maxSize;	//先移动指针
    qu.data[qu.rear]=x;		//存入元素
    return 1;
}
//出队
int deQueue(SqQueue &qu, int &x)
{
    if(qu.front==qu.rear)	//判断队空
        return 0;
   	qu.front=(qu.front+1)%maxSize;	//队非空,移动指针
    x=qu.data[qu.front];	//取出元素
    return 1;
}

双端队列

  • 一种插入和删除操作在两端均可进行的线性表
  • 输入受限的双端队列:允许在一端进行插入和删除(进队和出队),另一端只允许删除
  • 输出受限的双端队列:允许在一端进行插入和删除(进队和出队),另一端只允许插入

算术表达式三种形式

前缀

中缀

后缀


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

上一篇
Canvas 下一篇