Linked List-2
三、编码技巧
1、遍历链表
先将head
指针赋值给一个局部变量current
:
//return the number of nodes in a list (while-loop version)
int Length(struct node* head)
{
int count = 0;
struct node* current = head;
while (current != NULL)
{
count++;
current = current->next;
}
return count;
}
当然也可以写为:
for (current = head; current != NULL; current = current->next) {}
2、通过传递reference pointer
改变某个指针
看个例子:
//Change the passed in head pointer to be NULL
//Uses a reference pointer to access the caller's memory
void ChangeToNull(struct node** headRef) //takes a pointer to the value of interest
{
*headRef = NULL; //use * to access the value of interest
}
void ChangeCaller()
{
struct node* head1;
struct node* head2;
ChangeToNull(&head1); //use & to compute and pass a pointer to
ChangeToNull(&head2); //the value of interest
//head1 and head2 are NULL at this point
}
这块的思想是和(一)中的Push()
类似。
内存示意图:
3、通过Push()
建立链表(头插法)
这种方式的优点是速度飞快,简单易行,缺点是得到的链表是逆序的:
struct node* AddAtHead()
{
struct node* head = NULL;
for (int i = 1; i < 6; i++)
{
Push(&head, i);
}
//head == {5,4,3,2,1};
return head;
}
4、尾插法建立链表
这种方法需要找到链表最后一个节点,改变其.next
域:
- 插入或者删除节点,需要找到该节点的前一个节点的指针,改变其
.next
域; - 特例:如果涉及第一个节点的操作,那么一定要改变
head
指针。
5、特例+尾插法
如果要构建一个新的链表,那么头节点就要单独处理:
struct node* BuildWithSpecialCase()
{
struct node* head = NULL;
struct node* tail;
//deal with the head node here, and set the tail pointer
Push(&head, 1);
tail = head;
//do all the other nodes using "tail"
for (int i = 2; i < 6; i++)
{
Push(&(tail->next), i); //add node at tail->next
tail = tail->next; //advance tail to point to last node
}
return head; //head == {1,2,3,4,5}
}
6、临时节点建立
struct node* BuildWithDummyNode()
{
struct node dummy; //dummy node is temporarily the first node
struct node* tail = &dummy; //build the list on dummy.next
dummy.next = NULL;
for (int i = 1; i < 6; i++)
{
Push(&(tail->next), i);
tail = tail->next;
}
//the real result list is now in dummy.next
//dummy.next == {1,2,3,4,5}
return dummy.next;
}
7、本地指针建立
struct node* BuildWithLocalRef()
{
struct node* head = NULL;
struct node** lastPtrRef = &head; //start out pointing to the head pointer
for (int i = 1; i < 6; i++)
{
Push(lastPtrRef, i); //add node at the last pointer in the list
//advance to point to the new last pointer
lastPtrRef = &((*lastPtrRef)->next);
}
return head; //head == {1,2,3,4,5}
}
这块可能有些抽象:
1)lastPtrRef
开始指向head
指针,以后指向链表最后一个节点中的.next
域;
2)在最后加上一个节点;
3)让lastPtrRef
指针向后移动,指向最后一个节点的.next
域。 (*lastPtrRef)->next
可以理解为*lastPtrRef
指针指向的节点的next
域。
四、代码示例
1、AppendNode()
- 不使用
Push()
函数:
struct node* AppendNode(struct node** headRef, int num)
{
struct node* current = *headRef;
struct node* newNode;
newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = num;
newNode->next = NULL;
//special case for length 0
if (current == NULL)
{
*headRef = newNode;
}
else
{
//Locate the last node
while (current->next != NULL)
{
current = current->next;
}
current->next = newNode;
}
}
- 使用
Push()
函数:
struct node* AppendNode(struct node** headRef, int num)
{
struct node* current = *headRef;
//special case for length 0
if (current == NULL)
{
Push(headRef, num);
}
else
{
//Locate the last node
while (current->next != NULL)
{
current = current->next;
}
//Build the node after the last node
Push(&(current->next), num);
}
}
2、CopyList
用一个指针遍历原来的链表,两个指针跟踪新生成的链表(一个head
,一个tail
)。
- 不使用
Push()
函数:
struct node* CopyList(struct node* head)
{
struct node* current = head; //used to iterate over the original list
struct node* newList = NULL; //head of the new list
struct node* tail = NULL; //kept pointing to the last node in the new list
while (current != NULL)
{
if (newList == NULL) //special case for the first new node
{
newList = (struct node*)malloc(sizeof(struct node));
newList->data = current->data;
newList->next = NULL;
tail = newList;
}
else
{
tail->next = (struct node*)malloc(sizeof(struct node));
tail = tail->next;
tail->data = current->data;
tail->next = NULL;
}
current = current->next;
}
return newList;
}
内存示意图:
2) 使用Push()
函数:
struct node* CopyList2(struct node* head)
{
struct node* current = head; //used to iterate over the original list
struct node* newList = NULL; //head of the new list
struct node* tail = NULL; //kept pointing to the last node in the new list
while (current != NULL)
{
if (newList == NULL) //special case for the first new node
{
Push(&newList, current->data);
tail = newList;
}
else
{
Push(&(tail->next), current->data); //add each node at the tail
tail = tail->next; //advance the tail to the new last node;
}
current = current->next;
}
return newList;
}
- 使用
Dummy Node
:
struct node* CopyList3(struct node* head)
{
struct node* current = head; //used to iterate over the original list
struct node* tail = NULL; //kept pointing to the last node in the new list
struct node dummy; //build the new list off this dummy node
dummy.next = NULL;
tail = &dummy; //start the tail pointing at the dummy
while (current != NULL)
{
Push(&(tail->next), current->data); //add each node at the tail
tail = tail->next; //advance the tail to the new last node
current = current->next;
}
return dummy.next;
}
- 使用
Local References
:
struct node* CopyList4(struct node* head)
{
struct node* current = head; //used to iterate over the original list
struct node* newList = NULL; //head of the new list
struct node** lastPtr;
lastPtr = &newList; //start off pointing to the head itself
while (current != NULL)
{
Push(lastPtr, current->data); //add each node at the lastPtr
lastPtr = &((*lastPtr)->next); //advance lastPtr
current = current->next;
}
return newList;
}
核心思想是使用lastPtr
指针指向每个节点的.next
域这个指针,而不是指向节点本身。
- 使用
Recursive
:
struct node* CopyList5(struct node* head)
{
struct node* current = head;
if (head == NULL)
return NULL;
else {
struct node* newList = (struct node*)malloc(sizeof(struct node)); //make one node
newList->data = current->data;
newList->next = CopyList5(current->next); //recur for the rest
return newList;
}
}
Linked List-2的更多相关文章
- [LeetCode] Linked List Random Node 链表随机节点
Given a singly linked list, return a random node's value from the linked list. Each node must have t ...
- [LeetCode] Plus One Linked List 链表加一运算
Given a non-negative number represented as a singly linked list of digits, plus one to the number. T ...
- [LeetCode] Odd Even Linked List 奇偶链表
Given a singly linked list, group all odd nodes together followed by the even nodes. Please note her ...
- [LeetCode] Delete Node in a Linked List 删除链表的节点
Write a function to delete a node (except the tail) in a singly linked list, given only access to th ...
- [LeetCode] Palindrome Linked List 回文链表
Given a singly linked list, determine if it is a palindrome. Follow up: Could you do it in O(n) time ...
- [LeetCode] Reverse Linked List 倒置链表
Reverse a singly linked list. click to show more hints. Hint: A linked list can be reversed either i ...
- [LeetCode] Remove Linked List Elements 移除链表元素
Remove all elements from a linked list of integers that have value val. Example Given: 1 --> 2 -- ...
- [LeetCode] Intersection of Two Linked Lists 求两个链表的交点
Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...
- [LeetCode] Linked List Cycle II 单链表中的环之二
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Foll ...
- [LeetCode] Linked List Cycle 单链表中的环
Given a linked list, determine if it has a cycle in it. Follow up: Can you solve it without using ex ...
随机推荐
- python之excel的封装
python之excel的封装 将所有excel的操作都使用面向对象的思维进行封装,即将所有操作都放入一个类中即为封装. 它将excel的处理极大程度的进行了简化操作 封装前需要先处理的操作: 1.在 ...
- python--Django从创建一个项目说起
创建项目 首先进入一个空目录,打开操作命令行,输入: django-admin startproject 项目名称 建立数据库连接 进入项目目录打开settings.py文件,修改以下字段 DATAB ...
- websocket聊天室
目录 websocket方法总结 群聊功能 基于websocket聊天室(版本一) websocket方法总结 # 后端 3个 class ChatConsumer(WebsocketConsumer ...
- python3(二十) module
# 在Python中,一个.py文件就称之为一个模块(Module) # 1.最大的好处是大大提高了代码的可维护性. # 2.可以被其他地方引用 # 3.python内置的模块和来自第三方的模块 # ...
- 在linux中使用mailx发送邮件
[root@ml ~]# yum -y install mailx #安装 [root@ml ~]# vim /etc/mail.rc 在最后一行添加(我这里使用的是qq邮箱): @qq.com ...
- 【python实现卷积神经网络】定义训练和测试过程
代码来源:https://github.com/eriklindernoren/ML-From-Scratch 卷积神经网络中卷积层Conv2D(带stride.padding)的具体实现:https ...
- matlab计算相对功率
1.对脑电数据进行db4四层分解,因为脑电频率是在0-64HZ,分层后如图所示, 细节分量[d1 d2 d3 d4] 近似分量[a4] 重建细节分量和近似分量,然后计算对应频段得相对功率谱,重建出来得 ...
- Python-气象-大气科学-可视化绘图系列(一)——利用xarray读取netCDF文件并画图(代码+示例)
本文原创链接:https:////www.cnblogs.com/zhanling/p/12192978.html 1 import numpy as np import xarray as xr i ...
- 【draft】Team project :Bing dictionary plug-in
课后~ 开会调研开会调研开会~ 在和Bing词典负责人进行了可行性的深入磋商后,我们对本次选题有了更加清晰的认识~困难好多~然而终于敲定了项目内容,我们的目标是这样一款神奇的插件,它帮你记录下新近查询 ...
- Jmeter发送jdbc请求进行大批量造数
创建批量造数脚本,一个简单的结构如下图所示, 1.线程组(10个线程重复运行2次,相当于造20个数) 2.用户定义变量(这是全局变量,用于后面随机筛选用) 3.数据库连接配置 4.计数器(用于主键递增 ...