单链表的操作

1.链表的实体类:

public class ListNode {
    int val;
    ListNode next = null;

    ListNode(int val) {
        this.val = val;
    }
}

2.链表的部分操作类:

public class SolutListNode {
	ListNode head = null;

	public ListNode FindKthToTail(ListNode head, int k) {
		// 一种思路是先遍历一遍求长度,然后输出倒数k个
		// 正常的思路是,设置两个游标,让快的领先k个
		ListNode slow = head;
		ListNode fast = head;
		if (head == null || k <= 0) {
			return null;
		}
		for (int i = 1; i < k; i++) { // 快的先走k-1步,倒数第三个,其实应该快的指到第三个,只需要走两步即可。
			if (fast.next == null) // 这个是k与链表长度的关系,如果,链表长度小于k,肯定在走到k之前就出现null,直接返回null即可
				return null;
			else
				fast = fast.next;
		}
		while (fast.next != null) { // 快的从第k个,慢的从第1个,同时开始走。
			slow = slow.next;
			fast = fast.next;
		}
		return slow;
	}

	/**
	 * 链表添加结点: 找到链表的末尾结点,把新添加的数据作为末尾结点的后续结点
	 * 
	 * @param data
	 */
	public void addNode(int data) {
		ListNode newNode = new ListNode(data);
		if (head == null) {
			head = newNode;
			return;
		}
		ListNode temp = head;
		while (temp.next != null) {
			temp = temp.next;
		}
		temp.next = newNode;
	}

	public void printLink(ListNode head) {
		ListNode curNode = head;
		while (curNode != null) {
			System.out.print(curNode.val + " ");
			curNode = curNode.next;
		}
		System.out.println();
	}
    //反转链表
	public ListNode ReverseList1(ListNode head) {
		if (head == null) 
			return null; // head为当前节点,如果当前节点为空的话,那就什么也不做,直接返回null; 
		ListNode pre = null;
		ListNode next = null;
		// 当前节点是head,pre为当前节点的前一节点,next为当前节点的下一节点  
        // 需要pre和next的目的是让当前节点从pre->head->next1->next2变成pre<-head next1->next2  
        // 即pre让节点可以反转所指方向,但反转之后如果不用next节点保存next1节点的话,此单链表就此断开了  
        // 所以需要用到pre和next两个节点  
        // 1->2->3->4->5  
        // 1<-2<-3 4->5  
		while(head != null){ //注意这个地方的写法,如果写head.next将会丢失最后一个节点
			// 做循环,如果当前节点不为空的话,始终执行此循环,此循环的目的就是让当前节点从指向next到指向pre   
            // 如此就可以做到反转链表的效果  
            // 先用next保存head的下一个节点的信息,保证单链表不会因为失去head节点的原next节点而就此断裂
			next = head.next; //先让head.next指向的节点,即第二个节点叫next
			head.next = pre; //将head.next指向pre,也就是说断开head节点与后面的连接
			pre = head;//pre,head依次向后移动一个节点,进行下一次反转
			head = next;
		}
		// 如果head为null的时候,pre就为最后一个节点了,但是链表已经反转完毕,pre就是反转后链表的第一个节点 
		return pre;
	}
	//合并两个递增的链表并且保证最终的链表也是单调不减的。
	 public ListNode Merge(ListNode list1,ListNode list2) {
	    if (list1 == null) {
			return list2;
		}
	    if (list2 == null) {
			return list1;
		}
	    //新建一个用于存放融合之后的链表
	    //因为,融合的过程中链表是一直移动的,所以要把链表的头保存下来,才能返回正确的一条链
	    ListNode res = new ListNode(0);
	    ListNode merlistNode = res;
	    while (list1 != null && list2 != null) { //依次比较,将较小的节点连到融合节点上
			if(list1.val < list2.val){   
				merlistNode.next = list1;      //连上小的list1
			    list1 = list1.next;         //list1 可以往后移动一个,下次用移动后的和list2比较
			    merlistNode = merlistNode.next;// merlistNode也往后移动一个
			}
			
			else {
				merlistNode.next = list2;
			    list2 = list2.next;
			    merlistNode = merlistNode.next;
			}
			
		}
	    //把未结束的链表连接到合并后的链表尾部 
	    if(list1 != null)
	    	merlistNode.next = list1;
	    if(list2 != null)
	    	merlistNode.next = list2;
	    return res.next;
	 }
	 //递归的方式融合
	 public ListNode Merge2(ListNode list1,ListNode list2) {
		    if (list1 == null) {
		        return list2;
		    }
		    if (list2 == null) {
		        return list1;
		    }
		    ListNode newHead = null;
		    if (list1.val <= list2.val) {
		        newHead = list1;
		        newHead.next = Merge(list1.next,list2);
		    }else {
		        newHead = list2;
		        newHead.next = Merge(list1,list2.next);
		    }

		    return newHead;
		}

}

反转的原理分析:

过程就是:head的下一个名为next

                 断开head与next的连接,转为指向前面的pre。

                 pre、head依次往前移动

                 知道head==null结束,返回pre



3、测试类:

/**
 * 三个类:ListNode SolutListNode 和 本类是测试的
 * @author Administrator
 *
 */
public class TestListNode {

    public static void main(String[] args) {
		SolutListNode myliListNode = new SolutListNode();//ListNode 只是其中的一个节点,而myliListNode.head就是两个链表的头,找到头就依次可以了
		myliListNode.addNode(1);
		myliListNode.addNode(2);
		myliListNode.addNode(3);
		myliListNode.addNode(5);
		myliListNode.addNode(8);
		myliListNode.printLink(myliListNode.head);
		
		//输出反转之后的链表
		//ListNode reverListNode = myliListNode.ReverseList1(myliListNode.head);
		//myliListNode.printLink(reverListNode);
		
		//输出倒数第k个节点
		//ListNode nk = myliListNode.FindKthToTail(myliListNode.head, 2);
        //System.out.println(nk.val);
		
		//输出融合排序后的链表
		SolutListNode mlist2 = new SolutListNode();
		mlist2.addNode(4);
		mlist2.addNode(6);
		mlist2.addNode(9);
        ListNode resListNode = mlist2.Merge(myliListNode.head, mlist2.head);
        mlist2.printLink(resListNode);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值