第三章限定线性表-------栈与队列

1.栈是一种线性表,但限定这种线性表只能在某一端进行插入或删除的操作,栈的特性:后进先出。

栈顶:允许进行插入和删除的那一端

栈厎:固定的,不允许进行插入或删除的另一端。

n个不同元素进栈,出栈元素不同排列的个数为1/(n+1)C2nn

1.顺序栈

typedef int ElemType;
#define true 1
#define false 0
#define MaxSize 100//定义栈中元素的最大个数
typedef struct {
    ElemType data[MaxSize];//存放栈中元素的一维数组
    int top;//栈顶指针
}SqStack;
//栈顶指针S.top,初始时设-1,栈顶元素S.data[S.top]
// 栈空:S.top==-1,栈满:S.top==MaxSize-1,栈长:S.top+1;
//初始化
void InitStack(SqStack* S) {
    S->top = -1;
}
//判栈空
int IsEmptyStack(SqStack S) {
    if (S.top == -1)
        return true;
    else
        return false;
}
//进栈
int Push(SqStack* S, ElemType x) {
    if (S->top == MaxSize - 1)
        return false;
    S->top++;
    S->data[S->top] = x;
    return true;
}
//出栈
int Pop(SqStack* S, ElemType* x) {
    if (S->top == -1)
        return false;
    *x = S->data[S->top];
    S->top--;
    return true;
}
//读取栈顶元素
int GetTop(SqStack *S, ElemType *x) {
    if (S->top == -1)
        return false;
    *x = S->data[S->top];
}

2.多栈共享技术:最常用的是两个栈的共享技术,双端栈,两个栈共享一片空间,提高内存资源利用率,降低发生上溢的可能。

#include "stdlib.h"
#include "stdio.h";
#include "stdbool.h"

#define M 100
#define StackElemType int 
typedef struct {
    StackElemType Stack[M];
    StackElemType top[2];
}DqStack;
void InitStack(DqStack* S) {
    S->top[0] = -1;
    S->top[1] = M;
}
int Push(DqStack* S, StackElemType x, int i) {
    if (S->top[0] + 1 == S->top[1])
        return false;
    switch (i){
    case 0:
        S->top[0]++;
        S->Stack[S->top[0]] = x;
        break;
    case 1:
        S->top[1]--;
        S->Stack[S->top[1]] = x;
        break;
    default:
        return false;
    }
    return true;
}
int Pop(DqStack* S, StackElemType* x, int i) {
    switch (i) {
    case 0:
        if (S->top[0] == -1)
            return false;
        *x = S->Stack[S->top[0]];
        S->top[0]--;
        break;
    case 1:
        if (S->top[1] == M)
            return false;
        *x = S->Stack[S->top[1]];
        S->top[1]++;
        break;
    default:
        return false;
    }
    return true;
}

3.链栈

链栈即采用链表作为存储结构实现的栈,链表的表头指针就作为栈顶指针,栈顶指针始终指向当前栈顶元素前面的头结点。若top->next==NULL,则代表栈空。

采用链栈不必预先估计栈的最大容量,只要系统有可用空间,链栈就不会出现溢出,对于链栈,在使用完毕时,应该释放相应空间

#include "stdlib.h"
#include "stdio.h"
#define true 1
#define false 0
typedef int ElemType;
typedef struct node {
    ElemType data;
    struct node* next;
}LinkStackNode;
typedef LinkStackNode* LinkStack;
//链栈进栈
int Push(LinkStack top, ElemType x) {
    LinkStackNode *temp;
    temp = (LinkStackNode*)malloc(sizeof(LinkStackNode));
    if (temp == NULL)//申请空间失败
        return false;
    temp->data = x;
    temp->next = top->next;
    top->next = temp;//修改当前栈顶指针
    return true;
}
//链栈出栈
int Pop(LinkStack top, ElemType *x) {
    LinkStackNode *temp;
    temp = top->next;
    if (temp == NULL)//栈空
        return false;
    top->next = temp->next;
    *x = temp->data;
    free(temp);
    return true;
}

队列

一种操作受限的线性表,只允许在表的一端插入,而在表的另一端删除,特性:先进先出

队头:允许删除的一端,又称队首。

队尾:允许插入的一端

1.顺序存储结构:

重点看循环队列:为了解决假溢出现象并使队列得到充分利用,将顺序队列想象成一个环状的空间,即把存储队列元素的表从逻辑上视为一个环,称为循环队列。

在非空循环队列中,队头指针始终指向当前的队头元素,而队尾指针始终指向真正队尾元素后面的单元

当队首指针Q.font=Q.MaxSize-1后,再前进一个位置就自动到0,这就可以利用除法取余运算来实现。

初始时:Q.front=Q.rear=0

队首指针进1:Q.front=(Q.front+1)%MaxSize

队尾指针进1:Q.rear=(Q.rear+1)%MaxSize

队列长度:(Q.rear+MaxSize-Q.front)%MaxSize

出队入队时:指针都顺时针方向进1

判队空:Q.front=Q.rear

队满:1.损失一个元素空间,当队尾指针所指向的空单元的后继单元是队头元素所在的单元时,则停止入队。队满:(Q.rear+1)%MaxSize==Q.front

2.增设表示元素个数的数据单元,队空:Q.size=0;队满:Q.size=MaxSize

3.增设tag数据成员,初始化时:rear=front=tag=0;每次删除成功:tag=0;每次插入成功:tag=1;

队满:front==rear&&tag==1 队空:front==rear&&tag=0,删除才可能致空,插入才可能致满。

#include "stdio.h"
#include "stdlib.h"
typedef int ElemType;
#define MaxSize 50
#define true 1
#define false 0
typedef struct {
    ElemType data[MaxSize];//存放队列元素
    int front, rear;//队头指针和队尾指针
}SqQueue;
//初始化
void InitQueue(SqQueue* Q) {
    Q->rear = Q->front = 0;
}
//判断空
int IsEmpty(SqQueue Q) {
    if (Q.rear == Q.front)
        return true;
    else
        return false;
}
//入队
int EnterQueue(SqQueue *Q, ElemType x) {
    if ((Q->rear + 1) % MaxSize == Q->front)//队满则报错
        return false;
    Q->data[Q->rear] = x;
    Q->rear = (Q->rear + 1) % MaxSize;//队尾指针加1取模
    return true;
}
//出队
int DeQueue(SqQueue* Q, ElemType* x) {
    if (Q->rear == Q->front)//队空则报错
        return false;
    x = Q->data[Q->front];
    Q->front = (Q->front + 1) % MaxSize;//队头指针加1取模
    return true;
}
typedef struct {
    ElemType data[MaxSize];
    int front, rear;
    int tag;
}SeqQueue;
void InitQueueC(SeqQueue* Q) {
    Q->rear = Q->front = 0;
    Q->tag = 0;
}
int Isempty(SeqQueue Q) {
    if (Q.front == Q.rear && Q.tag == 0)
        return true;
    else
        return false;
}
int enterQueue(SeqQueue* Q, ElemType x) {
    if (Q->front == Q->rear && Q->tag == 1)
        return false;
    Q->data[Q->rear] = x;
    Q->rear = (Q->rear + 1) % MaxSize;
    Q->tag = 1;
    return true;
}
int Dequeue(SeqQueue* Q, ElemType* x) {
    if (Q->front == Q->rear && Q->tag == 0)
        return false;
    *x = Q->data[Q->front];
    Q->front = (Q->front + 1) % MaxSize;
    Q->tag = 0;
    return true;
}
typedef struct {
    ElemType data[MaxSize];
    int front, rear;
    int size;
}Queue;
void init(Queue* Q) {
    Q->rear = Q->front = 0;
    Q->size = 0;
}
int isEmpty(Queue Q) {
    if (Q.size == 0)
        return true;
    else
        return false;
}
int enqueue(Queue* Q, ElemType x) {
    if (Q->size == MaxSize)
        return false;
    Q->data[Q->rear] = x;
    Q->rear = (Q->rear + 1) % MaxSize;
    Q->size++;
    return true;
}
int dequeue(Queue* Q, ElemType* x) {
    if (Q->size == 0)
        return false;
    *x = Q->data[Q->front];
    Q->front = (Q->front + 1) % MaxSize;
    Q->size--;
    return true;
}

队列长度:(rear+MaxSize-front)%MaxSize;

2.链队列

若采用带头结点的链表结构:队头指针始终指向头结点,队尾指针指向最后一个元素,空的链队列的队头指针和队尾指针均指向头结点。

typedef struct Node{//链式队列结点
    ElemType data;
    struct Node *next;
}LinkQueueNode;
typedef struct{//链式队列
    LinkQueueNode *front, * rear;//队列的队头和队尾指针
}LinkQueue;
int Initqueue(LinkQueue* Q) {
    Q->front = (LinkQueueNode*)malloc(sizeof(LinkQueueNode));
    if (Q->front != NULL) {
        Q->rear = Q->front;
        Q->front->next = NULL;
        return true;
    }
    else
        return false;
}
//链队列入队
int EnterLinkQueue(LinkQueue *Q, ElemType x) {
    LinkQueueNode *NewNode;
    NewNode = (LinkQueueNode*)malloc(sizeof(LinkQueueNode));
    if (NewNode != NULL) {
        NewNode->data = x;
        NewNode->next = NULL;
        Q->rear->next = NewNode;
        Q->rear = NewNode;
        return true;
    }
    else
        return false;
}
//链队列出队
int DeleteQueue(LinkQueue* Q, ElemType* x) {
    LinkQueueNode* p;
    if (Q->front == Q->rear)
        return false;
    p = Q->front->next;
    Q->front->next = p->next;//队头元素p出队
    if (Q->rear == p)//若队中只有一个元素p,则p出队后为空队列
        Q->rear = Q->front;
    *x = p->data;
    free(p);
    return true;
}

 

posted @ 2021-09-29 22:11  #Lorraine#  阅读(90)  评论(0)    收藏  举报