《数据结构》第三章
3.1栈和队列的特点
3.1.1 栈的定义和特点
栈:限定仅在表尾进行插入或删除操作的线性表;
(又称先进先出的线性表)
栈顶:线性表表尾端;
栈底:线性表表头端;
3.1.2 队列的定义和特点
队列:先进先出的线性表;(队尾插入 队头删除)
队尾:允许插入的一端;
队头:允许删除的一端;
3.2案例引入
3.3栈的表示和操作的实现
3.3.1 栈的类型定义
栈的两种定义方式:顺序栈和链栈;
3.3.2 顺序栈的表示和实现
注:base为栈底指针,初始化完成后,栈底指针base始终指向栈底位置,
若base值为NULL,则栈结构不存在;
top为栈顶指针,其初值指向栈底;每当插入新的栈顶元素时,指针top增加1;
删除栈顶元素时,指针top减1;
栈空时,top和base的值相等,都指向栈底;栈非空时,top始终指向栈顶元素的上一个位置;
顺序栈:利用顺序存储结构实现的栈,即利用一组地址连续的存储单元依次存放自栈底到
栈顶的数据元素,同时附设指针top只是栈顶元素在顺序表中的位置;
1.初始化
顺序栈的初始化操作就是为顺序栈的基本操作分配一个预定义的数组空间;
顺序栈的初始化:
1.为顺序栈的动态分配一个最大容量为MAXSIZE的数组空间,(s.base = new SElemType [MAXSIZE])
使base指向这段空间的基地址,即栈底;
2.栈顶指针top初始为base;(s.top = s.base)
3.stacksize置为栈的最大容量;(s.stacksize = MAXSIZE)
2.入栈
顺序栈的入栈:
1.判断栈是否满,若满则返回ERROR;
2.将新元素压入栈顶,栈顶指针加1;
3.出栈
出栈的操作是指将栈顶元素删除;
1.判断栈是否空,若空则返回ERROR;
2.栈顶指针减1,栈顶元素出栈;
4.取栈顶元素
当栈非空时,此操作返回当前栈顶元素的值,栈顶指针保持不变;
(return *(s.top - 1))
3.3.3 链栈的表示和实现
栈链:采用链式存储结构实现的栈;
1.初始化
栈链的初始化操作就是构造一个空栈;
(因为没必要设头结点,所以直接将栈顶指针置空即可)
2.入栈
链栈在入栈前不需要判断是否栈满,只需要为入栈元素动态分配一个结点空间;
1.为入栈元素e分配空间,用指针p指向;
2.将新结点数据域置为e;
3.新结点插入栈顶;
4.修改栈顶指针为p;
3.出栈
链栈在出栈前也需要判断是否为空,链栈在出栈后需要释放出栈元素的栈顶空间;
4.取栈顶元素
当栈非空时,取栈顶元素操作返回当前扎你当元素的值;
3.4栈与递归
3.4.1 采用递归算法解决的问题
递归:若在一个函数,过程或者数据结构定义的内部(或间接)出现定义本身的应用,则称其是递归,或者是递归的定义。
1.定义是递归
分治法:分解求解的策略。
满足的要求:
1.能将一个问题转变成一个新问题,而新问题与原问题的解法相同或类似,
不同的仅是处理的对象,并且其处理对象更小且变化有规律。
2.可以通过上述转化而使问题简化;
3.必须有一个明确的递归出口,简称递归的边界;
2.数据结构是递归的
1.p为NULL,递归终止;
2.否则输出p->data,p指向后继结点;
3.4.2 递归过程与递归工作栈
3.4.3 递归算法的效率分析
3.4.4 利用栈将递归转换为非递归的方法
3.5队列的表示和操作的实现
3.5.1 队列的类型定义
3.5.2 循环列表——队列的顺序表示和形式
队列的两种存储表示:顺序表示和链式表示;
队列的顺序存储结构:用一组连续的存储单元存储;
假溢出:队列元素不等于存储元素且 头指针 = 尾指针,不可再插入队尾元素;
解决方法:将顺序队列变为一个环状空间,称为循环队列;
1.初始化
循环队列的初始化操作就是动态分配一个预定义大小为MAXQSIZE的数组空间;
1.为队列分配一个最大容量为MAXQISZE的数组空间,base指向数组空间的首地址;
2.将头指针和尾指针置为0,表示队列为空;
2.求队列长度
对于非循环列表,尾指针和头指针的插值便是队列长度;而对于循环列表,差值可能为负数,
所以需要将差值加上MAXQSIZE,然后与MAXQSIZE求余;
3.入队
入队操作是指再队尾插入一个新元素;
1.判断队列是否满,若满则返回ERROR;
2.将新元素插入队尾;
3.队尾指针加1;
4.出队
出队操作是指将队头元素删除;
1.判断队列是否为空,若空则返回ERROR;
2.保存队头元素;
3.队头元素加1;
5.取队头元素
当队列非空时,此操作返回当前队头元素的值,队头指针保持不变;
(return Q.base[Q.front])
3.5.3 链队列——队列的链式表示和实现
链队列是指采用链式存储结构实现的队列;(通常用单链表表示)
1.初始化
1.生成新结点作为头结点,队头和队尾指针指向此结点;
2.头结点的指针与置空;
2.入队
1.为入队元素分配空间,用p指针指向;
2.将新结点数据域置为e;
3.将新结点插入到队尾;(p->next = NULL; Q.rear -> next = p;)Q.rear为尾指针
4.修改队尾指针为p;(Q.rear = p)
3.出队
1.判断队列是否为空;
2.临时保存队头元素的值,以释放空间;
3.修改头结点的指针域,指向下一个结点;
4.判断出队元素是否为最后一个元素,若是,则将队尾指针重新赋值,指向头结点;
5.释放原队头元素的空间;
注意:在链队列的出队操作中还要考虑当队列中最后一个元素被删后,队尾指针也会丢失,
因此需对队尾指针重新赋值(指向头结点);
4.取队头元素
当队列非空时,此操作返回当前队头的元素值,队头指针保持不变;
(return Q.front ->next->data)