前言:
[toc]
顺序表的优点: 连续物理空间,方便通过下标随机访问 缺点:
基于顺序表的局限性,就设计出了链表
链表是一种在物理存储结构上非顺序非连续的存储结构,数据元素的逻辑结构是通过链表中的指针链接实现的 <img src="https://map--depot.oss-cn-hangzhou.aliyuncs.com/image/202207241009269.png" alt="截屏2022-07-24 10.09.27" style="zoom: 50%;" />
链表的基本结构:
节点/结点:在数据结构中,每一个数据节点/结点对应一个存储单元,节点/结点就是存储单元的地址(比如在链表里,结点就是链表结构体的地址) 注意:
最常见的两种结构:
复制带随机指针的链表 复制一个新的链表,除了要求存储的数据data与原链表一致,还要求链表内每个结点的random指向的相对位置不变 由于链表的结点都是malloc出来的,因此每个结点的地址都是随机的,只能通过相对关系来找到random指向的结点 思路一: 遍历原链表第一遍,创建一个新链表,把data数据复制过去 再用一个指针遍历一遍原链表,每到达一个结点A记录下它在链表中的位置,并跳转到random指向的结点B,再由另一个结点从链表头开始,直到走到random跳转之后的结点,记录下来结点B在链表位置,这样就可以得到结点A和它的random指向的结点B的相对位置关系。再在新链表中根据关系令random指向相应的结点。 最后返回新链表 缺点:过程太繁琐 于是就有了,思路二: 直接在原来链表的基础上创建复制结点,每个复制结点就在原结点后面,然后把下一个原结点连接在复制结点后面
创造拷贝结点,链接到原链表原结点的后面,并复制val的值 方法一:定义一个cur用来遍历原链表,定义一个copy指针用作拷贝 让copy=cur->next , cur->next=copy, cur= copy->next
struct Node *cur = head; while(cur) { struct Node *copy = (struct Node *)malloc(sizeof(struct Node)); copy->val = cur->val; copy->next = cur->next; cur->next = copy; cur = copy->next; }注意这里是对于链表进行的拷贝,而不是简单的进行链表的链接,因此需要构造新的结点再进行拷贝 方法二:定义一个cur用来遍历原链表,一个next来找cur的next,一个copy用作拷贝 有了next就不用在乎拷贝顺序了 next=cur->next, cur-> next=copy, copy->next= next
链接拷贝结点的random copy->random指向前面cur->random->next 以为cur->random的后一个就是它的copy,这样直接就找到了相对位置的copy 如果cur->random指向NULL,copy->random直接指向NULL
struct Node *copy = NULL; cur = head; while(cur) { copy = cur->next; if(cur->random == NULL) { copy->random = NULL; } else { copy->random = cur->random->next; } cur = copy->next; }把copy从原链表中解下来,形成复制链表,把原链表连回去 创建拷贝链表的头指针copyHead还有尾指针copyTail 尾指针是为了尾插结点,头指针是为了定位 创建一个next指针便于再原链表上辅助copy和cur移动 copy将值赋给拷贝链表,cur负责连接原链表 cur = head; struct Node *copyHead = NULL; struct Node *copyTail = NULL; while(cur) { struct Node *copy = cur->next; struct Node *next = copy->next; cur->next = next; if(copyTail == NULL) { copyHead = copyTail = copy; } else { copyTail->next = copy; copyTail = copyTail->next; } cur = next; } return copyHead;
可以看成构建新的链表
>//源代码 struct Node* copyRandomList(struct Node* head) { struct Node *cur = head; //创造拷贝结点,链接到原链表的结点后面,并复制val的值 while(cur) { struct Node *copy = (struct Node *)malloc(sizeof(struct Node)); copy->val = cur->val; copy->next = cur->next; cur->next = copy; cur = copy->next; } //连接拷贝结点的random struct Node *copy = NULL; cur = head; while(cur) { copy = cur->next; if(cur->random == NULL) { copy->random = NULL; } else { copy->random = cur->random->next; } cur = cur->next->next; } //把copy从原链表中解下来,形成复制链表,把原链表连回去 cur = head; struct Node *copyHead = NULL; struct Node *copyTail = NULL; while(cur) { struct Node *copy = cur->next; struct Node *next = copy->next; cur->next = next; if(copyTail == NULL) { copyHead = copyTail = copy; } else { copyTail->next = copy; copyTail = copyTail->next; } cur = next; } return copyHead; }
That’s all, thanks for reading!💐