线性结构基础总结
一:线性结构的存储
1)连续存储(数组)
什么叫做数组:元素类型相同、大小相等
2)离散存储(链表)
树和图的基础
二:链表
1. 什么叫链表
n个结点离散分配,彼此通过指针相连。每个结点只有一个前驱结点,各个结点只有一个后驱结点(首结点没有前驱结点,尾结点没有后驱结点)
2. 专业术语
首节点:第一个有效节点
尾节点:最后一个有效节点
头节点:在首节点前面,不存放数据,它指向首节点,目的是简化算法,并不存放有效数据
头指针:指向头结点的指针变量
尾节点:指向尾结点的指针变量
2)链表的分类
单链表:
双链表:每个节点有两个指针域(可以同时指向前后结点)
循环链表:能通过任何结点找到其他所有的结点
非循环链表:
3)链表的算法
遍历、查找、清空、销毁、求长度、排序、删除。
删除结点:
错: p->pNext=p->pNext->pNext; 会导致内存泄露
对: r=p->pNext; p->pNext=p->pNext->pNext; free(r); 要free() ,注意r本身没有free()
添加结点: p ,q 分别为一个节点的地址 比如:struct Stu * p ;
第一种方法:r=p->pNext ; p->pNext=q; q->pNext=r;
第二种方法:q->pNext = p->pNext; p->pNext=q;
三:线性结构的常见应用:栈和队列
1)栈的概念
定义:一种可以实现“先进后出”的存储结构,栈类似于箱子
分类: 动态栈(链表),静态栈
算法: 出栈,压栈
2)队列的概念
定义:先进先出可以实现“先进先出” 的存储结构
分类:
链式队列 --- 链表实现
静态队列 ---- 数组实现(静态队列必须通常是循环队列)
3)循环队列的理解
1.静态队列为什么必须是循环队列
front永远指向第一个元素 rear永远指向最后一个元素的下一个元素,为了便于存储结构的操作(自己体会)
用传统的数组队列:无论入队还是出队f ront或者rear都是增的(故用循环队列,免去空间浪费)
没有越界:地址(r)可以指向数组的最后一个有效元素的下一个元素,但是不可以使用它
循环队列(解决方法):尾部加一,可以指向首部
2.循环队列需要几个参数来确定(两个参数)
3.循环队列的各个参数的意义
(1)队列的初始化
Front 和 rear 都是零位置
(2)队列非空
Front代表的是队列的第一个元素
Rear代表的是最后一个元素的下一个元素
(3)队列空
Front和 rear的 值是相等的,但不一定是零位置
(4)循环队列入队的为算法讲解:
1)元素值放在rear的位置
2)错误的写法:rear = rear+1
正确的写法:rear = (rear+1)%(数组的长度)
(5)循环队列的出队的为算法的讲解
Front = (front+1)%(array.Length)
(6)如何判断队列是否为空
如果front与rear的值相等 ,那么队列为空
(7)如何判断队列是否为满:Front与rear的大小关系没有规律
数组里面都存放了元素,那么front与rear指向同一元素,不能判断是满还是空
解决办法:
多定义一个参数,保存元素的个数
数组少放一个元素,不存在front与rear相等的情况,n-1就是满(用第二种方法判断:当front 和(rear+1)%array.Length 相等的时候)
4.队列的算法: 入队和出队
5.队列的应用: 所有和时间有关的操作(操作系统)
四: 递归
1)什么是递归:一个函数直接或者间接的调用自己
2)A如何调用B函数,当函数调用另一个函数之前,系统要完成三件事:
1——函数A将所有实参,返回地址(下个语句的地址)等信息传递给被调函数保存
2——被调函数为被调函数分配存储区域
3——将控制转移到被调函数的入口(开始执行被调函数)
3)在被调函数B返回调用函数A之前,系统要完成三件事:
1——保存被调函数B的计算结果 (返回值产生拷贝,保存在临时的地方)
2——释放被调函数B的数据区(静态局部变量,不包括动态创建的)
3——依照被调函数B返回值的返回地址,控制传回调用函数A
4)嵌套调用
调用后调用先返回,函数退出正在运行的函数,注意函数调用与栈之间的关系。
5)递归满足的三个条件
必须有一个明确的终止条件
函数处理的数据规模必须递减
1 ,1+2+3+4.....100
2. 汉诺塔
3. 走迷宫
4. 求阶乘