`
xusulong
  • 浏览: 80961 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

遍历同时删除内容时的哨兵问题

阅读更多

这是我在做rdf的sentence时候遇到的问题,本来以为是个很复杂的问题,最后才发现是一个不起眼的地方酿成的大错。

此问题可以简单示例成如下问题:

找到ArrayList a = {"a", "*", "*", "b", "*", "*", "c"}中为"*"的那些元素,并且将这些元素删除

开始的时候不假思索就写下了下面的代码

错误的写法

public static void guardProblem(ArrayList<String> a) {
		for(int i = 0; i < a.size(); i ++) {
			if(a.get(i).equals("*")) {
				a.remove(i);
			} 
		}
	}
	public static void main(String []args) {
		ArrayList<String> a = new ArrayList<String>();
		Collections.addAll(a, "a", "*", "*", "b", "*", "*", "c");
		guardProblem(a);
		System.out.println(a);
	}
}

 但是发现删除之后数组为[a, *, b, *, c],调试发现其中有两个*被跳过了。

原因:

删除的时候,a的size变了,因此这时候的i假如递增就不能够遍历整个数组了,应该在没有删除的时候递增,删除的时候保持i不变

正确的写法

public class Test {
	public static void guardProblem(ArrayList<String> a) {
		for(int i = 0; i < a.size();) {
			if(a.get(i).equals("*")) {
				a.remove(i);
			} else {
				i ++;
			}
		}
	}
	public static void main(String []args) {
		ArrayList<String> a = new ArrayList<String>();
		Collections.addAll(a, "a", "*", "*", "b", "*", "*", "c");
		guardProblem(a);
		System.out.println(a);
	}
}

 这时候的结果就正确了,删除之后a为[a, b, c]

2
1
分享到:
评论
7 楼 wpsing 2010-03-05  
可以这样实现第一个循环
public static void guardProblem(ArrayList<String> a) {
for (int i = 0; i < a.size(); i++) {

if (a.get(i).equals("*")) {
a.remove(i);
i--;
}
}
}
6 楼 xusulong 2010-03-04  
rain2005 写道
应该使用迭代子,Iterator

another good idea
5 楼 rain2005 2010-03-04  
应该使用迭代子,Iterator
4 楼 xusulong 2010-03-04  
sdh5724 写道
你这个代码还是有问题的,倒过来循环更好。

恩,倒过来就好了,但是这样的问题出在哪里啊?
3 楼 xusulong 2010-03-04  
numen_wlm 写道
循环这样写就OK了

for (int i = loList.size()-1; i >= 0; i--){
         if (loList.get(i).equals("*"))
                 loList.remove(i);
}
	
System.out.println(loList);


我咋就么想到呢,思维定势了,多谢
2 楼 numen_wlm 2010-03-04  
循环这样写就OK了

for (int i = loList.size()-1; i >= 0; i--){
         if (loList.get(i).equals("*"))
                 loList.remove(i);
}
	
System.out.println(loList);
1 楼 sdh5724 2010-03-04  
你这个代码还是有问题的,倒过来循环更好。

相关推荐

    基于双向链表实现双端队列结构算法(java算法源码)

    //遍历 public void Traversal() { DLNode p = header.getNext(); while (p != trailer) { System.out.print(p.getElem()+" "); p = p.getNext(); } System.out.println(); } }

    Leetcode 移除链表元素.go

    LeetCode 203的题目是“移除链表元素”...解决这个问题的关键步骤包括创建一个哨兵节点(dummy node)作为新链表的头部,这样可以简化头节点删除的情况,然后遍历原链表,跳过所有值为val的节点,将剩余节点连接起来。

    题目整理(二叉树).pdf

    - 先序遍历建立二叉树的函数build_frist,利用递归和哨兵符号#来建立二叉树。 - 先序和中序遍历序列建立二叉树的函数pre_mid_build,通过递归方法结合两个遍历序列构建出原始二叉树。 - 实现队列和栈的基本操作...

    数据结构解析第三章-列表1

    在习题[3-3]中,我们讨论了列表的删除操作,发现其可以使用哨兵节点来实现删除操作。 在习题[3-4]中,我们讨论了列表的去重复算法,发现其可以使用排序算法来实现去重复操作。 在习题[3-5]中,我们讨论了列表的...

    [宫水三叶的刷题日记]:链表1

    解决这个问题可以使用“哨兵”技巧,即创建一个虚拟头结点来简化边界条件的处理。具体步骤如下: 1. 创建一个名为`dummy`的新链表节点,作为结果链表的头结点。 2. 初始化一个临时变量`tmp`指向`dummy`,并设置进位...

    链表的存储与检索优化策略.pptx

    - **遍历速度优化**:指针跳跃减少了遍历链表时所需的指令数,从而提高了遍历速度。对于那些需要频繁遍历大型链表的应用程序来说,这是一种极为有效的优化手段。 - **缓存利用率**:通过将连续节点保存在同一个缓存...

    九章算法之链表与数组(Linked List & Array)

    整个课程内容不仅涵盖了链表与数组的基础知识,还包括了哨兵节点的应用、特定问题的解决方案以及排序算法的比较等。通过学习这门课程,可以加深对链表与数组操作的理解,提升解决复杂算法问题的能力,并为软件开发...

    《数据结构》链表的插入和删除操作

    2. **删除尾节点**:需要从头开始遍历链表,找到尾节点的前一个节点,更新其next指针为NULL。 3. **删除中间节点**:同样需要找到待删除节点的前一个节点,修改前一个节点的next指针指向待删除节点的后继节点。 ...

    数据结构题

    相比之下,链接法处理冲突时,同一个散列地址对应的所有元素都会链接在一个链表中,查找时只需遍历链表即可。 #### 6. 若需要利用形参直接访问实参时,应将形参变量说明为()参数。 **答案:C.指针** 解析:通过...

    《剑指Offer》题目及代码.pdf

    57. 删除链表中重复的节点:需要遍历链表,并检查是否有节点的值重复出现,有则删除。 58. 二叉树的下一个节点:对于二叉树中的任意一个节点,找到其在中序遍历下的后继节点。 59. 对称的二叉树:判断二叉树是否是...

    java大厂面试题.docx

    本文档涵盖了Java相关的面试知识点,包括缓存机制、一致性哈希算法、Memcached与Redis的区别、...以上内容涵盖了Java面试中常见的缓存、分布式、数据持久化和数据结构等方面的知识,对于理解和解答相关问题非常有帮助。

    leetcode-链表笔记

    - 避免不必要的遍历,如在插入或删除节点时,提前查找目标节点。 - 使用哨兵节点简化边界条件处理。 - 在处理链表问题时,理解并利用链表的动态特性,避免数组操作的固定成本。 通过学习和练习 LeetCode 中的...

    数据结构与算法 全 数据结构与算法全 Java

    ### 数据结构与算法详解 #### 一、初识算法 ...- **删除**:在红黑树中删除节点的同时保持树的性质。 以上内容涵盖了从算法基础到高级数据结构和算法的各个方面,旨在帮助读者深入理解和掌握这些核心概念和技术。

    数据结构查找作业PPT学习教案.pptx

    - 在静态查找表中,顺序查找的实现是通过遍历整个数组,利用哨兵元素(如ST.elem[0])来防止越界。 3. **有序表的折半查找法**: - 折半查找只适用于已排序的表,它通过比较中间元素与目标关键字,每次将查找范围...

    数据结构整理算法.zip

    “必背-带哨兵的顺序查找.c”是顺序查找的一种变体,使用哨兵(一个额外的标记元素)来减少边界条件的处理,提高查找效率。 最后,“了解-树的遍历递归算法.c”可能包括前序遍历、中序遍历和后序遍历,这些都是树...

    03A-03B-03C无序列表1

    在析构时,需要清除所有节点并释放内存,同时删除头尾哨兵节点。 总之,静态数据结构如向量适用于数据量固定且不需要频繁改变的情况,而动态数据结构如列表则适用于需要灵活添加和移除元素的场景。理解这两种数据...

    3-3双向链表的基本操作1

    在本问题中,我们将详细讨论双向链表的一些基本操作,包括判断链表是否为空、插入节点以及删除节点。 首先,我们需要定义双向链表类`DLList`,这里使用C++模板类的方式实现,可以支持不同类型的元素。在`DLList`类...

    数据结构顺序表和4个链表的代码

    数据结构是计算机科学中的核心概念,它涉及到如何高效地存储和操作数据。顺序表和链表是两种基本的数据结构,它们...同时,不断实践和理解这些基本数据结构,有助于解决更复杂的问题,为日后的软件开发打下坚实的基础。

    数据结构顺序表查找(C语言版)

    例如,在查找过程中,我们可以假设哨兵就是目标值,直到找到真正的目标值或遍历到哨兵为止。 下面是一个使用哨兵的例子: ```c #include void sequentialSearchWithSentinel(int arr[], int target, int n) { ...

Global site tag (gtag.js) - Google Analytics