链表 - Part II

循环链表

相比单链表,循环链表将最后一个结点的指针指向了头结点。

循环链表里没有空指针,所以在判断结束条件时不是判断指针是否为空,而是判断指针是否等于某固定指针。

单链表里,一个结点只能访问它后面的结点,但是循环链表里它能访问所有结点。

双向链表

指针域记录了结点的上一个结点(前驱结点)和下一个节点(后继节点),这样既可以从头结点遍历到尾结点,也可以从尾结点遍历到头结点。

约瑟夫问题:

约瑟夫问题来源于犹太历史学家约瑟夫,他和他的一位朋友与另外三十九名犹太人为了躲避罗马人藏在了一个山洞中,三十九位犹太人决定宁愿自杀也不能被抓到。他们商议围成一个圈,从某一个人开始数 ,每数到第 3 的人必须自杀然后再从他之后的人继续数。这时候,约瑟夫把朋友和自己安排在了第 16 和 31 的位置,最终,当其它三十九名犹太人都自杀之后,他们两个躲过一劫。

约瑟夫问题可以用循环链表来模拟。删除操作实现方法如下:

  1. 定义一个遍历指针,初始指向 head,并让 head 指向空地址避免操作结束后变为野指针。
  2. 找到遍历指针往后数的第 n 次所指向的结点。
  3. 输出该结点的数据,更新遍历指针,然后删除该结点。
  4. 重复操作 2 直至只剩下最后一个结点。
  5. 输出最后一个结点并删除。

相比之前的单链表类,要实现循环链表类,需要修改其中一些操作。

首先是修改析构函数:

可以将循环链表拆成单链表,其中,让head指向空指针,让它做为链表中的最后一个结点。

 1 ~LinkedList() {
 2         if (head == NULL) {
 3             return;
 4         }
 5         Node<Type> *current_node = head -> next;
 6         head -> next = NULL;
 7         while (current_node != NULL) {
 8             Node<Type> *delete_node = current_node;
 9             current_node = current_node->next;
10             delete delete_node;
11         }
12     }

然后修改插入函数。

 1 void insert(Node<Type> *node, int index) {
 2 // 当head为空时,让node直接赋值给头结点,同时让它指向自己
 3         if (head == NULL) {
 4             if (index != 0) {
 5                 return;
 6             }
 7             head = node;
 8             head -> next = head;
 9             return;
10         }
11 // 当index为0,结点要成为第一个结点时,结点首先指向头结点的下一个结点,然后头结点的下一位再指向结点。
12 // 注意!!,在循环链表中,head其实该视为尾结点,head -> next才该被视为头结点
13         if (index == 0) {
14             node -> next = head -> next;
15             head -> next = node;
16             return;
17         }
18         Node<Type> * current_node = head -> next;
19         int count = 0;
20 // 寻找目标位置的前一个节点,并且如果遍历到最后一个结点(即head)立刻结束循环
21         while (current_node  != head && count < index - 1) {
22             current_node = current_node->next;
23             count++;
24         }
25         if (count == index - 1) {
26             node->next = current_node->next;
27             current_node->next = node;
28         }
29 // 如果结点插入后成了最后一个结点:(head) -> (node) -> (head -> next),则让它成为head
30         if (node == head -> next) {
31             head = node;
32         }
33     }

接下来实现依次输出被约瑟夫环删除的元素直到只剩最后一个元素的函数

 1 output_josephus()
 2 void output_josephus(int m) {
 3     Node<Type> * current_node = head;
 4     head = NULL;// head指向一个空地址,因为方法执行完后链表将成为空链表,要防止head成为野指针
 5     while (current_node -> next != current_node) {
 6         for (int i = 1; i < m; i++) {
 7             current_node = current_node -> next;
 8         }
 9         cout << current_node -> next -> data <<  " ";
10         Node<Type> * delete_node = current_node -> next;
11         current_node -> next = current_node -> next -> next;
12         delete delete_node;
13     }
14     cout << current_node -> data << endl;
15     delete current_node;
16 }
时间: 2024-10-17 00:04:31

链表 - Part II的相关文章

LeetCode OJ:Remove Duplicates from Sorted List II(链表去重II)

Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. For example,Given 1->2->3->3->4->4->5, return 1->2->5.Given 1->1->1->2->3, return 2->3.

[LeetCode系列]翻转链表问题II

给定一个链表和两个整数m, n, 翻转链表第m个节点到第n个节点(从1开始计数). 如, 给定链表: 1->2->3->4->5->NULL, 以及 m = 2, n = 4. 返回 1->4->3->2->5->NULL. 假定m和n满足约束条件: 1 ≤ m ≤ n ≤ 链表长度. 注意: 不能使用额外空间, 且只能遍历链表一次. 算法思路: 翻转的过程可以分解成3步: 把相邻的节点的指向关系倒置; 即 1->2<-3<-4

2017校招常考算法题归纳&amp;典型题目汇总

2017校招即将来临,我们为大家整理了2017校招的常考算法类型,以及对应的典型题目. 另附参考答案地址:http://www.jiuzhang.com/solution/ 数学 尾部的零 斐波纳契数列 x的平方根 x的平方根 2 大整数乘法 骰子求和 最多有多少个点在一条直线上 超级丑数 比特位操作 将整数A转换为B 更新二进制位 二进制表示 O(1)时间检测2的幂次 二进制中有多少个1 动态规划 编辑距离 正则表达式匹配 交叉字符串 乘积最大子序列 二叉树中的最大路径和 不同的路径 通配符匹

聚类算法kmeans

1. 聚类问题 所谓聚类问题,就是给定一个元素集合D,其中每个元素具有n个可观察属性,使用某种算法将D划分成k个子集,要求每个子集内部的元素之间相异度尽可能低,而不同子集的元素相异度尽可能高. 2. K-均值算法简介 k-means算法,也被称为k-平均或k-均值,是一种得到最广泛使用的聚类算法. 它是将各个聚类子集内的所有数据样本的均值作为该聚类的代表点, 算法的主要思想 是通过迭代过程把数据集划分为不同的类别,使得评价聚类性能的准则函数达到最优,从而使生成的每个聚类内紧凑,类间独立.这一算法

校招的常考算法类型以及对应的典型题目

数学 尾部的零斐波纳契数列x的平方根x的平方根2大整数乘法骰子求和最多有多少个点在一条直线上超级丑数 比特位操作 将整数A转换为B更新二进制位二进制表示O(1)时间检测2的幂次二进制中有多少个1 动态规划 编辑距离正则表达式匹配交叉字符串乘积最大子序列二叉树中的最大路径和不同的路径通配符匹配 堆 滑动窗口的中位数数据流中位数最高频的K个单词接雨水堆化排序矩阵中的从小到大第k个数 二叉树 二叉树中序遍历二叉树的序列化和反序列化子树最近公共祖先二叉树的层次遍历将二叉树拆成链表在二叉查找树中插入节点

leetcode——Reverse Linked List II 选择链表中部分节点逆序(AC)

Reverse a linked list from position m to n. Do it in-place and in one-pass. For example: Given 1->2->3->4->5->NULL, m = 2 and n = 4, return 1->4->3->2->5->NULL. Note: Given m, n satisfy the following condition: 1 ≤ m ≤ n ≤ le

Leetcode 链表 Linked List Cycle II

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie Linked List Cycle II Total Accepted: 20444 Total Submissions: 66195My Submissions Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Follow up: Can you

Leetcode:Reverse Linked List II 反转链表区间

Reverse Linked List II Reverse a linked list from position m to n. Do it in-place and in one-pass. For example:Given   1->2->3->4->5->NULL,  m = 2 and n = 4, return  1->4->3->2->5->NULL. Note:Given m, n satisfy the following

LeetCode之“链表”:Linked List Cycle &amp;&amp; Linked List Cycle II

1. Linked List Cycle 题目链接 题目要求: Given a linked list, determine if it has a cycle in it. Follow up: Can you solve it without using extra space? 刚看到这道题,很容易写出下边的程序: 1 bool hasCycle(ListNode *head) { 2 ListNode *a = head, *b = head; 3 while(a) 4 { 5 b =