Java_实现单链表

来源:互联网 发布:淘宝旗舰店都是真的吗 编辑:程序博客网 时间:2024/06/03 23:20

单链表的实现

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。

存储原理图

单链表存储原理图

  • 1 单链表的构造以及常用的成员方法
  • 2 判断单链表是否有环问题
  • 3 判断单链表是否相交问题
  • 4 寻找倒数第K个节点

1 单链表的构造以及常用的成员方法

//先构造一个节点类,并给出该类相关的成员变量和成员方法class Node{    int value;    Node next;    public Node(){        this(0);    }    public Node (int value){        this.value = value;        this.next = null;    }}//利用节点类,构造链表类class LinkList{    Node head;    public LinkList(){             head = new Node();    }    //判空    public boolean empty(){            return head.next == null;     }    //头插法    public void insertHead(int val){        Node s = new Node(val);        s.next = head.next;        head.next = s;    }    //尾插法    public void insertTail(int val){        Node n = head;        while (n.next != null){            n = n.next;        }        n.next = new Node(val);    }    //删除一个节点    public void destroy(int value){        Node pcur = head.next;        Node ppre = head;        while(pcur != null){            if(pcur.value == value){                ppre.next = pcur.next;                break;            }            ppre = pcur;            pcur = pcur.next;        }    }    //打印    public String toString(){        StringBuilder builder = new StringBuilder();        Node n = head.next;        while(n != null){            builder.append(n.value+" ");            n = n.next;        }        return builder.toString();    }}

2 判断单链表是否有环问题

(1) 判断当前单链表是否有环 true:有环 false:没有环
思路方法:定义两个快慢指针,步长为一和二,从头结点出发,当相遇时,说明有环;否则没有环

public boolean haveCircle(){        if(this.head ==null || this.head.next==null) return false;         Node p = this.head;        Node q = this.head;        while(p!=null || q!=null)         {              p = p.next;                          q = q.next.next;             if(p == q) return true;         }        return false;    }

(2) 判断单链表是否有环,如果有,需要返回环的入口节点
思路方法:找到快慢指针相遇的节点,该节点到入口节点的距离与头节点到入口节点的距离相等

public Node firstCircleNode(){        if(this.head ==null || this.head.next==null) return null;         Node p = this.head;        Node q = this.head;        while(p!=null || q!=null)         {              p = p.next;                          q = q.next.next;             if(p==q){                q = this.head;                while(p != q){                    p = p.next;                    q = q.next;                }                if(p == q){                    return p;                }            }         }        return null;    }

(3) 判断单链表是否有环,如果有,返回环的节点个数
思路方法:入口结点出发,进行计数,再次回到入口节点时结束

public int getCircleNodeNum(){          Node p = firstCircleNode();        if(p == null) return 0;         Node q = p.next;          int length = 1;          while(p!=q)          {              length++;              q = q.next;          }          return length;    }

3 判断单链表是否相交 true:相交 false:不相交

思路方法:求出两单链表长度的差,长的链表先遍历,从而可以让两链表从同一起点长度开始遍历,若能找出相同的节点说明相交,否则不想交。

public Node isLinkCross(LinkList list){         Node p = this.head;        Node q = list.head;        if (p == null || q == null)  return null;         int length1 = 0;        int length2 = 0;        while(p != null){            length1++;            p = p.next;        }        while(q != null){            length2++;            q = q.next;        }        p = this.head;        q = list.head;        if(length1 > length2){            for(int i =0;i<length1-length2;i++){                p = p.next;            }            while(p != null && q!= null){                if(p.value == q.value){                    break;                }                p = p.next;                q = q.next;            }            return p;        }        else{            for(int i =0;i<length2-length1;i++){                q = q.next;            }            while(p != null && q!= null){                if(p.value == q.value){                    break;                }                p = p.next;                q = q.next;            }            return p;        }    }  

4 寻找倒数第K个节点 没有返回null

思路方法:先求出节点个数,遍历时的次数即为length-k+1

public Node findReverseKNode(int k){        Node p = this.head;        if (empty()) return null;           int length=0;        while(p.next!=null){            length++;            p = p.next;        }        if (k==0 || k>length) return null;        p = this.head;        for (int i=0;i<length-k+1;i++)        {            p = p.next;        }        return p;    }

代码测试

public class TestLinklist {    public static void main(String[] args) {        LinkList s = new LinkList();//初始化        for(int i = 1;i<10;i++){            s.insertHead((int)(Math.random()*100));   //头插法生成单链表        }        System.out.println(s.toString());//打印        System.out.println("倒数第三个节点值为:" + s.findReverseKNode(3).value);        //将链表最后一个节点与第三个节点链接,构成环;        Node p = s.head;        Node q = s.head.next.next.next;        while(p.next != null){            p = p.next;        }        p.next = q;        System.out.println("入口节点为:"+s.firstCircleNode().value);        System.out.println("节点数为:"+s.getCircleNodeNum());        //构造两个交叉的链表        p.next = null;        LinkList s1 = new LinkList();        Node h = s1.head;        for(int i = 1;i<10;i++){            s1.insertHead((int)(Math.random()*100));                }        while(h.next != null){            h = h.next;        }        h.next = q;        System.out.println(s.toString());        System.out.println(s1.toString());        System.out.println("交叉节点为:"+s.isLinkCross(s1).value);    }}
原创粉丝点击