章节3.1和3.2----栈的表示、实现和应用

文章目录

    • 1、存储结构 P46
    • 2、顺序栈实现
    • 3、链栈的实现
    • 4、进制转换
    • 5、括号匹配
    • 6、行编辑程序
    • 7、迷宫求解
    • 8、表达式求值
    • 9、斐波那契数列
    • 10、汉诺塔问题

1、存储结构 P46

typedef struct{
    int *base;
    int *top;
    int StackSize;
}SqStack;

2、顺序栈实现

会了顺序表和链表的话,栈就简单的多了
下面我给出的这个小例子,里面包含了顺序栈的初始化、压栈、弹栈、遍历操作

#include
#include

#define Init_size 100
#define Increment 10

typedef struct{
    int *base;
    int *top;
    int StackSize;
}SqStack;

int InitStack(SqStack *S){//初始化
    S->base=(int *)malloc(Init_size*sizeof(int));
    if(!S->base) return -1;
    S->top=S->base;
    S->StackSize=Init_size;
    return 0;
}
int Push(SqStack *S,int e){//入栈
    if(S->top-S->base>=S->StackSize){//如果空间不够 增加空间
        S->base=(int *)realloc(S->base,(S->StackSize+Increment)*sizeof(int));
        if(!S->base) return -1;
        S->top=S->base+S->StackSize;
        S->StackSize+=Increment;
    }
    *(S->top)=e;
    S->top++;
    return 0;
}
int Pop(SqStack *S,int *e){//弹栈
    if(S->top==S->base)return -1;
    S->top--;
    *e=*(S->top);
    return 0;
}
int main(){
    //申请一个栈 将1-10依次入栈 并依次弹栈输出
    SqStack S;
    InitStack(&S);
    for(int i=1;i<=10;i++){
        Push(&S,i);
    }
    int e;
    while(S.base!=S.top){
        Pop(&S,&e);
        printf("%d ",e);
    }
}

3、链栈的实现

关于链栈的实现,其实前面我们在写链表的时候,最终我们优化出来的终极版本,其实就已经很像一个链式栈了。只是操作上再加以限制就好了
栈要遵循先进后出的原则:
章节3.1和3.2----栈的表示、实现和应用_第1张图片
章节3.1和3.2----栈的表示、实现和应用_第2张图片
需要注意的是,我们在弹栈的时候,也就相当于删除链表末尾元素,所以要先找到末尾元素的前驱,如果这是个双向链栈,那么我们可以直接通过top指针找到他的前驱,单向链栈的话,我们就需要遍历找到最后了。
这里我用的是单向链栈,显然用双向效率更高,有兴趣可以试试实现双向链栈。
实现代码:


#include
#include


typedef struct LDataNode{
	int x;
	struct LDataNode *next;//结点指针
}LDataNode;
typedef struct LHeadNode{
	LDataNode *base; //栈底指针
	LDataNode *top; //栈顶指针
}LHeadNode,*LinkStack;

int InitStack(LinkStack *head){//初始化链栈
	*head =(LinkStack)malloc(sizeof(LHeadNode));//指向头结点的头指针
	LDataNode *vhNode =(LDataNode *)malloc(sizeof(LDataNode));//首元结点
	if(*head==NULL||vhNode==NULL) return -1;//申请失败

	vhNode->next=NULL;
	(*head)->base=vhNode;
	(*head)->top=vhNode;
	return 0;
}
int Push(LinkStack *head,int e){
    (*head)->top->x=e;//压入栈

    LDataNode *vhNode =(LDataNode *)malloc(sizeof(LDataNode));
    if(vhNode==NULL)  return -1;//申请失败
    (*head)->top->next=vhNode;
    vhNode->next=NULL;
	(*head)->top=vhNode;//栈顶指针后移
	return 0;
}
int Pop(LinkStack *head,int *e){
    LDataNode *p=(*head)->base;//指向第1个结点
    while(p!=NULL){//遍历链栈
        if(p->next==(*head)->top) break;
        p=p->next;
    }
    (*head)->top=p;//栈顶指针回退
    *e=p->x;
    return 0;
}
int main(){
    LinkStack head;
    InitStack(&head);

    for(int i=1;i<=10;i++){
        Push(&head,i);//依次压栈
    }
    int e;
    for(int i=1;i<=10;i++){
        Pop(&head,&e);//依次弹栈
        printf("%d ",e);
    }
}

4、进制转换

注意:这里我写的三个程序,均实现的是一个十进制数转化成n进制数,n<10.
如果要转换十六进制,需要略作修改。

C语言实现

#include
#include

#define Init_size 100
#define Increment 10

typedef struct{
    int *base;
    int *top;
    int StackSize;
}SqStack;

int InitStack(SqStack *S){//初始化
    S->base=(int *)malloc(Init_size*sizeof(int));
    if(!S->base) return -1;
    S->top=S->base;
    S->StackSize=Init_size;
    return 0;
}
int Push(SqStack *S,int e){//入栈
    if(S->top-S->base>=S->StackSize){//如果空间不够 增加空间
        S->base=(int *)realloc(S->base,(S->StackSize+Increment)*sizeof(int));
        if(!S->base) return -1;
        S->top=S->base+S->StackSize;
        S->StackSize+=Increment;
    }
    *(S->top)=e;
    S->top++;
    return 0;
}
int Pop(SqStack *S,int *e){//弹栈
    if(S->top==S->base)return -1;
    S->top--;
    *e=*(S->top);
    return 0;
}
//将10进制数a转换为n进制数
int conversion(int a,int n){
    SqStack S;
    InitStack(&S);
    while(a){
        Push(&S,a%n);
        a/=n;
    }
    int e;
    while(S.top!=S.base){
        Pop(&S,&e);
        printf("%d",e);
    }
    return 0;
}
int main(){
    int a,n;
    scanf("%d%d",&a,&n);
    conversion(a,n);
}

数组模拟栈实现:

#include
int conversion(int a,int n){
    int q[100];//模拟栈
    int t=0,w=0;//模拟指针
    while(a){
        q[w++]=a%n;
        a/=n;
    }
    while(w){
        printf("%d",q[--w]);
    }
}
int main(){
    int a,n;
    scanf("%d%d",&a,&n);
    conversion(a,n);
}

C++(STL)实现

/******
author:  1900
language: C++
******/
#include
#include

#include

using namespace std;
int conversion(int a,int n){
    stack<int> q;
    while(a){
        q.push(a%n);
        a=a/n;
    }
    while(!q.empty()){
        cout<<q.top();
        q.pop();
    }
    return 0;
}
int main(){
    int a;
    cin>>a;
    conversion(a,8);
}

5、括号匹配

注意:括号是字符型数据

#include
#include
#include
#define Init_size 100
#define Increment 10

typedef struct{
    int *base;
    int *top;
    int StackSize;
}SqStack;

int InitStack(SqStack *S){//初始化
    S->base=(int *)malloc(Init_size*sizeof(char));
    if(!S->base) return -1;
    S->top=S->base;
    S->StackSize=Init_size;
    return 0;
}
int Push(SqStack *S,char e){//入栈
    if(S->top-S->base>=S->StackSize){//如果空间不够 增加空间
        S->base=(int *)realloc(S->base,(S->StackSize+Increment)*sizeof(int));
        if(!S->base) return -1;
        S->top=S->base+S->StackSize;
        S->StackSize+=Increment;
    }
    *(S->top)=e;
    S->top++;
    return 0;
}
int Pop(SqStack *S,char *e){//弹栈
    if(S->top==S->base)return -1;
    S->top--;
    *e=*(S->top);
    return 0;
}

int main(){
    SqStack S;
    InitStack(&S);
    
    char a[100];
    scanf("%s",a);
    int l=strlen(a);
    char e;
    for(int i=0;i<l;i++){
        if(a[i]=='('||a[i]=='['||a[i]=='{'){
            Push(&S,a[i]);
        }
        else{
            if(a[i]==')'&&*(S.top-1)=='('){
                Pop(&S,&e);
            }
            else if(a[i]==']'&&*(S.top-1)=='['){
                Pop(&S,&e);
            }
            else if(a[i]=='}'&&*(S.top-1)=='{'){
                Pop(&S,&e);
            }
        }
    }
    if(S.top==S.base) printf("Yes\n");
    else printf("No\n");
}

6、行编辑程序

章节3.1和3.2----栈的表示、实现和应用_第3张图片

#include
#include
#include
#define Init_size 100
#define Increment 10

typedef struct{
    int *base;
    int *top;
    int StackSize;
}SqStack;

int InitStack(SqStack *S){//初始化
    S->base=(int *)malloc(Init_size*sizeof(char));
    if(!S->base) return -1;
    S->top=S->base;
    S->StackSize=Init_size;
    return 0;
}
int Push(SqStack *S,char e){//入栈
    if(S->top-S->base>=S->StackSize){//如果空间不够 增加空间
        S->base=(int *)realloc(S->base,(S->StackSize+Increment)*sizeof(int));
        if(!S->base) return -1;
        S->top=S->base+S->StackSize;
        S->StackSize+=Increment;
    }
    *(S->top)=e;
    S->top++;
    return 0;
}
int Pop(SqStack *S,char *e){//弹栈
    if(S->top==S->base)return -1;
    S->top--;
    *e=*(S->top);
    return 0;
}
int LTraverse(SqStack S){
    while(S.base!=S.top){
        printf("%c",*(S.base));
        S.base++;
    }
    printf("\n");
}
int main(){
    char a[100];
    while(scanf("%s",a)!=EOF){
        SqStack S;
        InitStack(&S);
        int l=strlen(a);
        char e;
        for(int i=0;i<l;i++){
            if(a[i]=='#'){
                Pop(&S,&e);
            }
            else if(a[i]=='@'){
                S.top=S.base;//清空栈
            }
            else{
                Push(&S,a[i]);
            }
        }
        LTraverse(S);//正序遍历整个栈
    }
}

7、迷宫求解

关于这个迷宫求解,建议后边学了图之后,再回过头来写,会更明白些
这里贴出一个我之前学的时候写的
两种写法:
迷宫求解解法详解

8、表达式求值

关于最后这三个问题,我先更新下边的东西,这个回过头第二遍的时候再写吧,我太懒了,要跟不上进度了。。。/大哭

9、斐波那契数列

10、汉诺塔问题

你可能感兴趣的:(数据结构(严蔚敏版))