单向链表末尾插入一个节点(指向指针的指针该怎样理解)

程序如下:

#include<iostream>
using namespace std;
struct ListNode
{
	int value;
	ListNode* m_pNext;
};
void AddToTail(ListNode** pHead,int value)
{
	ListNode* newNode=new ListNode();
	newNode->value=value;
	newNode->m_pNext=NULL;
	
	if (pHead==NULL)
	{
		return;
	}
	if (*pHead==NULL)
	{
		*pHead=newNode;
		return;
	}
	ListNode* p=*pHead;
	ListNode* q=NULL;
	while (p!=NULL)
	{
		q=p;
		p=p->m_pNext;
	}
	q->m_pNext=newNode;
}
ListNode* CreateLink(int a[],int len)
{
	ListNode* Head=NULL,*q=NULL;
	for (int i = 0; i < len; i++)
	{
		ListNode* pNew=new ListNode();
		pNew->value=a[i];
		pNew->m_pNext=NULL;
		if (Head==NULL)
		{
			Head=pNew;
			q=pNew;
		}
		else
		{
			q->m_pNext=pNew;
			q=pNew;
		}
	}
	return Head;
}
void print(ListNode* head)
{
	ListNode* q=head;
	while (q!=NULL)
	{
		cout<<q->value<<endl;
		q=q->m_pNext;
	}
	cout<<endl;
}
int main()
{
	int a[]={1,2,3};
	ListNode* head=CreateLink(a,3);
	print(head);
	AddToTail(&head,4);
	print(head);
	cin.get();
}

所谓链表可以这样理解:链表有多个结构体组成(当然这里说的结构体说的是看上去像结构体),每个结构体可以简化看成由两个部分组成,一个是值,另一个存放一个指针,这个指针指向下一个结构体。

这里着重讲一下void AddToTail(ListNode** pHead,int value)函数,它的第一个形参是一个指向指针的指针,mian中调用它的语句是AddToTail(&head,4)。

我们知道指针传递和引用传递可以起到修改实参的效果,那么这里的head本来就是一个指向ListNode结构体的指针,为啥还要取的指针作为实参?

原因很简答,虽然我们写程序的人知道head是一个指针,但是在编译器看来它就是一个值而已(只是这个值恰巧是指针),那么在AddToTail函数中对head进行赋值操作,肯定不会对函数外的head产生任何影响。只有把&head作为实参传递进AddToTail去,然后在函数中对*head作赋值操作,才会对函数外的head产生影响。

可以这样看,如果实参有&修饰,那就是真正意义上的指针传递,反之则不是。

所以,当对一个空链表使用AddToTail(ListNode* pHead,int value)函数时,执行下面程序段时

if (pHead==NULL)
	{
		pHead=newNode;
		return;
	}

此时的pHead只是一个副本,对它进行任何修改都不会改变链表,因为它只是一个局部变量,出了AddToTail就被释放掉了。

形参取**,只是为了考虑空链表的情况,如果链表不是空的,那么其实用AddToTail(ListNode* pHead,int value)函数也是完全可以的。

一个注意点:->的优先级高于*,所以*pHead->m_pNext并不能取到m_pNext的内存,只有这样写才能达到目的:(*pHead)->m_pNext。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: var middleNode = function (head) { var slow = head; var fast = head; while (fast.next && fast.next.next) { slow = slow.next; fast = fast.next.next; } return slow; } ### 回答2: 要写一个JS代码来找到一个单向链表节点,可以使用快慢指针的方法来解决。快指针每次移动两个节点,慢指针每次移动一个节点,当快指针到达链表尾部时,慢指针所在的位置就是节点。 下面是一个示例的代码实现: ```javascript function findMiddleNode(head) { let slow = head; let fast = head; while (fast && fast.next) { slow = slow.next; fast = fast.next.next; } return slow; } ``` 以上代码,我们使用两个指针`slow`和`fast`初始化为链表的头节点。在每次循环,`slow`指针向后移动一个节点,`fast`指针向后移动两个节点。当`fast`指针到达链表尾部时,`slow`指针正好处于链表间位置。 最后,返回`slow`指针所在的节点,即为链表节点。 以上代码的时间复杂度为O(n/2),其n为链表的长度。 ### 回答3: 首先,我们需要定义一个链表节点的类。每个节点包含一个值和一个指向一个节点指针。代码如下: ```javascript class Node { constructor(value) { this.value = value; this.next = null; } } ``` 然后,我们创建一个单向链表类,其包含几个方法。其一个方法是用于添加节点的`addNode`方法。我们还需要两个指针来追踪链表的头部和节点。代码如下: ```javascript class LinkedList { constructor() { this.head = null; this.mid = null; } addNode(value) { const newNode = new Node(value); if (!this.head) { this.head = newNode; this.mid = newNode; } else { this.mid.next = newNode; this.mid = newNode; } } } ``` 接下来,我们需要编写一个方法来查找链表节点。由于单向链表只能从头部向下遍历,我们可以使用两个指针的方法来实现。一个指针,我们称之为'快指针',将每次移动两个节点,而另一个指针,我们称之为'慢指针',将每次移动一个节点。当快指针到达链表末尾时,慢指针指向节点。最后,我们将节点返回。代码如下: ```javascript findMiddleNode() { let slow = this.head; let fast = this.head; while (fast && fast.next) { slow = slow.next; fast = fast.next.next; } return slow; } } ``` 这样,我们就可以使用上述代码创建一个单向链表,并找到其节点。以下是一个示例: ```javascript const linkedList = new LinkedList(); linkedList.addNode(1); linkedList.addNode(2); linkedList.addNode(3); linkedList.addNode(4); linkedList.addNode(5); const midNode = linkedList.findMiddleNode(); console.log(midNode.value); // 输出3 ``` 这样,我们就成功地使用JavaScript编写了一个单向链表节点的代码。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值