(一)包含头结点的单链表

包含头节点(head)的单链表的学习总结。 头结点是指不包含data,只包含指针的节点。
如有错误的地方,请大家不吝指正。


/**
 * 包含头结点的单链表
 * @author zsk
 *
 */
public class MyList {

    private Node head;//链表的头结点,只有指针,没有数据。
    public MyList(){
        this.head = new Node();
    }

    /**  头插法构建单链表 
     *   头插法可用于将链表逆序。
     * @param data
     */
    public void insertHead(int data){
        Node node = new Node(data);
        Node p = head.next;
        head.next = null;
        node.next = p;
        head.next = node;
    }

    /**  尾插法构建单链表
     * @param data
     */

    public void insertTail(int data){
        Node node = new Node(data);
        Node tempHead = head.next;
        Node tail = null;
        if(tempHead==null){
            tail = head;
        }else{
            while(tempHead!=null){
                tail = tempHead;
                tempHead = tempHead.next;
            }
        }

        tail.next = node;
    }

    /**
     * 判断链表是否为空
     * @return
     */
    public boolean isEmpty(){
        return this.head.next==null?true:false;
    }

    /**
     * 求链表的长度
     * @return
     */
    public int size(){
        int size = 0;
        Node node = head.next;
        while(node!=null){
            size++;
            node = node.next;
        }
        return size;
    }

    /**
     * 根据下标获取节点
     * @param position
     * @return
     */
    public Node getNode(int position){
        int pos = 0;
        Node node = head.next;
        if(position<0||position > size()){
            try {
                throw new Exception("下标越界");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            while(pos != position){
                pos++;
                node = node.next;
            }
        }

        return node;
    }

    /**
     * 为position位置上的节点设置新的值value
     * @param position
     * @param value
     */
    public void set(int position,int value){
        Node settedNode = getNode(position);
        settedNode.setData(value);
    }


    /**
     * 删除给定下标位置上的节点
     * @param position
     */
    public void delete(int position){
        if(position<0||position>size()){
            try {
                throw new Exception("下标越界");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            if(position==0){
                Node p = head.next;
                Node q = p.next;
                head.next = q;
                p.next = null;
            }else{
                Node delPreNode = getNode(position-1);//被删除节点的前一个节点
                Node delNode = getNode(position);
                delPreNode.next = delNode.next;
                delNode.next = null;
            }
        }
    }

    public void append(int position,Node node){
        Node appendNode = getNode(position);
        node.next = appendNode.next;
        appendNode.next = node;
    }

    /**
     * 使用头插法,将链表逆序
     */
    public void revereList(){
        if(this.size()>1){//至少有两个节点,再进行逆序
            Node p = head.next;
            head.next = null;
            while(p!=null){
                Node q = p.next;//记录下p节点的下一个节点
                p.next = head.next;
                head.next = p;
                p = q;//让p节点指向它的下一个节点,重新判断是否需要循环
            }
        }
    }

    /**
     * 使用递归,将链表逆序
     */

    public void revereListByRecursion(){
        Node first = head.next;
        head.next = reverseListFun1(first);//将头结点的下一个节点设置为递归逆序后的第一个节点
    }

    /**  
     * 真正的递归方法,进行逆序
     * @param head
     * @return
     */
    private Node reverseListFun1(Node head){//没有头结点的链表进行逆置(方法1:递归法)
        Node p = head;
        if(null == p)
            return null;
        Node q = p.next;
        if(null == q)
            return p;
        else
            head = reverseListFun1(q);//每次都是返回最后一个节点。

        q.next = p;    //|-- 这两步操作就只是将(锁)链表进行重新排序
        p.next = null; //|--

        return head;
    }

    /**
     * 从前至后打印链表
     * @param head
     */
    public void printList(Node head){
        Node tempHead = head.next;
        while(tempHead!=null){
            System.out.print(tempHead.data + ",");
            tempHead = tempHead.next;
        }
        System.out.println();
    }


    /**
     * 逆序输出链表的值(采用递归的方法)
     * @param head
     */
    public void reversePrintList(Node head){

        /*if(head!=null){
            reversePrintList(head.next);
            System.out.print(head.data+",");
        }*/
        Node first = head.next;
        reversPrint(first);
    }


    /**
     * 对于无头结点的单链表使用的递归方法
     * @param head
     */
    private void reversPrint(Node head){
        if(head!=null){
            reversPrint(head.next);
            System.out.print(head.data+",");
        }
    }


    /**
     * 获取链表的中间节点
     * @param head
     * @return
     */
    public Node getMiddleNode(Node head){
        if(null==head)//链表为空,则返回null
            return null;
        if(null==head.next||null==head.next.next)//链表只有一个节点或两个节点,则返回地一个节点
            return head.next;
        else{
            Node p = head.next;
            Node q = head.next;
            while(q.next!=null){
                q = q.next;
                if(q!=null){
                    q = q.next;
                }

                if(q==null)
                    return p;
                p = p.next;

            }
            return p;
        }

    }

    /**
     * 判断链表是否为循环链表
     * @param head
     * @return
     */
    public boolean isCircle(Node head){
        if(null==head)
            return false;
        if(null==head.next)
            return false;
        if(null==head.next.next)
            return false;

        Node p = head.next;
        Node q = head.next;
        while(true){
            p = p.next;
            q = q.next;
            if(q==null||p==null)
                return false;
            q = q.next;//如果q!=null则q再向后移一格。

            if(q==null)
                return false;
            if(p==q)
                return true;
        }
    }
    /**
     * 
     * 合并两个有序List
     * @param list1
     * @param list2
     * @return
     */
    public static Node mergeList(MyList list1,MyList list2){
        MyList result = new MyList();
        int i = 0;
        int j = 0;
        while(i<list1.size()&&j<list2.size()){
            Node list1_node = list1.getNode(i);
            Node list2_node = list2.getNode(j);
            if(list1_node.data<list2_node.data){
                result.insertTail(list1_node.data);
                i++;
            }
            else{
                result.insertTail(list2_node.data);
                j++;
            }
        }

        while(i<list1.size()){
            result.insertTail(list1.getNode(i).data);
            i++;
        }

        while(j<list2.size()){
            result.insertTail(list2.getNode(j).data);
            j++;
        }
        return result.head;
    }

    public static class Node{
        private int data;
        private Node next;

        public Node(){}
        public Node(int data){
            this.data = data;
            this.next = null;
        }

        public int getData(){
            return this.data;
        }
        public void setData(int data){
            this.data = data;
        }


    }



    public static void main(String[] args){
        MyList myList = new MyList();
        int[] a = {3,1,2,6,3,8,0};
        for(int i=0;i<a.length;i++){
            myList.insertHead(a[i]);
//          myList.insertTail(a[i]);
        }

        System.out.println("是否为空:" + myList.isEmpty());
        System.out.println("链表长度:" + myList.size());
        myList.printList(myList.head);
        myList.revereListByRecursion();
        System.out.println("逆序后输出:" );
        myList.printList(myList.head);
        System.out.println("逆序后下标为3的位置上的值为:" + myList.getNode(3).data);
        System.out.println("逆序后下标为5的位置上的值为:" + myList.getNode(5).data);
//      System.out.println("逆序后下标为5的位置上的值为:" + myList.get(8));
        myList.set(5, 99);
        System.out.println("修改值后链表输出:");
        myList.printList(myList.head);
        myList.delete(5);
        System.out.println("删除下标为5的节点后,链表输出:");
        myList.printList(myList.head);
        myList.delete(0);
        System.out.println("删除下标为0的节点后,链表输出:");
        myList.printList(myList.head);

        System.out.println("在下标为0点节点后插入一个值为78的节点后,链表输出:");
        Node node = new Node(78);//需要将内部类声明为static,否则会有如下的编译错误。因为main函数是静态的,静态只能访问静态。
        //No enclosing instance of type MyList is accessible.
        //Must qualify the allocation with an enclosing instance of type MyList 
        //(e.g. x.new A() where x is an instance of MyList).
        myList.append(0, node);
        myList.printList(myList.head);



        MyList myList1 = new MyList();
        int[] a1 = {1,2,3,4,6};
        for(int i=0;i<a1.length;i++){
            myList1.insertTail(a1[i]);
        }

        MyList myList2 = new MyList();
        int[] a2 = {1,4,6,8,9};
        for(int i=0;i<a2.length;i++){
            myList2.insertTail(a2[i]);
        }

        Node headNode = MyList.mergeList(myList1, myList2);
        System.out.println("");
        myList.printList(headNode);

    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值