`

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

 
阅读更多
   实现双向链表的任意遍历打印,涉及到双向链表和递归调用。本这段代码一共实现了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,是属于类的,这里是否真的合适哟?

相关推荐

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

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

    特殊的链表——双向、循环、静态

    双向链表 定义 :每个节点有两个指针域,分别知道直接前驱和直接后继节点 , 特点是可以重任意节点出发,从两个方向遍历链表 数据结构 typedef struct node { int data; struct node *font ; struct node *next; ...

    linked-list:C用于单链表和双链表

    双向链表结构体 创建结点 初始化链表 释放链表 获取链表长度 获取头结点 获取尾结点 遍历链表 插入头结点 插入尾结点 任意位置插入结点 删除头结点 删除尾结点 删除任意位置结点 获取任意位置结点 查找链表中指定的...

    lrucacheleetcode-Codes:学习编程

    lru缓存leetcode 学习和探索编程 C、C++、Python 探索领域: 1 数组 二分搜索、在滑动窗口中查找...,将二叉树转换为双向链表,打印树边界、连接同级兄弟、序列化/反序列化二叉树、连接所有兄弟、带父指针的中序后继 BS

    《妙趣横生的算法(C语言实现)》(杨峰 编著)

    7.9 动态双向链表的应用 7.10 判断完全二叉树 7.11 动画模拟创建二叉树 7.12 打印符号三角形 7.13 递归函数的非递归求解 7.14 任意长度整数加法 第8章 数值计算问题 8.1 递推化梯形法求解定积分 8.2 求解低阶定积分...

    inf-1101-assignment1:作业1,INF1101课程

    它是使用双向链表实现的。 还提供了两个简单的程序来演示和使用ADT。 它们都接受任意数量的txt文件作为输入: Sortwords:此程序从给定的txt文件中提取单词,然后按排序顺序将它们打印到控制台。 反向单词:该...

    数据结构:八大数据结构分析.pdf

    根据指针的指向,链表能形成不同的结构,例如单链表,双向链表, 循环链表等。 链表的优点: 1. 链表是很常⽤的⼀种数据结构,不需要初始化容量,可以任意加减元素; 2. 添加或者删除元素时只需要改变前后两个元素...

    C语言通用范例开发金典.part2.rar

    范例1-52 双向链表元素值的查询 129 ∷相关函数:GetElemP函数 1.3.22 稀疏矩阵的建立 136 范例1-53 稀疏矩阵的建立 136 ∷相关函数:Create函数 1.3.23 稀疏矩阵的删除 138 范例1-54 稀疏矩阵的删除 138 ∷...

    C语言通用范例开发金典.part1.rar

    范例1-52 双向链表元素值的查询 129 ∷相关函数:GetElemP函数 1.3.22 稀疏矩阵的建立 136 范例1-53 稀疏矩阵的建立 136 ∷相关函数:Create函数 1.3.23 稀疏矩阵的删除 138 范例1-54 稀疏矩阵的删除 138 ∷...

    C 开发金典

    范例1-52 双向链表元素值的查询 129 ∷相关函数:GetElemP函数 1.3.22 稀疏矩阵的建立 136 范例1-53 稀疏矩阵的建立 136 ∷相关函数:Create函数 1.3.23 稀疏矩阵的删除 138 范例1-54 稀疏矩阵的删除 138 ∷...

    C程序范例宝典(基础代码详解)

    实例088 创建双向链表 114 实例089 创建循环链表 117 实例090 双链表逆置 118 实例091 双链表逆序输出 120 实例092 约瑟夫环 122 实例093 创建顺序表并插入元素 123 实例094 向链表中插入结点 125 ...

    数据结构课设

    (3)从文件读入30个学生成绩(0-100之间),建立一个双向循环链表并输出,调整链表顺序,使所有的及格成绩排在不及格成绩之前,并输出。 2、二叉树的应用 任务 :编程实现二叉树的建立,层次遍历,(递归和非递归...

    脑力保健 微软,GOOGLE等试题试做 C#版

    输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 要求不能创建任何新的结点,只调整指针的指向。 10 / \ 6 14 / \ / \ 4 8 12 16 转换成双向链表 4=6=8=10=12=14=16。 n个数字(0,1,...

    数据结构(C++)有关练习题

    2、实现1所要求的代码后,运行设计好的代码,将以下的几组整数序列建成搜索二叉树,并记录下它们的前序遍历序列和后序遍历序列: a. 1、3、5、7、9; b. 1、13、35、13、27; c. 50、25、78、13、44、...

    Delphi开发范例宝典目录

    实例049 使用任意组件拖动窗体 58 实例050 动态创建窗体和释放窗体 59 实例051 修改提示字体及颜色 60 1.14 其他技术 61 实例052 窗口融合技术 61 实例053 给MDI窗体加背景 62 实例054 如何关闭MDI类型...

    C#开发实例大全(基础卷).软件开发技术联盟(带详细书签) PDF 下载

    实例132 双向链表的实现 168 实例133 堆栈的实现 173 实例134 队列的实现 175 实例135 树的实现 177 6.2 常见算法的实际应用 180 实例136 计算1+22+33+44+…+nn的值 180 实例137 计算10!的值 181 实例138 求最大公...

Global site tag (gtag.js) - Google Analytics