栈和队列
栈
栈的存储结构:
顺序栈
typedef struct SqStack
{
int data[maxSize];
int top;
}SqStack;
链式栈
typedef struct LNode
{
int data;
struct LNode *next;
}LNode;
::栈的本质是线性表::,和线性表的定义方式完全一样!
顺序栈
四要素:两状态+两操作
-
几个状态
- 空栈:st.top == -1//top 代表栈顶元素的index
- 满栈:st.top == maxSize-1
- 非法上下溢
-
两个基本操作
- 进栈:先移动指针,再进入元素
stack[++top] = x;
- 出栈:先取出元素,后移动指针
x = stack[top--];
::用前先判断,空时不出,满时不进!::
链栈
四要素:两状态+两操作
-
两个状态
- 空栈:lst->next == NULL
- 满栈:不存在这种情况
-
两个基本操作
-
进栈:头插法
::头结点原来是指向的栈顶啊!!!:: -
出栈:出栈元素保存到x中
-
p = lst->next;
x = p->data;
lst->next = p->next;
free(p);
::考试不用写栈的函数,直接写必要的语句!::
习题
- 编写算法,判断一个表达式中括号是否真确配对,表达式个数为n
int match(char exp[], int n){
//初始化栈
char stack[maxSize];
int top = -1;
for(int i = 0; i < n; ++i){
if(exp[i] == '(')
stack[++top] = '(';
if(exp[i] == ')'){
if(top == -1)
return 0;
else
--top;
}
}
if(top == -1)
return 1;
else
return 0;
}
::栈中只放左括号!然后看到右括号就出栈::
- 编写一个函数,求后缀式的数值,其中后缀式存于字符数组exp中,exp中最后一个‘/0’作为结束符,并假设后缀式中的数字都只有一位。
//先定义操作符
int op(int a, char op, int b){
if(op == '+') return a + b;
if(op == '-') return a - b;
if(op == '*') return a * b;
if(op == '/'){
if(b == 0){
std::cout<<"b不能为0!"<<endl;
return 0;
}
else return a/b;
}
}
//再定义后缀计算函数
int com(char exp[]){
int stack[maxSize];
int top == -1;
int a, b, c;
char op;
for(int i = 0; exp[i] != '/0'; ++i){
if(exp[i] >= '0' && exp[i] <= '9')
stack[++top] = exp[i] - '0';
else{
op = exp[i];
b = stack[top--];
a = stack[top--];
c = op(a, op, b);
stack[++top] = c;
}
}
return stack[top];
}
队列
队列的存储结构
顺序队
typedef struct SqQueue
{
int data[maxSize];
int front;
int rear;
}SqQueue;
链队
//队结点类型定义
typedef struct QNode
{
int data;
struct QNode *next;
}QNode;
//队类型定义
typedef struct LiQueue
{
QNode *front;
QNode *rear;
}LiQueue;
顺序队
使用传统的顺序队列会产生“假溢出”情况,我们一般使用循环队列。
当元素进队时,rear指针向后移动;
当元素出队时,front指针向前移动。
-
两状态
- 队空状态:qu.rear == qu.front
- 队满状态:(qu.rear + 1)%maxSize == front
-
两操作
- 元素x进队:
qu.rear == (qu.rear + 1)%maxSize;
qu.data[qu.rear] = x;
- 元素x出队:
qu.front == (qu.front + 1)%maxSize;
x = qu.data[qu.front];
::都是先移动指针,后存取数据。::
链队
不存在“假溢出”。
-
两状态
- 队空状态:lqu->rear == NULL || lqu->front == NULL
- 不存在队满状态
-
两操作
- 入队:
lqu->rear->next = p;
lqu->rear = p;
- 出队:
p = lqu->front;
lqu->front = lqu->front->next;
x = p->data;
free(p);
::顺序队比链队简单多了,要尽量用顺序队。::
总习题
-
设循环队列的下标范围是0~n-1,其头、尾指针分别为f和r,则其元素个数为 (r - f + n)%n
- 当r > f 时,队列内元素为r - f;
- 当r < f 时,队列内元素为n - ( f - r )
-
编写一个算法,将一个非负的十进制整数N转换为一个二进制数。
int BaseTrans(int N){
int i, result = 0;
int stack[maxSize], top = -1;
while(N != 0){
i = N % 2;
N = N / 2;
stack[++top] = i;
}
while(top != -1){
i = stack[top--];
result = result * 10 + i;
}
return result;
}