单链表

做了一个单链表,可以实现增删改查逆序打印反转合并等操作,但遗留了三个问题:
1、如何将两个未按序号排序的链表按顺序合并?
2、如何将未知数量的链表按顺序合并?
3、下面这个程序为什么会出问题?
假设我创建一个节点A
·在链表1里调用add()方法将A连接到链表1中。
·在链表2里再次调用add()方法添加A节点,却将A节点及后面的节点全部添加到链表2中,这是我们不希望看到的,可是原因是什么呢?
问题见主方法最后一部分注释处,为使程序正常运行我使用addByOrder()方法添加了book1节点,使用add()方法添加会导致程序无限循环。

import java.util.Stack;
//为什么第五十八行调用add方法会出错?如何纠正?list1将book1节点曾经连上过会影响list2连接book1节点?
public class SingleLinkedListDemo {
	public static void main(String[] args) {
		//测试增删改等基本操作
		Book book1=new Book(1,"Joker");
		Book book2=new Book(2,"No face man");
		Book book3=new Book(3,"Traveler");
		Book book4=new Book(4,"Immortal");
		Book book5=new Book(5,"Red sacrifices");
		Book book6=new Book(6,"Light trap");
		Book book7=new Book(7,"Handed man");
		
		SingleLinkedList list1=new SingleLinkedList();
		
		list1.add(book1);
		list1.add(book3);
		list1.add(book5);
		list1.add(book7);
		
		list1.list();
		System.out.println();
		
		list1.addByOrder(book2);
		list1.addByOrder(book4);
		
		list1.list();
		System.out.println();
		
		Book newBook1=new Book(1,"Clown");
		list1.update(newBook1);
		
		list1.list();
		System.out.println();
		
		list1.del(1);
		
		list1.list();
		System.out.println("基本操作结束");
		
		//获取第一个链表的长度
		System.out.println("第一个链表的长度为:"+getLength(list1.getHead()));
		
		//逆序打印
		System.out.println("逆序打印的链表为:");
		reversePrint(list1.getHead());
		
		//反转
		System.out.println("反转的链表为:");
		reverseList(list1.getHead());
		list1.list();
		reverseList(list1.getHead());
		System.out.println();
		list1.list();
		System.out.println();
		
		SingleLinkedList list2=new SingleLinkedList();
		list2.addByOrder(book1);//为什么这儿调用add方法而不是addByOrder会出错?
		list2.add(book6);
		list2.list();
		System.out.println();
		Book book=mergeTwoList(list1.getHead(),list2.getHead());
		book=book.next.next;
		while(book!=null) {
			System.out.println(book);
			book=book.next;
		}
	}
	
	//获取链表的长度
	public static int getLength(Book head) {
		if(head.next==null) {
			return 0;
		}
		int length=0;
		Book temp=head.next;
		while(temp!=null) {
			length++;
			temp=temp.next;
		}
		return length;
	}
	
	
	//查找链表的倒数第k个节点
	public static Book findLastIndexNode(Book head,int index) {
		if(head.next==null) {
			System.out.println("没有找到");
			return null;
		}
		int size=getLength(head);
		if(index<=0||index>size) {
			return null;
		}
		Book temp=head.next;
		for(int i=0;i<size-index;i++) {
			temp=temp.next;
		}
		return temp;
	}
	
	//逆序打印
	public static void reversePrint(Book head) {
		if(head.next==null) {
			System.out.println("空链表,不能打印");
		}
		Stack<Book> st=new Stack<Book>();
		Book temp=head.next;
		while(temp!=null) {
			st.push(temp);
			temp=temp.next;
		}
		while(st.size()>0) {
			System.out.println(st.pop());
		}
	}
	
	//反转单链表
	public static void reverseList(Book head) {
		if(head.next==null||head.next.next==null) {
			return;
		}
		Book temp=head.next;
		Book next=null;//指向temp的下一个节点
		Book reverseHead=new Book(0,"");
		while(temp!=null) {
			next=temp.next;
			temp.next=reverseHead.next;
			reverseHead.next=temp;
			temp=next;
		}
		head.next=reverseHead.next;
	}
	
	//单链表的合并
	public static Book mergeTwoList(Book head1,Book head2) {
		if(head1==null||head2==null) {
			return head1!=null?head1:head2;
		}
		Book head=head1.no<=head2.no?head1:head2;
		Book cur1=head==head1?head1:head2;
		Book cur2=head==head1?head2:head1;
		Book pre=null;//初始为cur1的前一个,之后为cur1和cur2中较小的那一个
		Book next=null;//初始为cur2的后一个,之后为上次较大的那一个后面的一个
		while(cur1!=null&&cur2!=null) {
			if(cur1.no<=cur2.no) {
				pre=cur1;
				cur1=cur1.next;
			}else {
				next=cur2.next;
				pre.next=cur2;
				cur2.next=cur1;
				pre=cur2;
				cur2=next;
			}
		}
		pre.next=cur1==null?cur2:cur1;
		return  head;

	}
}

//定义一个SingleLinkedList管理书
class SingleLinkedList{
	//先初始化一个头节点
	private Book head=new Book(0,"");
	
	public Book getHead() {
		return head;
	}
	
	/*
	 * 当不考虑编号顺序添加:
	 * 1、找到当前链表的最后节点
	 * 2、将这个节点的next指向新的节点
	 */
	public void add(Book book) {
		
		//因为头节点不能动,我们需要一个辅助结点temp
		Book temp=head;
		//遍历链表,找到他的最后
		while(true) {
			if(temp.next==null) {
				break;
			}
			//没有找到,就将temp后移
			temp=temp.next;
		}
		//当退出这个循环时,temp就只想了链表的最后
		temp.next=book;
	}
	
	// 第二种添加节点的方式:将Book按编号插入指定位置
	public void addByOrder(Book book) {
		Book temp=head;//temp为添加位置的前一个节点
		boolean flag=false;//标志添加的编号是否存在,默认为false
		while(true) {
			if(temp.next==null) {
				break;
			}else if(temp.next.no>book.no) {
				break;
			}else if(temp.next.no==book.no) {
				flag=true;
				break;
			}
			temp=temp.next;
		}
		if(flag) {
			System.out.println("编号已存在,不能添加");
		}else {
			book.next=temp.next;
			temp.next=book;
		}
	}
	
	//根据no修改节点的信息
	public void update(Book book) {
		if(head.next==null) {
			System.out.println("链表为空");
			return;
		}
		
		Book temp=head.next;
		boolean flag=false;
		while(true) {
			if(temp==null) {
				break;
			}else if(temp.no==book.no) {
				flag=true;
				break;
			}
			temp=temp.next;
		}
		if(flag) {
			temp.name=book.name;
		}else {
			System.out.printf("没有找到编号为%d的节点",book.no);
		}
	}
	
	//删除节点
	public void del(int no) {
		Book temp=head;
		boolean flag=false;
		while(true) {
			if(temp.next==null) {
				break;
			}else if(temp.next.no==no) {
				flag=true;
				break;
			}
			temp=temp.next;
		}
		if(flag) {
			temp.next=temp.next.next;
		}else {
			System.out.println("要删除的节点不存在");
		}
	}
	
	//显示链表(遍历)
	public void list() {
		if(head.next==null) {
			System.out.println("链表为空");
			return;
		}
		Book temp=head.next;
		while(true) {
			if(temp==null) {
				break;
			}
			System.out.println(temp);
			temp=temp.next;
		}
	}
	
}
//每一本书都是一个节点
class Book {
	public int no;
	public String name;
	public Book next;
	//构造器,注意下一个节点Book不用传进来
	public Book(int no,String name) {
		this.no=no;
		this.name=name;
	}
	
	//重写一个toString()方法
	public String toString() {
		return "Book[no="+no+",name="+name+"]";
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值