数据结构和算法(压缩矩阵和队列模拟)

具体思路和分析放在末尾
稀疏矩阵的处理方法是:

1.记录矩阵一共有几行几列,有多少个不同的值。
2.把具有不同值的元素的行列和值记录都在一个小规模的矩阵中,从而缩小程序的规模。

原始矩阵转换稀疏矩阵的思路:
1.遍历原始的二维数组,得到有效数据的个数sum
2.根据sum就可以创建稀疏矩阵sparseArr int[sum+1][3]
3.将二维数组的有效数据存入稀疏矩阵

稀疏矩阵转原始矩阵的思路:
1.先读取稀疏矩阵的第一行,根据第一行的数据,创建原始矩阵,
2.再读取稀疏矩阵后几行的数据,并赋值 给原始的二维矩阵即可

稀疏矩阵格式:

	row col number
1	...
2	...
3	...
队列介绍:

队列是一个有序列表,可以用数组或者是链表来实现
遵循先入先出的原则

数组模拟队列:

1.队列本身是有序列表,若使用数组的结构来存储队列的数据,则需要设置一个最大值maxSize
2.因为队列的输出、输入是分别从数组的前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,front会随着数据输出而改变,而rear则是随着数据输入而改变

我们将数据存入队列需要有两个步骤
1.将尾指针往后移:rear+1,当front == rear【空】
2.若尾指针rear小于队列的最大下标maxSize-1,则将数据存入rear所指的数据元素中,否则无法存入数据,rear = maxSize-1【队列满】
front的值和rear的值初始都为-1,
指针含义:
front指向数组数据的前一个空间
rear指向数组数据的最后一个元素
数组需要的功能:

是否为空
是否为满
添元素:条件(判断是否满)
取元素:条件(判断索引是否在范围内)
遍历数组:条件(判断是否空)
获取队列头部的值:(判断是否为空)

但如果使用数组实现,则需要实现环型队列,否则数组是能使用一次,不能复用,可以使用 % 取模的方式

复用思路如下:

1.将front变量的含义做一个调整,front就指向队列的第一个元素,也就是说arr[front]就是队列的第一个元素,front的初始值 = 0
2.将rear变量的含义想做一个调整,rear指向队列的最后一个元素的后一个位置,因为希望空出一个空间作为约定,rear的初始值 = 0
3.当队列满时,条件时(rear + 1) % maxSize = front 【满】【队列满公式思路解析
4.队列为空的条件 rear = front 【空】
5.队列中的有效的数据的个数 = (rear + maxSize - front)%maxSize 【有效数据个数公式思路解析

接下来适用链表实现

链表模拟队列(单向链表):

链表使用节点的方式进行存储的
链表的节点不一定连续存储
每个节点包含data域和next域:指向下一个节点
链表分为带有头节点的和不带有头节点的

以下使用带头节点的实现:

单向链表重要的应用:

增删改查

head节点的作用:

1.不存放具体的数据
2.作用时表示单链表的头部

每个节点的结构:

class Node{
	int no;	//节点的编号(非必要)
	String nickName; //昵称(非必要)
	String name;	//节点的数据(必要)
	Node next;	//指向下一个节点的引用(必要)
}

接下来创建链表管理类,基本功能包含:

初始化head节点,该节点不能变化
方法1:添加元素:直接添加在末尾
方法2:遍历元素:条件(判断是否为空,遍历时不用把头节点输出),通过辅助变量

对链表功能的增加要求:

按照编号插入数据

按照编号的顺序添加思路(不考虑重复问题):

1.首先找到新添加的节点的位置(指针),通过遍历来搞定,查找的位置为添加位置的前一个节点【位置查找思路
2.新的节点的next = temp.next
3.将temp.next = 新的节点

修改链表信息思路(参数为newNode):

使用temp利用newNode的编号定位到位置,修改信息即可。

从单链表中删除一个节点的思路:(参数为编号int)

1.我们先找到需要删除的这个节点的前一个节点temp
2.temp.next = temp.next.next
3.被删除的节点,将不会有其他引用指向,会被垃圾回收机制回收

面试题目:

1.求单链表中有效节点的个数【遍历即可】
2.查找单链表中倒数第k个节点【解题思路
3.反转单链表【解题思路
4.从尾到头打印单链表【方式1:反向遍历,方式2:栈(推荐)】
5.合并两个有序单链表,合并之后依然有序【个人解题思路


队列满公式思路解析:

如果要预留空间,则maxSize = 8,可用空间为7
rear下标紧跟在front下标后面即表示满,只要rear + 1 = front即可,如果+1后下标大于maxSize,则取模即可。
最后公式统一即为:(rear + 1) % maxSize = front :

在这里插入图片描述

有效数据个数公式思路解析:

假设数组maxSize = 8
如果rear在front后面:
情况一
这种情况很好算,按照刚才的约定,rear中没有数据,所以有效数据个数为rear - front = 1 - 0 =1
所以初步公式为rear - front
接下来换一种情况:
front的下标比rear大:
情况二
如果这种情况,使用rear - front,就会得到负数,不符合情况
这里要思考一下,数组指针变化的过程:
在队列数据增加和取出时,rear不停向后移动,而front只能紧随其后,如果front指向了5并取出了数据,则暗示rear之前就经过5了并存了数据。如上图,front指向了7,暗示rear也曾指向7。可以推算出,若到达上图的状态,rear至少绕了数组一圈,front才能到达7,即rear至少从0移动了9次(1 + 8 = 1 + maxSize)到1,front至少从0移动了7次(即图中的位置)到7,次数相减,即可得到有效个数:
在这里插入图片描述
可得公式:rear + maxSize - front
但是如此一来,rear下标比front大的时候就不能使用了,就会超出maxSize范围:
难道要用if-else对比rear和front的大小选择公式?
其实
这时取个模就可以解决问题:
(rear + maxSize - front) % maxSize 等价于
如果rear > front:
rear + maxSize - front就会大于maxSize,取个模刚好就会减回来
如果rear < front:
rear + maxSize - front就会小于maxSize,取模不会对结果造成影响

有以上思路,就可以模拟环型数组。

位置查找思路

如何找到添加的位置:(临时Node为temp,插入Node为insertNode)
如果temp指向的元素的下一个元素的编号大于insertNode,则insertNode将插入在temp指向元素的后面,如果不大于,则指针后移,如果等于,则表示元素已经存在,直接退出。利用这种方法,只要原链表种的数据有序(或为空),该插入方法有效。
在这里插入图片描述
在这里使用头节点的好处就显现出来了,如果没有头节点,第一个节点就有数据,则插入数据到头部的操作就必须独立出来,而不能复用上述的方法。

如下节点插入到头部:
蓝色为第一步操作
红色为第二步操作
灰色为失效指针
绿色为不变指针
在这里插入图片描述

按照以上思路,每次temp都要和下一个元素比较且temp的值小于该元素才有可能后移,就能保证temp移动后指向的元素编号必然小于insertNode的编号。
如果指针遍历到末尾都没有停下,说明在链表中的所有数据都小于insertNode的编号,即插入位置为末尾。

倒数节点思路:

1.方法接收head节点,同时接收一个index
2.index表示倒数第几个链表
3.先把链表从头到尾遍历,得到链表总的长度length
4.再将链表指针从第一个数据(不是头节点)向后移动length-index次,注意先判断每个数据的有效范围,index>=0,length>=index,是否链表为空

反转思路:

1.先定义一个节点
2.从头到尾遍历原来的链表,每遍历一个节点,就将其取出,并放在新的链表的最前端
3.原来的链表的head.next最后再接上新链表。

取数据时,必须保存取出节点的后一个节点的地址,如果没有保存,整个链表都会丢失,所以需要一个保存取出节点地址的临时指针

解题思路分析:

我们的目标是将链表反转,由于是单链表,遍历为单向,所以思路是在遍历链表时,将遍历到的数据块一个一个连到新链表的头部,如果直接将数据插入到到新链表头上时,数据链就会断裂丢失。

如图:将数据块 2 插入到revers链表头部时,由于是单链表,所以插入后 数据块2 到 数据块3 的链接就会断裂,导致后续数据丢失。
在这里插入图片描述
所以我们需要在移动数据块之前,保存下一个数据块的地址,以保证链接即使断裂不丢失,数据块不丢失:
在这里插入图片描述
移动数据完成后,继续上述操作直到遍历到null

上述插入数据块的步骤同样适用于第一个数据块的插入,这时只要把null看做一个虚拟数据块即可(可被指向,不可主动指向的数据块) :
在这里插入图片描述

个人合并链表解题思路

1.将链表分为list1和list2
2.将list2中的数据取出.保存在变量 no 里。
3.将no与list1中的数据依次比较,如果list1中的节点数据大,则cur2节点插入到该节点前头,插入前要注意使用临时指针保存后续地址,以防链表断裂。
3.如果no比list1中的数据都大,则将在末尾进行插入操作。
4.如果list中有数据和no相等,则退出,并提示失败。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值