链表经典算法题实现

本文包含链表的以下内容:

  1、单链表的创建和遍历

  2、求单链表中节点的个数

  3、查找单链表中的倒数第k个结点(剑指offer,题15)

  4、查找单链表中的中间结点

  5、合并两个有序的单链表,合并之后的链表依然有序【出现频率高】(剑指offer,题17)

  6、单链表的反转【出现频率最高】(剑指offer,题16)

  7、从尾到头打印单链表(剑指offer,题5)

  8、判断单链表是否有环

  9、取出有环链表中,环的长度

  10、单链表中,取出环的起始点(剑指offer,题56)。本题需利用上面的第8题和第9题。

  11、判断两个单链表相交的第一个交点(剑指offer,题37)

 

package com.he;

import java.util.Stack;

import com.he.LinkList.Node;

public class test32 {
	class Node{
		int data;
		Node next;
		Node(int data){
			this.data = data;
		}
	}
	public Node head =null;
    public Node current = null;
    //添加节点
    public void add(int data){
    	if(head==null){
    		head = new Node(data);
    		current = head;
    	}else{
    		current.next = new Node(data);
    		current = current.next;
    	}
    }
    //方法重载:向链表中添加结点
    public void add(Node node){
    	if(head==null){
    		head = node;
    		current = node;
    	}else{
    		current.next = node;
    		current = current.next;
    	}
    }
    
    //遍历节点
    public void print(Node node){
        current = node;
        while(current!=null){
        	System.out.println(current.data);
        	current = current.next;
        }
    }
    //求单链表节点
    public int getLength(Node node){
    	current = node;
    	int length = 0;
    	if(current == null){
    		return 0;
    	}
    	while(current!=null){
    		length++;
    		current = current.next;   		
    	}
		return length;  
    	
    }
    //查找单链表中的倒数第k个结点
    public Node findLastNode(Node node,int k){
    	if(node==null || k==0){
    		return null;
    	}
    	Node first = node;
    	Node second = node;
    	for (int i = 0; i < k-1; i++) {
			second = second.next;
			if(second == null){
				return null;
			}
		}
    	while(second.next!=null){
    		first = first.next;
    		second = second.next;
    	}
    	return first;
    }
    
    //查找单链表中的中间结点
    public Node findMiddle(Node node){
    	if(node==null){
    		return null;
    	}
    	Node first = node;
    	Node second = node;
    	while(first!=null && second!=null){
    		if(second.next!=null){
    			second = second.next.next;
    		}else{
    			return first;
    		}   
    		first = first.next;
    	}
    	return first;
    }
   
    //合并两个有序的单链表,合并之后的链表依然有序
    public Node getMergeLinkList(Node head1,Node head2){
    	if(head1==null && head2==null){
    		return null;
    	}
    	if(head1==null){
    		return head2;
    	}
    	if(head2==null){
    		return head1;
    	}
    	Node head;
    	Node current;
    	if(head1.data < head2.data){
    		head = head1;
    		current = head1;
    		head1 = head1.next;
    	}else{
    		head = head2;
    		current = head2;
    		head2 = head2.next;
    	}
    	while(head1!= null && head2!= null){
    		if(head1.data < head2.data){
    			current.next = head1;
    			current = current.next;
    			head1 = head1.next;
    		}else{
    			current.next = head2;
    			current = current.next;
    			head2 = head2.next;
    		}
    	}
    	if(head1 == null){
    		current.next = head2;
    	}
    	if(head2 == null){
    		current.next = head1;
    	}
    	return head;
    }
    //单链表的反转
    public Node reverseList(Node head){
    	if(head==null && head.next==null){
    		return head;
    	}
    	Node reverseHead = null;
    	Node next = null;
    	Node current = head;
    	while(current!=null){
    		next = current.next;
    		current.next = reverseHead;
    		reverseHead = current;
    		current = next;
    	}
    	return reverseHead;
    }
     
  //翻转链表方法2
   public ListNode reverseList(ListNode head) {
        ListNode prev = null;
        while(head!=null){
            ListNode tmp = head.next;
            head.next = prev;
            prev = head;
            head = tmp;
        }
        return prev;
    }
    
    //从尾到头打印单链表
    public void reversePrint(Node head){
    	if(head == null){
    		return;
    	}
    	Stack<Node> stack = new Stack<Node>();
    	Node current = head;
    	while(current!=null){
    		stack.push(current);
    		current = current.next;
    	}
    	while(stack.size()>0){
    		System.out.println(stack.pop().data);
    	}
    }
    
    //判断单链表是否有环
    public boolean hasCycle(Node head){
    	if(head == null){
    		return false;
    	}
    	Node first = head;
    	Node second = head;
    	while(second!=null){
    		first = first.next;
    		if(second.next!=null){
    			second = second.next.next;
    		}else{
    			return false;
    		}    		
    		if(first == second){
    			return true;
    		}
    	}
    	return false;
    }
   
    //取出有环链表中,环的长度
    public int getCycleLength(Node node){
    	int length = 0;
    	Node current = node;
    	while(current!=null){
    		current = current.next;
    		length++;
    		if(current == node){
    			return length;
    		}
    	}
    	return length;
    }
    
    //单链表中,取出环的起始点
    public Node getCycleStart(Node head,int cycleLength){
    	if(head==null){
    		return null;
    	}
    	Node first = head;
    	Node second = head;
    	for (int i = 0; i < cycleLength; i++) {
			second = second.next;
		}
    	while(first!=null&& second!=null){
    		if(first == second){
    			return first;
    		}
    		first = first.next;
    		second = second.next;
    	}
    	return null;
    }
    
    //求两个单链表相交的第一个交点
    public Node getFirstCommonNode(Node head1,Node head2){
    	if(head1==null|| head2==null){
    		return null;
    	}
    	int length1 = getLength(head1);
    	int length2 = getLength(head2);
    	int lengthDif = 0;
    	Node longHead = null;
    	if(length1 > length2){
    		lengthDif = length1-length2;
    		longHead = head1;
    	}else{
    		lengthDif = length2-length1;
    		longHead = head2;
    	}
    	for (int i = 0; i < lengthDif; i++) {
		    longHead = longHead.next;	
		}
    	while(longHead!=null && head2!=null){
    		longHead = longHead.next;
    		head2 = head2.next;
    		if(longHead == head2){
    			return head2;
    		}
    	}
		return null;    	
    }
    
    public static void main(String[] args) {
	    test32 sh = new test32();
	    for (int i = 0; i < 4; i++) {
			sh.add(i);
		}
	   // sh.print(sh.head);
	   // System.out.println(sh.getLength(sh.head));
	   // System.out.println(sh.findLastNode(sh.head, 3).data);
	   //sh.print(sh.reverseList(sh.head));
	    sh.add(sh.head);
	    System.out.println(sh.hasCycle(sh.head));
	    System.out.println(sh.hasCycle(sh.head));
	    System.out.println(sh.getCycleLength(sh.head));
	    System.out.println(sh.getCycleStart(sh.head, sh.getCycleLength(sh.head)).data);	      
//	    test32 sh1 = new test32();
//	    for (int i = 6; i < 8; i++) {
//			sh1.add(i);
//		} 
//	    sh.print(sh.getMergeLinkList(sh.head, sh1.head));
	    
	}
}

 

 

 

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、查找 1. 算法设计 :已知n元顺序表a0, a1, … , an-1按关键字递增有序存储。给定关键字值key,编写算法用对分查找下标i,满足ai-1<key且aikey。 2. 编程:输入n个两两互不相等的整数,以这些整数为关键字建立平衡的二叉排序树。判断该二叉树是否为平衡的,输出判断结果;输出该二叉树的中序遍历关键字访问次序。 3. 从空树起连续插入以下20个关键字构建m=4的B-树。 50, 15, 09, 18, 03, 85, 33, 72, 48, 22, 91, 88, 11, 99, 06, 56, 68, 77, 43, 36。 4. 16个关键字组成的5阶B-树如下图所示,请按关键 字递减的次序删除所有结点至空树,画出每删除1个关键字后得到B-树,直至空树。 5. 12个关键字如本电子教案例1所示,设H(K)=K mod 13,地址空间范围0~15,用二次探测再散列解决冲突。画出哈希表;若各元素等概率查找,成功查找时的平均查找长度。 二、内部排序 1.算法设计与分析:将直接插入排序的内循环改造为使用对分查找实现元素插入,请写出基于对分查找的插入排序算法并给出其时间复杂度分析。 2.算法设计:将教案给出的非递归直接插入排序和冒泡排序算法用递归算法实现。 3.算法设计:带附加头结点链表将各数据结点按关键字升序连接。 4.编程:键盘输入n个无符号整数,用链式基数排序实现由小到大排序,输出排序结果。 提示:对于C语言32bit宽的unsigned型,可以采用16进制形式来实现基数排序,即32bit共有8个16进制位,每个16进制位进行一趟分配和收集,共8趟。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值