数据结构 ③栈与队列

一、栈
1.定义:栈是限定仅在表尾进行插入和删除操作的线性表;

栈也是一种线性表,即一对一的关系
其重点在于队尾,注意利用这个点明白其实际应用。
相关概念:

  • 栈顶
  • 栈底
  • 入栈/压栈/进栈
  • 出栈/弹栈
  • 空栈:不含任何数据元素
2.特点:

后进先出
只在队尾添加删除

3.储存方式

声明时两种方式都只用声明top的值

① 顺序:数组

  • 用数列队尾的值当作top的值(下标为0的值和栈底的值性质类似,很少移动,而队尾可以变化比较常见,故选取队尾的值为top值)

  • top==0时即代表栈顶指针指向已经储存了的一个元素,故top==-1代表该数组为空

  • 算法

    • 声明
    typedef struct {
    	int data[maxsize];
    	int top;    //只用加上top的值即可;
    }Sqstack;
    
    • 入栈出栈时检验top的值,并注意更改top的值
  • 两栈共享空间:当两个栈的数据类型一样,空间需求有相反关系,可以用一个数组储存两个栈的内容。即用一个数组的头尾分别储存两个栈的栈底。
    这种方式可以更合理的利用空间。

② 链式:链栈

  • 栈顶通常为头指针,空栈时top==NULL
  • 算法
    • 声明
      用两个结构体,一个和普通链表一样,另一个用来储存top值;

      第一个结构体在添加和删除数据的时候会申请空间重新建立和删除;第二个结构体始终不变,整个函数中就用这一个结构体,在主程序中为其申请空间,且只申请一次;

    typedef struct stacknode{
    	int data;
    	struct stacknode *next;
    }Stacknode,*linkstackptr;    //定义头指针;
    
    typedef struct linkstack{
    	linkstackptr top;     //用来记录栈顶的值,注意这里申请为linkstackptr类型的值;
    	int count;     //用来记录链表的数量
    }Linkstack;
    
    • 入栈时用头插法
    • 入栈出栈时修改top,count,及指针的值;
4.实例
  • 斐波拉契数列
    迭代法:用循环解决
    递归法:递归函数,自己调用自己,程序能更加简洁

    //递归法
    int Fbi(int i){    //递归函数
     if(i<2){
     	return i==0?0:1;
     }
     return Fbi(i-1)+Fbi(i-2);
     }
     
    int main()
    {
    	int n;
    	int i;
    	scanf("%d",&n);
    	for(i=0;i<n;i++){
    		printf("%d",Fbi(i));   //此处我的设定是打印指定的斐波拉契列;
    	}
    	return 0;
    }
    

    递归函数一定要注意有没有递归终止条件;

  • 四则运算-后缀表示法(逆波兰法)

    这部分内容在离散数学部分也有涉及,后缀表示法的求法有两种,一种是直接利用栈的原理,将中缀表示法(即我们所见的一般表示法)直接转化为后缀表示法,另一种是利用树的结构

二、队列
1.定义:只在队头删除,在队尾添加的线性表
2.特点:

先进先出
用front指向头,rear指向尾

3.储存方式:

①顺序:数组

  • 通常用front指向第零个元素(数组中储存的第一个值),用rear指向数组的最后一个值的下一位,数组满时始终有一位为空,即循环队列
    (不直接指向最后一位:数组满时front == rear,和数组空的条件一样,不好分辨)
    (如果指向最后一位,也可以单独用一个变量来表示数组是否为空)

  • 判别条件:

    • 队列是否为满:front在尾,rear在首或者front == rear+1
      将rear和front整合为一个问题:(rear+1)%Queuesize == front
    • 队列长度:(rear-front+Queuesize)%Queuesize
  • 算法

    • 声明
    typedef strcut{
    	int [Queuesize];
    	int front;
    	int rear;
    }
    
    • 插入时检验是否为满,删除时检验是否为空;

②链式:链队列

  • 链队列一般都有头结点

  • 通常用front指向头结点,rear指向尾结点

  • 链表一般不存在链表为满的情况,因为其增加一个元素始终是在内存中申请空间

  • 算法

    • 声明:两个结构体

      和上面的栈的声明类似,一个用于每次储存新的数据,另一个在一个队列中就用这一个。

    typedef struct {
    	int data;
    	struct *next;
    }
    typedef struct {
    	front;
    	rear;
    }
    
    • 插入时使用尾插法
    • 删除时要注意删除到空表的条件是:rear = front + 1
    • 若除了头结点,队列中只有一个元素,删除后将rear指向头结点,即使rear和front相等(方便统一管理)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值