指针的指针

从交换两个数谈起。一般地,如果我们要交换两个数,不论是是使用指针,还是直接使用对应的类型。要么引入一个临时变量,要么进行异或操作,或者说进行加法运算。不过,当使用指针时,我们还可以这么做:交换两个指针的指向,而不是直接交换指针所指向的值。
代码如下:

#include<iostream>
using namespace std;
void swap(int **ptr1, int **ptr2) {
    int *temp = *ptr1;
    *ptr1 = *ptr2;
    *ptr2 = temp;
}
int main() {
    int a = 5;
    int b = 8;
    int* ptr1 = &a;
    int *ptr2 = &b;
    cout <<"    "<< ptr1 << " " << ptr2 << endl;
    swap(&ptr1, &ptr2);
    cout << "After swapping ----------" << endl;
    cout <<"    "<< ptr1 << " " << ptr2 << endl;
    cin.get();
}

根据输出可以看到,在没有交换指针指向时,ptr1指向0x00EFFC98,而ptr2指向0x00EFFC8C,在交换指针指向后,ptr1指向0x00EFFC8C,ptr2指向了0x00EFFC98。
指针交换指向

除此之外,指针的指针在队列方面还有非常便捷的应用,而这也是Linus所推崇的使用指针的方式来遍历队列,可以参考这里This persons don’t understand pointers。在这篇文章里,Linus认为正确使用指针遍历队列的做法应该是使用指针的指针,而不是按照一般教科书那样再使用一个prev指针。另外,还可以看看StackoverFlow的解释:Using pointers to remove itme from a singly-linked list
在这里,贴一下我Stackoverlfow上排名第一答案的理解,先把Linus版本代码贴一下:

  /* LINUS VERSION */
  ll **pp = &list_head;
  while (*pp != NULL) {
    if ((*pp)->value == REMOVE) {
      (*pp) = (*pp)->next;
    } else {
      pp = &((*pp)->next);
    }
    //这里没有free操作

首先,执行语句:
pp = &list_head;
然后,随着不断的遍历链表,你就通过下面这个语句来移动“游标”
pp = &((*pp)->next);
然后,原作者说,通过这样的方式,你就始终可以追踪你是从哪里来的,并且修改其实的指针(This way, you always keep track of the point where “you come from” and can modify the pointer living there.)
对于,我贴上我自己的理解,先上张图:
图解
比如,对于链表1->2->3->4->5。那么从图可以看出,节点1的地址为10(省略前部分),节点2的地址为30。。剩下的可以自己看head所在的地址。在循环还未开始前,*pp的值是节点1的值,而这时pp的值不重要。随着循环不断的进行,执行了语句:
pp=&((*pp)->next)
这样,就把节点的next指针的地址赋给了pp,而next指针指向的是下一个节点,所以*pp的就是下一个节点的地址。因为,pp的值就可以表示当前你所在的位置(除了第一个值除外),而*pp的值这反映了当前要处理哪个节点。所以,当找到要删除的节点,就可以执行语句:
*pp = entry->next
执行这条语句的结果就是把next指向当前节点的下一个节点,另外pp的值反映这个next指针的位置。于是,当前节点就被顺利的删除了。

最后,看看该如何解决这道LeetCode:Delete Node in linked list
这是我的代码:

void deleteNode(ListNode *node) {
    ListNode** p = &node;
    **p = *((*p)->next);
}

和上面不同的是,这里只知道当前需要删除的节点、P和不在尾部的信息,所以我们不能直接把这个节点删除掉,而是先把P的下一个节点的值赋给P,接着把P的下一个节点删除掉(利用了节点不在尾部的信息)。
另外,其实完全可以不需要再申明一个指针p,而只利用节点node

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值