`

双向链表任意遍历打印实现

 
阅读更多
   实现双向链表的任意遍历打印,涉及到双向链表和递归调用。本这段代码一共实现了5中遍历打印的方法,其中有一种是传入根节点,一种是不需要传入结点,另外3种都是任一个结点的参数。其中printRan3()方法独立实现打印,是这段代码的亮点,printRan2()方法有助于你理解递归调用。printRan4()方法是石军同学实现的,我只是在这里展示。
    看懂这段代码,将很大程度上提高你看懂递归调用的能力。
package linkdemo;

public class LinkDemo {

	public static void main(String args[]){
		LinkDemo demo=new LinkDemo();
		LinkNode foot=demo.creatLink();
        System.out.println("调用printAll()方法打印");
		demo.printAll(foot);
		System.out.println("调用printRan1()方法打印");
		demo.printRan1();
		System.out.println("调用printRan2()方法打印");
		demo.printRan2(foot.getNext());
		System.out.println("调用printRan3()方法打印");
		demo.printRan3(foot.getNext());
		
		foot.delete();    //删除链表中的根节点
		foot.insert(new LinkNode("插入的结点"));
		System.out.println("调用printRan4()方法打印");
		demo.printRan4(foot.getNext());
	}
	
	//创建一个新的链表,返回根节点
	public LinkNode creatLink(){
		LinkNode no1=new LinkNode("节点1");
		LinkNode no2=new LinkNode("节点2");
		LinkNode no3=new LinkNode("节点3");
		LinkNode no4=new LinkNode("节点4");
		LinkNode no5=new LinkNode("节点5");
		
		//手动设置节点在链表中的关系
		no1.setNext(no2);
		no2.setPre(no1);
		no2.setNext(no3);
		no3.setPre(no2);
		no3.setNext(no4);
		no4.setPre(no3);
		no4.setNext(no5);
		no5.setPre(no4);
		LinkNode.setFoot(no1);  //设置no1为根节点
		
		return no1;
	}
	
	//传入链表的根节点,输出所有的节点的值的方法
	public void printAll(LinkNode foot){
		if(foot!=null){
			System.out.println("节点的值是:"+foot.getData());
			foot=foot.getNext();
			printAll(foot);
		}
	}
	
	//无需传入任何一个链表中的节点,打印出所有的节点的方法一(使用根节点foot类属性)
	public void printRan1(){
		printAll(LinkNode.getFoot());
	}
	
	//传入链表中任何一个节点,遍历输出所有链表中所有节点的方法二(未使用根节点foot类属性)
	public void printRan2(LinkNode ran){
		boolean b1=true;
		boolean b2=true;
		int count1=0;
		
		printRan(ran,b1,b2,count1);
		
	}
	
	private void printRan(LinkNode ran,boolean b1,boolean b2,int count1){
		//打印ran之后的所有节点
		if(b1&&(ran.getNext()!=null)){
			ran=ran.getNext();
			if(ran.getNext()!=null){
				System.out.println("节点的值是:"+ran.getData());
				count1++;
				printRan(ran,b1,b2,count1);
			}

			if(ran.getNext()!=null){
				b1=false;
				b2=false;
			}
		}	
		
		//打印ran节点,并将ran回复到原始出入的ran值
		if(b1){
			System.out.println("节点的值是:"+ran.getData());
			
			if(count1!=0){
				for(int i=0;i<count1+1;i++){
					ran=ran.getPre();
				}
				System.out.println("节点的值是:"+ran.getData());
			}
			b1=false;
		}
		
		//打印ran节点之前的所有节点
		if(b2){
			ran=ran.getPre();
			if(ran!=null){
				System.out.println("节点的值是:"+ran.getData());
				printRan(ran,b1,b2,count1);
			}
			if(ran!=null){
				b2=false;
			}
			System.out.println("****************一组打印完了*******************");
		}
	}
	
	//单个方法实现任一节点的遍历打印:方法三
	//(不需要调用另外的方法,单个参数,不需要使用LinkNode类中的foot属性)
	public void printRan3(LinkNode ran){
		if(ran.getPre()==null){
			while(ran!=null){
				System.out.println(ran.getData());
				ran=ran.getNext();
			}
			return;
		}
		if(ran!=null){
			ran=ran.getPre();
			printRan3(ran);
		}
    }
	
	//传入任意结点,遍历打印所有结点的方法四
	//(不需要使用LinkNode中foot属性,要调用printRan1()方法)
	//     ——石军同学实现的,没有征得你同意就在这边贴出来了,希望原谅
	public void printRan4(LinkNode ran){
		if(ran.getPre()!=null){
			ran=ran.getPre();
			printRan4(ran);
		}else{
		    printAll(ran);
		}
	}
	
};



package linkdemo;
//链表的节点类
public class LinkNode {

	private LinkNode next;   //下一个节点
	private LinkNode pre;   //前一个节点
	private String data;   //链表的值
	private static LinkNode foot;   //类属性,链表的根节点属性
	
	public LinkNode(String data){
		this.data=data;
	}
	public static LinkNode getFoot(){
		return foot;
	}
	
	
	
	public LinkNode getNext() {
		return next;
	}



	public void setNext(LinkNode next) {
		this.next = next;
	}



	public LinkNode getPre() {
		return pre;
	}



	public void setPre(LinkNode pre) {
		this.pre = pre;
	}



	public String getData() {
		return data;
	}



	public static void setFoot(LinkNode foot) {
		LinkNode.foot = foot;
	}



	//在一个节点后面插入新的节点的方法
	public void insert(LinkNode newNode){
		LinkNode no=this.next;
		
		this.next=newNode;
		newNode.pre=this;
		no.pre=newNode;
		newNode.next=no;
	}
	
	//删除调用该方法的节点
	public void delete(){
		if(this.pre==null){   //如果是首节点
			this.data=this.next.data;
			this.next.next.pre=this;
			this.next=this.next.next;
		}else{
			this.pre.next=this.next;
			this.next.pre=this.pre;
		}	
	}
	
	
};










  • 大小: 14 KB
分享到:
评论
2 楼 贾懂凯 2010-11-29  
major1314 写道
小小的看了一下,也运行了一次,一个小问题:LindNode中的foot为static,那么当我在LinkDemo中想创建两个链表的时候,根节点怎么办,即如果我在LinkDemo中加入一个函数
public LinkNode creatLink2(){  
   
        LinkNode no1=new LinkNode("节点11");  
        LinkNode no2=new LinkNode("节点21");  
        LinkNode no3=new LinkNode("节点31");  
        LinkNode no4=new LinkNode("节点41");  
        LinkNode no5=new LinkNode("节点51");  
       
        //手动设置节点在链表中的关系  
        no1.setNext(no2);  
        no2.setPre(no1); 
        no2.setNext(no3);  
        no3.setPre(no2); 
        no3.setNext(no4);  
        no4.setPre(no3);     
        no4.setNext(no5);  
        no5.setPre(no4);      
        LinkNode.setFoot(no1);  //设置no1为根节点           
        return no1;  
    }
这儿加入这么一个函数完全只是想创建第二个不同的链表,楼主只提供了一个写死了的函数,没办法用哈,LinkNode node2 = demo.creatLink2();
此时后面再打印的时候可就出问题了,LinkNode.getFoot()得到的可是我第二次创建链表的根节点了哟,foot为static,是属于类的,这里是否真的合适哟?

显然staic属性是类级的,所以在所有对象间共享也是必然的。
我的createLink()只是测试用,如果你想要复用性比较强的方法,可以自己重新去定义。
请注意printRan3()方法,这才是highlight!
注意,本文的链表不是通常意义上的循环双向链表,如果是循环双向链表,上面多有的讨论将变得一文不值!
1 楼 major1314 2010-11-29  
小小的看了一下,也运行了一次,一个小问题:LindNode中的foot为static,那么当我在LinkDemo中想创建两个链表的时候,根节点怎么办,即如果我在LinkDemo中加入一个函数
public LinkNode creatLink2(){  
   
        LinkNode no1=new LinkNode("节点11");  
        LinkNode no2=new LinkNode("节点21");  
        LinkNode no3=new LinkNode("节点31");  
        LinkNode no4=new LinkNode("节点41");  
        LinkNode no5=new LinkNode("节点51");  
       
        //手动设置节点在链表中的关系  
        no1.setNext(no2);  
        no2.setPre(no1); 
        no2.setNext(no3);  
        no3.setPre(no2); 
        no3.setNext(no4);  
        no4.setPre(no3);     
        no4.setNext(no5);  
        no5.setPre(no4);      
        LinkNode.setFoot(no1);  //设置no1为根节点           
        return no1;  
    }
这儿加入这么一个函数完全只是想创建第二个不同的链表,楼主只提供了一个写死了的函数,没办法用哈,LinkNode node2 = demo.creatLink2();
此时后面再打印的时候可就出问题了,LinkNode.getFoot()得到的可是我第二次创建链表的根节点了哟,foot为static,是属于类的,这里是否真的合适哟?

相关推荐

    支持类模版的C++双向链表

    在双向链表的实现中,类模版使得我们可以创建一个通用的链表类,用于存储任意类型的数据。例如,我们可以定义一个名为`ListNode`的节点类模版,它有两个成员:一个是存储数据的模板类型`T`,另一个是指向前后节点的...

    C++经典算法 双向链表

    输出双向链表的函数`void PrLink(linky p)`可以遍历整个链表,并打印每个节点的数据值。 #### 排序双向链表 排序双向链表可以通过多种算法实现,如冒泡排序、插入排序等。给定的代码示例中并没有给出具体的排序...

    双向链表双向链表双向链表

    这种设计使得双向链表在数据操作上具有更高的灵活性,比如可以方便地进行前向和后向遍历。 在双向链表中,每个节点通常包含三个部分:数据部分,用于存储实际的数据;后继指针,指向链表中的下一个节点;以及前驱...

    实现循环链表及双向链表2

    循环链表和双向链表在许多应用场景中都很有用,如实现队列(循环链表适合实现循环队列)、在图形渲染中存储顶点信息(双向链表方便遍历和修改相邻元素),以及在数据库索引结构(如B树)中。 在《实现循环链表及...

    04_双向链表_链表_declaredzfw_双向链表_

    - `dlinklist.c`通常包含了对双向链表的函数实现,如创建链表、插入、删除、打印链表等操作的函数。 - `main.c`是主程序,调用`dlinklist.c`中的函数进行测试,展示双向链表的功能。 4. 实际应用 双向链表在很多...

    C语言实现通用双向链表标准版.rar

    本资源“C语言实现通用双向链表标准版.rar”提供了一个使用C语言实现的通用双向链表实例,这对于理解和掌握数据结构,尤其是链表操作具有重要意义。 双向链表是一种线性数据结构,与单向链表不同,它允许节点在两个...

    带头节点的双向链表

    在众多类型的链表中,双向链表(Double Linked List)是一种特殊形式,它允许我们从两个方向遍历数据,即向前和向后。这里我们将深入探讨“带头节点的双向链表”这一主题。 双向链表与单链表的主要区别在于每个节点...

    双向链表C语言实现

    本文将详细讲解如何使用C语言来实现一个双向链表,并涵盖按照ID序列插入、删除、更新和修改等操作。 双向链表与单链表不同,它在每个节点中不仅存储数据,还包括指向前后节点的指针。这种特性使得双向链表可以在...

    双向链表模板类的实现

    这个模板类实现了双向链表的基本功能,包括构造函数、追加元素、插入元素、删除元素、遍历链表和获取链表长度。通过实例化这个类,你可以创建一个存储任何类型元素的双向链表。例如,你可以创建一个存储整数的双向...

    数据结构双向链表

    本篇将详细介绍双向链表及其C语言实现的基础操作。 双向链表是一种线性数据结构,每个节点包含数据部分以及两个指针,一个指向前一个节点(prev),另一个指向后一个节点(next)。这种设计使得双向链表在插入、...

    ==双向链表python实现源代码==

    3.适用于大部分场景:双向链表在许多场景中都非常有用,比如需要频繁地在链表的任意位置插入和删除节点,或者需要在双向遍历的情况下快速访问前一个节点。 然而,与单向链表相比,双向链表在空间上需要更多的内存,...

    实现循环链表及双向链表1

    遍历双向链表有两种主要方式:正向遍历和反向遍历。正向遍历从头结点开始,沿着前向指针直到尾结点;反向遍历则从尾结点开始,沿着后向指针直至头结点。这种特性使得双向链表在某些需要频繁反转顺序访问数据的场景下...

    sss.rar_sss_双向链表_链表_链表 插入

    双向链表因其独特的结构特性,常用于实现高效的算法,如在数据库索引、缓存管理、文件系统等领域。理解并熟练掌握双向链表的操作是成为一名优秀的程序员的关键技能之一。在实际应用中,根据具体需求选择合适的数据...

    通用双向链表以及内存检漏算法

    总结起来,这个项目提供了一个实际的案例,展示了如何在C语言中实现一个通用的双向链表,并结合内存检漏检测算法确保程序的资源效率。通过学习和理解这部分代码,开发者可以深化对数据结构和内存管理的理解,提高...

    可以实现增删改遍历的双向链表

    双向链表相较于单向链表具有更强的灵活性,在本篇文章中,我们将详细介绍如何使用C++来实现一个支持多种操作的双向链表,包括节点的插入、删除、遍历以及文件读写功能。 #### 二、核心概念与设计 ##### 2.1 节点...

    实现循环链表及双向链表3

    至于提供的"实现循环链表及双向链表3.pdf"文件,它很可能是对这两种链表实现的详细步骤、代码示例或相关问题的解答。通过阅读这份文档,你可以深入理解这两种数据结构的内部工作机制,并学习如何在实际编程中应用...

    模板实现c语言版的单双向链表,有例子程序,绝对好用

    本示例将详细讲解如何利用宏定义实现一个通用的单双向链表,包括链表节点的定义、链表操作的宏定义以及实际应用的例子。 首先,我们来理解单双向链表的基本概念。单向链表是一种线性数据结构,每个节点包含数据和...

    双向链表的基本操作建立,插入,删除

    在实际应用中,双向链表常用于实现高效的迭代器、缓存系统、数据结构如LRU等,因为它提供了向前和向后的遍历能力。通过熟练掌握这些基本操作,你可以更好地理解和利用这种数据结构解决实际问题。

Global site tag (gtag.js) - Google Analytics