# Ch3

#

LIFO

# 顺序栈的实现

定义
1
2
3
4
5
#define MaxSize 50
typedef struct{
ElemType data[MaxSize];
int top;
}SqStack;
初始化
1
2
3
void InitStack(SqStack &S){
S.top = -1;
}
判断空
1
2
3
4
5
6
bool StackEmpty(SqStack S){
if(S.top == -1)
return true;
else
return false;
}
push
1
2
3
4
5
6
bool Push(SqStack &S,ElemType x){
if(S.top == MaxSize - 1)
return false;
S.data[++S.top] = x;
return true;
}
pop
1
2
3
4
5
6
bool Pop(SqStack &S,ElemType &x){
if(S.top == -1)
return false;
x = S.data[S.top--];
return true;
}
gettop
1
2
3
4
5
6
bool GetTop(SqStack S,ElemType &x){
if(S.top == -1)
return false;
x = S.data[S.top];
return true;
}

# 共享栈

同时从两边向中间压栈

# 链栈

定义
1
2
3
4
typedef struct Linknode{
ElemType data;
struct Linknode *next;
}LiStack;

# 队列

FIFO

# 顺序存储

队列的实现
1
2
3
4
5
#define MaxSize 50
typedef struct{
ElemType data[MaxSize];
int front,rear;
}SqQueue;

初始状态:front = rear = 0

队列判空
1
2
3
4
5
6
bool QueueEmpty(SqQueue Q){
if(Q.front == Q.rear)
return true;
else
return false;
}

# 循环队列

初始化
1
2
3
void InitQueue(SqQueue &Q){
Q.front = Q.rear = 0;
}
队列判空
1
2
3
4
5
6
bool QueueEmpty(SqQueue Q){
if(Q.front == Q.rear)
return true;
else
return false;
}
队列判满
1
2
3
4
5
6
bool QueueFull(SqQueue Q){
if((Q.rear + 1) % MaxSize == Q.front)
return true;
else
return false;
}
入队
1
2
3
4
5
6
7
bool EnQueue(SqQueue &Q,ElemType x){
if(QueueFull(Q))
return false;
Q.data[Q.rear] = x;
Q.rear = (Q.rear + 1) % MaxSize;
return true;
}
出队
1
2
3
4
5
6
7
bool DeQueue(SqQueue &Q,ElemType &x){
if(QueueEmpty(Q))
return false;
x = Q.data[Q.front];
Q.front = (Q.front + 1) % MaxSize;
return true;
}
求元素个数
1
2
3
int QueueLength(SqQueue Q){
return (Q.rear - Q.front + MaxSize) % MaxSize;
}

# 链式存储

链队列的实现
1
2
3
4
5
6
7
typedef struct Linknode{
ElemType data;
struct Linknode *next;
}LinkNode;
typedef struct{
LinkNode *front,*rear;
}LinkQueue;

一般设计成带头结点的链队列

初始化
1
2
3
4
void InitQueue(LinkQueue &Q){
Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
Q.front->next = NULL;
}
队列判空
1
2
3
4
5
6
bool QueueEmpty(LinkQueue Q){
if(Q.front == Q.rear)
return true;
else
return false;
}
入队
1
2
3
4
5
6
7
bool EnQueue(LinkQueue &Q,ElemType x){
LinkNode *s = (LinkNode*)malloc(sizeof(LinkNode));
s->data = x;
s->next = NULL;
Q.rear->next = s;
Q.rear = s;
}
出队
1
2
3
4
5
6
7
8
9
10
11
bool DeQueue(LinkQueue &Q,ElemType &x){
if(Q.front == Q.rear)
return false;
LinkNode *p = Q.front->next;
x = p->data;
Q.front->next = p->next;
if(Q.rear == p)
Q.rear = Q.front;
free(p);
return true;
}

# 双端队列

  • 输出受限的双端队列
    允许在一端进行 push/pop 操作,另一端只能 push
  • 输入受限的双端队列
    允许在一端进行 push/pop 操作,另一端只能 pop

# 栈和队列的应用

#

# 表达式

  • 括号匹配
    左括号压栈,右括号出栈,判断是否匹配
  • 算术表达式
    中缀表达式:左根右
    前缀表达式:根左右
    后缀表达式:左右根

中缀转后缀

  1. 加括号
  2. 把运算符移到当前层的括号后面
  3. 去掉括号
    用栈实现中缀转后缀:
  1. 遇到操作数直接加入后缀表达式
  2. 遇到括号,左括号入栈,右括号依次出栈加入后缀表达式直到遇到左括号位置,并删除左括号
  3. 遇到运算符,判断优先级,如果栈为空或者栈顶为 “(” 或者栈顶运算符优先级低于当前运算符,则入栈,否则依次出栈加入后缀表达式,直到栈为空或者栈顶运算符优先级低于当前运算符(优先级相同的也要出栈),最后将当前运算符入栈
    所以栈里面只存运算符和括号

后缀表达式求值
从左到右扫描表达式,遇到操作数压栈,遇到操作符就弹出两个操作数,计算结果压入栈中

# 递归

# 队列

# 层次遍历

根左右入队,依次 pop

# 队列的应用

  • 缓冲区
  • 操作系统的请求队列

# 数组

特殊矩阵的压缩存储

  • 对称矩阵
    只存下三角的元素,存在一维数组里
  • 三角矩阵
    省略 0,摊平存在一维数组
  • 三对角
    同理省略 0,存在一维数组里
  • 稀疏矩阵
    行标,列标,值都成三元组,存储在线性表(数组或者十字链表),保存的同时要保存系数矩阵的行数、列数和非零元素的个数
Edited on

Give me a cup of [coffee]~( ̄▽ ̄)~*

NoResponse WeChat Pay

WeChat Pay

NoResponse Alipay

Alipay

NoResponse PayPal

PayPal