个人学习回顾,欢迎学习交流。
java中有大量已经封装好的链表,例如:linkedList、linkedHashSet等等,当我经常使用这些封装类后,我对指针 *** 作就愈来愈不敏感,导致刷leetcode时,关于指针 *** 作的题总是摸不着头脑。所以即使在学java,python,我们仍然要对指针有较好的掌握。
一、指针与地址1、指针和地址最大的区别就是指针是有类型的,地址是没有类型的。我们当然可以通过绝对地址的方式找到函数和数据,但是地址是没有类型的,不能对地址进行算术 *** 作,在涉及诸如数组等 *** 作时就不能通过地址的自增和自减来访问数组的各个变量。
2、指针是由地址和类型两部分构成的,指向数据的指针不仅记录该数据的在内存中的存放的地址,还记录该数据的类型,即在内存中占用几个字节,这是地址所不具有的。
简单来说,我们使用的指针实际上是用来保存或着说是指向地址空间的。指针更像是地址空间的导航标识,它会告诉我们的数据存放的地址以及该数据的数据类型。
二、指针与链表说到链表我们就不能不想到指针,两者就是一体的。且链表是有序的。
我们初学时都常学到的链表有两大类,即单链表和双链表。
单链表就是只有后继没有前驱,即只有指向下一个元素节点的指针,没有指向上一个元素节点的指针。
双链表就是既有前驱也有后继。
三、个人对指针的理解当我们对地址 *** 作时,即修改指针时,实际是 *** 作当前指针的变化改变地址之间的结构,所以无论我们是对 指针1 本身 *** 作,还是将 指针1 赋值给另一个 指针2 ,然后 *** 作 指针2 。这两种情况都是在 *** 作同一个地址,都会改变了地址结构。但值得注意的是,我们将 指针1 赋值给另一个 指针2时,然后 *** 作 指针2,我们是改变了 指针1 所指向的地址结构,但却没有改变 指针1 ,即 指针1 不会因 指针2 的改变而发生改变。
四、例题举例剑指 Offer 18. 删除链表的节点
题解:
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
示例 1:
输入: head = [4,5,1,9], val = 5 输出: [4,1,9] 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
解法:
只需注意一点,在赋值时,因为这是一个链表所以head是一个地址,我们将head赋值给tmpNode时,当我们对地址 *** 作时,实际是 *** 作当前指针的变化,所以tmpNode和cache的变化也会改变head所属链表的结构变化,但我们有没有改变head头指针所以,头指针不发生变化,变化的只是链表结构。
class Solution { public ListNode deleteNode(ListNode head, int val) { ListNode tmpNode = head,cache = head.next; if (head.val == val){ head = head.next; return head; } while(cache != null && cache.val != val){ tmpNode = cache; cache = cache.next; } if (cache != null){ tmpNode.next = cache.next; } return head; } }
也有另一种方法,就是设置哑节点。哑节点的主要目的是让链表中的每一个节点都有前驱,这样我们在 *** 作时就无需过多考虑特殊情况。
class Solution { public ListNode deleteNode(ListNode head, int val) { ListNode temp = new ListNode(0); temp.next = head; head = temp; while(temp.next!=null){ if(temp.next.val==val){ temp.next = temp.next.next; return head.next; } temp = temp.next; } return head.next; } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)