一直都是用c来实现单链表的基本操作和算法的,今天突然想使用Java来实现下,想起早上面试的穆迪姐姐,说写博客是很好的习惯,很受鼓舞,所以利用晚上的时间简单整理了下。
package linknode;
import java.util.Scanner;
import java.util.Stack;
/**
*
* @author helloway
* java中链表的基本操作与算法
* 1. 求单链表中结点的个数: getListLength
* 2. 将单链表反转: reverseList(非递归)
* 3. 查找单链表中倒数第K个节点: findkthNode
* 4. 查找单链表的中间节点: findMiddleNode
* 5. 从尾到头打印单链表: reversePrintStack(非递归),reversePrintR(递归)
* 6. 合并两条各自有序的单链表(递归): mergeR(递归), merge(非递归)
* 7. 对单链表进行排序,listSort(归并),insertionSortList(插入)
* 8. 判断一个单链表中是否有环: hasCycle
* 9. 已知一个单链表中存在环,求进入环中的第一个节点: entryNodeOfLoop
* 10. 单链表排序,insertSortList(插入)
*/
public class MyLinklist {
public static class Node{
int val;
Node next;
public Node(int val){
this.val=val;
}
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
Node head=null;
Node temp=null;
while (scan.hasNextInt()) {
int val=scan.nextInt();
if (val==0) {
break;
}
if (head==null) {
head = new Node(val);
temp=head;
}else {
temp.next=new Node(val);
temp=temp.next;
}
}
scan.close();
MyLinklist myLinklist = new MyLinklist();
//求单链表中结点的个数: getLength
//System.out.println(myLinklist.getLength(head));
//求反转后的单链表: reverseList(非递归)
//System.out.println(myLinklist.reverseList(head).val);
//查找单链表中倒数第K个节点: findkthNode
//System.out.println(myLinklist.findkthNode(head,3).val);
//查找单链表的中间节点: findMiddleNode
//System.out.println(myLinklist.findMiddleNode(head).val);
//从尾到头打印单链表: reversePrintR(递归)
//myLinklist.reversePrintR(head);
//从尾到头打印单链表: reversePrintStack(利用栈,非递归遍历)
//myLinklist.reversePrintStack(head);
//判断单链表是否有环
//System.out.println(myLinklist.hasCycle(head));
}
//求单链表中结点的个数: getLength
public int getLength(Node head) {
int len=0;
if (head==null) {
return len;
}
Node node = head;
while (node!=null) {
len++;
node=node.next;
}
return len;
}
//求反转后的单链表: reverseList(非递归)
public Node reverseList(Node head){
Node reverseHead = null;
Node pNode = head;
Node pPrev = null;
while (pNode!=null) {
Node pNext = pNode.next;
if (pNext==null) {
reverseHead=pNode;
}
pNode.next = pPrev;
pPrev = pNode;
pNode=pNext;
}
return reverseHead;
}
//求单链表中倒数第K个节点: findkthNode
public Node findkthNode(Node head,int k){
if (head==null||k<=0) {
return null;
}
Node fst = head;
for (int i = 0; i < k-1; i++) {
if (fst.next!=null) {
fst=fst.next;
}else {
return null;
}
}
Node sec = head;
while(fst.next!=null){
fst=fst.next;
sec=sec.next;
}
return sec;
}
//查找单链表的中间节点: findMiddleNode
public Node findMiddleNode(Node head){
if (head==null||head.next==null) {
return head;
}
Node fst = head;
Node sec = head;
while (fst.next!=null&&fst.next.next!=null) {
fst=fst.next.next;
sec=sec.next;
}
return sec;
}
//从尾到头打印单链表: reversePrintR(递归)
public void reversePrintR(Node head) {
if (head==null) {
return;
}
reversePrintR(head.next);
System.out.println(head.val);
}
//从尾到头打印单链表: reversePrintStack(利用栈,非递归遍历)
public void reversePrintStack(Node head) {
Stack<Node> myStack = new Stack<Node>();
while (head!=null) {
myStack.push(head);
head=head.next;
}
while (!myStack.isEmpty()) {
System.out.println(myStack.pop().val);
}
}
//判断单链表是否有环,快慢指针
public boolean hasCycle(Node head){
boolean flag=false;
if (head==null) {
return flag;
}
Node slow = head.next;
if (slow.next==null) {
return flag;
}
Node fst = slow.next;
while (slow!=null&&fst!=null) {
if (fst==slow) {
flag=true;
return flag;
}
slow=slow.next;
fst=fst.next;
if (fst!=null) {
fst=fst.next;
}
}
return flag;
}
//快慢指针,找到有环链表中快慢指针第一次相遇的节点
public Node meetingNode(Node head) {
if (head==null) {
return null;
}
Node slow = head.next;
if (slow==null) {
return null;
}
Node fast = slow.next;
while (slow!=null && fast!=null) {
if (slow==fast) {
return fast;
}
slow=slow.next;
fast=fast.next;
if (fast!=null) {
fast=fast.next;
}
}
return null;
}
//求环的第一个入口节点
public Node entryNodeOfLoop(Node head) {
Node meetingNode = meetingNode(head);
if (meetingNode==null) {
return null;
}
int loopNodeNum=1;
Node pNode1 = meetingNode;
while (pNode1.next!=meetingNode) {
pNode1=pNode1.next;
++loopNodeNum;
}
pNode1 = head;
for (int i = 0; i < loopNodeNum; i++) {
pNode1 = pNode1.next;
}
Node pNode2 = head;
while (pNode1!=pNode2) {
pNode1=pNode1.next;
pNode2=pNode2.next;
}
return pNode1;
}
//合并两条各自有序的单链表(递归)
public Node mergeR(Node head1,Node head2){
if (head1==null) {
return head2;
}else if (head2==null) {
return head1;
}
Node mergeHead = null;
if (head1.val<head2.val) {
mergeHead=head1;
mergeHead.next=mergeR(head1.next, head2);
}else {
mergeHead=head2;
mergeHead.next=mergeR(head1, head2.next);
}
return mergeHead;
}
//两条单链表合并(非递归)
public Node merge(Node head1,Node head2){
if (head1==null) {
return head2;
}else if (head2==null) {
return head1;
}
Node tmp = null;
if (head1.val<head2.val) {
tmp=head1;
head1=head1.next;
}else {
tmp=head2;
head2=head2.next;
}
Node mergeHead = tmp;
while (head1!=null&&head2!=null) {
if (head1.val<head2.val) {
tmp.next=head1;
head1=head1.next;
}else {
tmp.next=head2;
head2=head2.next;
}
tmp=tmp.next;
}
if (head1!=null) {
tmp.next=head1;
}
if (head2!=null) {
tmp.next=head2;
}
return mergeHead;
}
//链表的插入排序
//1、使用一个指针p指向未排好序的链表的第一个结点
//2、在排序好的部分中找到找第一个大于等于q的前驱结点
//3、将p对应的结点插入到正确位置,p重新指向未排好序的链表的第一个结点。直到链表完成排序好。
public Node insertSortList(Node head) {
Node root = new Node(0); // 头结点
root.next = head;
Node p = head;
Node q;
Node r;
while (p != null && p.next != null) {
if (p.val <= p.next.val) {
p = p.next;
}else {
q = p.next;
p.next = q.next;
r = root;
// 找第一个大于等于q.val的前驱结点,因为在root.next到p之间必定存在这样的结点
while (r.next.val <= q.val) {
r = r.next;
}
q.next = r.next;
r.next = q;
}
}
return root.next;
}
}