顺序栈的形状
问题?
typedef struct SqStack{
int data[maxSize]; // 顺序栈实现数组,maxSize 定义存储的最大个数
int top; // top 栈顶指针
}SqStack;
void initStack(SqStack &st){
st.top = -1; // 栈顶指针默认初始值为 -1
}
int isEmpty(SqStack st){
if(st.top == -1){
return 1; // 栈空
}else{
return 0; // 栈不空
}
}
注意:栈空返回 1 ,栈不空返回 0
int push(SqStack &st , int x){
if(st.top == maxSize-1){ // 栈满,上溢,入栈失败
return 0;
}
++(st.top); // 先移动栈顶指针,因为初始值为 -1
st.data[st.top] = x; // 元素入栈
return 1;
}
注意:入栈成功返回 1, 失败返回 0。入栈需要先判断栈是否已经满,因为数组存储是固定的
int pop(SqStack &st , int &x){
if(st.top == -1){ // 栈空,下溢,出栈失败
return 0;
}
x = st.data[st.top]; // 元素出栈
--(st.top); // 后移动栈顶指针,因为初始值为 -1
return 1;
}
注意:出栈成功返回 1, 失败返回 0 ,出栈需要先判断栈空,否则栈空出栈没有元素产生错误
链栈的形状
问题?
typedef struct LNode{
int data; // 数据域
struct LNode *next; // 指针域,指向下一个结点
}LNode;
void initStack(LNode *&lst){
lst = (LNode *)malloc(sizeof(LNode)); // 制造一个头结点
lst->next = NULL;
}
int isEmpty(LNode *lst){
if(lst->next == NULL){ // 判断栈空
return 1;
}else{
return 0;
}
}
注意:栈空返回 1 ,栈不空返回 0
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;
}
注意:入栈操作不需要判断栈空,因为链表是动态增长的,只要内存够大,就可以一直创建节点
int pop(LNode *lst , int &x){
if(lst->next == NULL){ // 栈空
return 0;
}
LNode *q;
/*将指针指向要删除的结点*/
q = lst->next;
x = q->data;
/*将删除结点从链表中删除*/
lst->next = q->next;
/*释放结点,不要忘了*/
free(q);
return 1;
}
注意:出栈操作需要判断栈空,出栈记得将节点释放掉
案例:编写一个算法,将一个非负的十进制整数N转换为一个二进制数?
代码分析
代码实现
int tenTotwo(int N , int r){ // r 为 2
int t[maxSize]; // maxSize 为已定义常量
int top = -1; // 初始化栈顶指针
int n = N;
int result = 0;
while(n != 0){
t[++top] = n%r; // 将余数放入栈中
n = n/r;
}
while(top != -1){
result = result*10 + t[top--];
}
return result;
}
案例:试编写一个算法,检查一个程序中的花括号、方括号和圆括号是否配对,若全部配对,则返回 1 ,否则返回 0。对于程序中出现的一对单引号或双引号内的字符不进行括号配对检查。 39 为单引号的 ASCII 值,34 为双引号的 ASCII 值,单引号和双引号如果出现则必成对出现。假设 stack 是已定义的顺序栈结构体,可以直接调用的元素进展/出栈、取栈顶元素、判断栈空的函数定义如下:
void push(stack &S , char ch);
void pop(stack &S , char &ch);
void getTop(stack S , char &ch);
int isEmpty(stack S); // 若栈 S 空,则返回 1,否则返回 0
代码分析
代码实现
int match(char ch[]){
int i = 0; // 循环变量
/*定义栈*/
stack S;
char c; // 接收字符
while(ch[i] != '\0'){
if(ch[i] == 39){ // 单引号内不检查配对
++i;
while(ch[i] != 39)
++i;
++i;
}else if(ch[i] == 34){ // 双引号内不检查配对
++i;
while(ch[i] != 34)
++i;
++i;
}else{
switch(ch[i]){
case '{':
case '[':
case '(':
push(S,ch[i]);
break;
case '}':
getTop(S,c); // 获取栈顶元素
if(c == '{') // 配对
pop(S,c);
else
return 0;
break;
case ']':
getTop(S,c);
if(c == '[') // 配对
pop(S,c);
else
return 0;
break;
case ')':
getTop(S,c);
if(c == '(') // 配对
pop(S,c);
else
return 0;
}
++i;
}
}
if(isEmpty(S) == 1){ // 栈空,则表明括号匹配无误,返回 1
return 1;
}else{
return 0;
}
}
共享栈图形
栈S1 从低到高,栈S2从高到低,当两个栈顶在中间相遇时,栈满
案例:用两个顺序栈实现共享栈?
代码分析
代码实现
// 定义共享栈的结构体
typedef struct SqStack{
int elem[maxSize]; // 定义共享栈空间
int top[2]; // top[0] 为 s0 的栈顶,top[1] 为 s1 的栈顶
}SqStack;
// 入栈操作
int push(SqStack &st, int stNo , int x){ // st共享栈,stNo 顺序栈序号,x 入栈元素
// 入栈,先判断栈是否满
if(st.top[0]+1 < st.top[1]){
// 栈不满,再判断 顺序栈的序号
if(stNo == 0){
++(st.top[0]); // 先移动 s0 栈顶指针
st.elem[st.top[0]] = x; // 元素入栈
return 1;
}
if(stNo == 1){
--(st.top[1]); // 先移动 s1 栈顶指针
st.elem[st.top[1]] = x; // 元素入栈
return 1;
}
return -1; // 序号不对
}
return 0; // 栈满
}
// 出栈操作
int pop(SqStack &st , int stNo , int &x){
// 先判断出栈序号
if(stNo == 0){
// 再判断栈是否空
if(st.top[0] != -1){
// 栈不空,元素出栈
x = st.elem[st.top[0]];
--(st.top[0]);
return 1;
}else{
return 0; // 栈空
}
}else if(stNo == 1){
// 判断栈是否空
if(st.top[1] != maxSize){
// 栈不空,元素出栈
x = st.elem[st.top[1]];
++(st.top[1]);
return 1;
}else{
return 0; // 栈空
}
}else{
return -1; // 序号不对
}
}
案例:栈模拟队列实现?
代码分析
代码实现
// 入队列
int enQueue(SqStack &s1 , SqStack &s2 , int x){
int y;
if(s1.top == maxSize-1){ // 判断 s1 栈是否已满,则看 s2 是否空
if(!isEmpty(s2)){
return 0; // s1 满,s2 非空
}else if(isEmpty(s2)){ // s2 空,先将 s1 中元素进入 s2 中
while(!isEmpty(s1)){
pop(s1,y);
push(s2,y);
}
push(s1,x); // 将 x 进入栈 s1 中
return 1;
}
}else{ // s1 栈不满,直接入栈
push(s1,x);
return 1;
}
}
// 出队列
int deQueue(SqStack &s1 , SqStack &s2 , int &x){
int y;
if(!isEmpty(s2)){ // s2 非空,出队列(本质,s2 元素出栈)
pop(s2,x);
return 1;
}else{
if(isEmpty(s1)){ // s1 空,直接结束,不空,将 s1 中元素压入 s2 中
return 0;
}else{
while(!isEmpty(s1)){
pop(s1,y);
push(s2,y);
}
pop(s2,x);
return 1;
}
}
}
// 判断队列是否空
int isQueueEmpty(SqStack s1 , SqStack s2){
if(isEmpty(s1) && isEmpty(s2)){
return 1; // 队列空
}else{
return 0; // 队列不空
}
}
代码分析
代码实现
void preOrder(BTNode *bt){
/*根结点不空,执行遍历*/
if(bt != NULL){
// 1)
BTNode *stack[maxSize]; // 定义一个栈(存的都是BTNode类型指针)
int top = -1;
BTNode *p;
// 2)
stack[++top] = bt; // 根节点入栈
while(top != -1){ // 栈不空
p = stack[top--]; // p 指向根结点,并执行出栈
visit(p); // visit 访问结点
if(p->rChild != NULL){
stack[++top] = p->rChild;
}
if(p->lChild != NULL){
stack[++top] = p->lChild;
}
}
}
}