
1.队列的定义:
1.3.1队列的定义和初始化:

//队列的顺序存储类型
# define MaxSize 10; //定义队列中元素的最大个数
typedef struct{
ElemType data[MaxSize]; //用静态数组存放队列元素
//连续的存储空间,大小为——MaxSize*sizeof(ElemType)
int front, rear; //队头指针和队尾指针
}SqQueue;
//初始化队列
void InitQueue(SqQueue &Q){
//初始化时,队头、队尾指针指向0
Q.rear = Q.front = 0;
}
void test{
SqQueue Q; //声明一个队列
InitQueue(Q);
//...
}
// 判空
bool QueueEmpty(SqQueue 0){
if(Q.rear == Q.front) //判空条件后
return true;
else
return false;
}1.4.1定义:
将循环队列臆造为一个环状的空间,即把存储队列元素的表从逻辑上视为一个环,称为循环队列。
基本操作:
a%b == a除以b的余数
初始: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
bool EnQueue(SqQueue &Q, ElemType x){
if((Q.rear+1)%MaxSize == Q.front) //队满
return false;
Q.data[Q.rear] = x; //将x插入队尾
Q.rear = (Q.rear + 1) % MaxSize; //队尾指针加1取模
return true;
}//出队,删除一个队头元素,用x返回
bool DeQueue(SqQueue &Q, ElemType &x){
if(Q.rear == Q.front) //队空报错
return false;
x = Q.data[Q.front];
Q.front = (Q.front + 1) % MaxSize; //队头指针后移动
return true;
}
bool GetHead(SqQueue &Q, ElemType &x){
if(Q.rear == Q.front) //队空报错
return false;
x = Q.data[Q.front];
return true;
}实际上获取队头元素的值就是出队操作去掉队头指针后移的代码
# define MaxSize 10;
typedef struct{
ElemType data[MaxSize];
int front, rear;
int size; //队列当前长度
}SqQueue;
//初始化队列
void InitQueue(SqQueue &Q){
Q.rear = Q.front = 0;
size = 0;
}不牺牲一个存储空间,在结构体中多建立一个变量size
初始化时rear=front=0;size = 0;
队列元素个数= size
插入成功size++;删除成功size--;
此时队满条件:size==MaxSize
队空条件:size == 0;
# define MaxSize 10;
typedef struct{
ElemType data[MaxSize];
int front, rear;
int tag; //最近进行的是删除or插入
}SqQueue;不牺牲一个存储空间,在结构体中多建立一个变量tag
初始化时rear=front=0;tag = 0;
因为只有删除操作,才可能导致队空,只有插入操作,才可能导致队满因此
每次删除操作成功时,都令tag=0;
每次插入操作成功时,都令tag=1;
队满条件:front==rear && tag == 1
队空条件:front==rear && tag == 0
队列元素个数:(rear+MaxSize-front)%MaxSize



//新元素入队 (表尾进行)
void EnQueue(LinkQueue &Q, ElemType x){
LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode)); //申请一个新结点
s->data = x;
s->next = NULL; //s作为最后一个结点,指针域指向NULL
Q.rear->next = s; //新结点插入到当前的rear之后
Q.rear = s; //表尾指针指向新的表尾
}

//队头元素出队
bool DeQueue(LinkQueue &Q, ElemType &x){
if(Q.front == Q.rear)
return false; //空队
LinkNode *p = Q.front->next; //p指针指向即将删除的结点 (头结点所指向的结点)
x = p->data;
Q.front->next = p->next; //修改头结点的next指针
if(Q.rear == p) //此次是最后一个结点出队
Q.rear = Q.front; //修改rear指针
free(p); //释放结点空间
return true;
}
4.1定义:
4.2考点:

4.3代码实现:

算数表达式: 由三个部分组成:操作数、运算符、界限符 我们平时写的算术表达式都是中缀表达式 如何可以不用界限符也能无歧义地表达运算顺序 Reverse Polish notation(逆波兰表达式=后缀表达式) Polish notation(波兰表达式=前缀表达式) 中缀、后缀、前缀表达式:

中缀转后缀的方法(手算):
“左优先”原则:只要左边的运算符能先计算,就优先算左边的,保证手算和机算是一致的

中缀表达式转后缀表达式(机算,用栈实现):
按上述方法处理完所有字符后,将栈中剩余运算符依次弹出,并加入后缀表达式。
后缀表达式的计算(手算):
后缀表达式的计算(机算,用栈实现):
中缀表达式转前缀表达式(手算):
中缀表达式的计算(机算,用栈实现):
中缀表达式的计算=中缀转后缀+后缀表达式求值,两个算法的结合
用栈实现中缀表达式的计算:
函数调用的特点: 最后被调用的函数最先执行结束(LIFO) 函数调用时,需要用一个栈(函数调用栈)存储,里面包含以下信息:
适合用“递归”算法解决:可以把原始问题转换为属性相同,但规模较小的问题
栈在递归中的应用:
栈在递归中过程:
缺点:
太多层递归可能会导致栈溢出
可能包含很多重复计算
操作系统中的应用
一维数组的存储结构:
二维数组的存储结构:
普通矩阵的存储:
对称矩阵的压缩存储:

三角矩阵的压缩存储:


三对角矩阵的压缩存储:

稀疏矩阵的压缩存储:
