数据结构中的栈和递归以及队列

栈定义:是限定仅在表尾进行插入或删除操作的线性表。表尾 称为栈顶,表头称为栈底,不含元素的空表称为空栈(记得以前学汇编语言的时候,经常讲压栈、出栈当是就不明白,现在算是明白了一点了,栈并不是能把所有不同的东西都压入的,我猜测可能有多种栈,按元素类型来划分,比如有函数栈,变量栈等)。
栈表示和实现:栈也是像线性表一样可以用数组或者链表来实现,大多采用链表。栈的操作就是在添加到链表尾和从链表尾取出。

C语言实现的栈结构

#include <stdio.h>
#include <stdlib.h>

typedef int NodeType;  //重定义一下int这个数据类型,作为节点数据域类型
struct LinkList{
    NodeType i;   //数据域,这里可以使用泛型代替,这样就可以对泛型数据操作了
    struct LinkList* pLast; //指向上一个节点的指针,因为我们是在表尾操作,所以存储前一个的指针;
};

struct Stack{
    int size; //栈中元素个数
    struct LinkList* bottomLink;  //栈结构中的栈底元素
    struct LinkList* topLink;   //栈结构中的栈顶元素
};

void initStack(struct Stack *s) //初始化栈结构
{
    struct LinkList l;
    l.i=0;
    l.pLast=NULL;
    s->size=0;
    s->bottomLink=&l;
    s->topLink=s->bottomLink;
}
//压栈
void push(NodeType node,struct Stack *s)
{
    struct LinkList *m=(struct LinkList *)malloc(sizeof(struct LinkList));  //首先把节点元素给穿件出来
    m->i=node;     //把节点元素中的数据域赋值
    m->pLast=s->topLink;  //把节点元素中指向上一个节点的指针改为栈顶指针
    s->size++;      //栈元素增加
    s->topLink=m; //更新栈顶指针
}
void show(struct Stack *s)
{
    struct LinkList* m=s->topLink; //先取到栈顶元素
    while(m->pLast!=NULL)    //判断是否到达栈底
    {
        printf("%d  |",m->i);  //输出单前节点的元素
        m=m->pLast;            //把m指向上一个节点
    }
    printf("\n");
}
int count(struct Stack *s)
{
    return s->size;  //统计元素个数,用size属性 也是可以的
}
//出栈
int pop(struct Stack *s)    //对于栈来说,移除肯定是指移除栈底元素,不然就不是栈了
{
    struct LinkList* m=s->topLink;    //获取栈顶元素
    s->topLink=m->pLast;     //把上一个节点的指针赋给栈顶元素
    s->size--;   //更改栈中元素个数
    free(m);  //释放开始的栈顶元素
}
int main(void)
{
    struct Stack s; //新建一个栈引用,还没有分配内存
    initStack(&s);
    int i=10;
    for(i;i<20;i++){
        push(i,&s);
    }
    pop(&s);
    pop(&s);
    show(&s);
    printf("%d",s.size);
    return -1;
}

结果:
这里写图片描述

栈结构的应用:进制之间的转换

#define BINARY 2 //二进制数
#define OCTONARY 8 //八进制
#define DECIMAL 10 //十进制
#define HEXAD 16//十六进制

void conversion(unsigned n,int d)
{
    struct Stack s1; //新建一个栈引用,还没有分配内存
    initStack(&s1);
    int m=0;
    switch(d)
    {
    case BINARY:
        m=BINARY;
        break;
    case OCTONARY:
        m=OCTONARY;
        break;
    case DECIMAL:
        m=DECIMAL;
        break;
    case HEXAD:
        m=HEXAD;
        break;
    default:
        printf("你输入的进制不合法!");
        exit(-1);
        break;
    }

    while(n)
    {
        push(n%m,&s1);
        n=n/m;
    }
    while(isEmpty(&s1))
    {
        int i=pop(&s1);
        if(i<9){
            printf("%d",i);
        }else{
            printf("%c",i+55); //应对十六进制的,大于9的数就使用字母表示
        }
    }
    switch(d)
    {
    case BINARY:
        printf(" b\n");
        break;
    case OCTONARY:
        printf(" O\n");
        break;
    case DECIMAL:
        printf(" \n");
        break;
    case HEXAD:
        printf(" H\n");
        break;
    default:
        printf("你输入的进制不合法!");
        exit(-1);
        break;
    }
}
//用法,直接传入需要转换的数和要被转换的进制数就行,这个必须是十进制转换为其他进制
conversion(1348,BINARY);

这里写图片描述

递归:自身调用自身的函数,或者形成循环调用的函数

汉诺塔问题使用递归求解
#include <stdio.h>
long c=0;
void move(char x,int n,char z)
{
    //第n个圆盘从塔座x搬到塔座z
    c++;
}
void hannoi(int n,char x,char y,char z)
{
    if(n==1){
       move(x,1,z);
    }else{
        hannoi(n-1,x,z,y);
        move(x,n,z);
        hannoi(n-1,y,x,z);
    }
}
int main(void)
{
    int n=0;
    printf("请输入圆盘数:");
    scanf("%d",&n);
    hannoi(n,'x','y','z');
    printf("%ld",c);
    return -1;
}

队列

#include <stdio.h>
typedef int QElemType;
struct Node{
    QElemType e;
    struct Node* pNext;
};
struct Queue{
    int zise;
    struct Node* front;
    struct Node* rear;
};

void init(struct Queue *q)
{
    struct Node n;
    n.e=0;
    n.pNext=NULL;
    q->zise=0;   //一定要记住初始化,不然这个size值就不是从0开始计数
    q->front=&n;
    q->rear=&n;
}
/*
    在表尾添加,
*/
void push(QElemType e,struct Queue *q)
{
    struct Node* n=(struct Node*)malloc(sizeof(struct Node));  //先生成一个节点
    n->e=e;   //把这个节点数据域赋值
    n->pNext=NULL; //把这个节点指向下一个节点的值赋值为NULL
    q->rear->pNext=n;  //把尾节点的指向下一个节点的值赋值为新节点
    q->rear=n;   //把当前节点赋值为尾节点
    q->zise++;   //节点元素增加
}
void show(struct Queue *q)
{
    struct Node* n=q->front;
    while(n->pNext!=NULL)
    {
        n=n->pNext;
        printf("%d ",n->e);
    }
    printf("\n");
}
/*
    从表头弹出
*/
int pop(struct Queue *q)
{
    struct Node* n=q->front; //获取表头元素
    int i=n->e; //先把节点中的数据拿出来
    if(n->pNext==NULL)
    {
        printf("队列中没有元素!");
        exit(-1);
    }
    struct Node* m=n->pNext; //把表头之后的那个元素指针拿到
    q->front=m;
    free(n);//释放节点内存
    q->zise--;
    return i;
}
int main(void)
{
    struct Queue q;
    init(&q);
    int i=90;
    for(i;i<100;i++)
    {
        push(i,&q);
    }
    pop(&q);
    pop(&q);
    pop(&q);
    show(&q);
    printf("%d",q.zise);
    return -1;
}

结果:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值