编程导航算法通关村第1关青铜教程学习

编程导航算法通关村第1关|青铜教程学习

1 构造链表定义

链表是一种物理单元上非连续、非顺序,但逻辑存储结构上连续的一种数据结构。

链表结点:由值和后继结点地址组成独立单元

头结点:链表的第一个元素,获得头结点就可以遍历整个链表

虚拟结点:dummyNode.next = next,方便处理头结点问题

//链表的后继结点是唯一的,前驱结点可以不唯一
public class ListNode {
    public int val;	//该结点值
    public ListNode next;	//后继结点的地址

    public ListNode(int x) {
        val = x;
        next = null;
    }

    public static void main(String[] args) {
        ListNode listnode=new ListNode(1);
    }
}

2 根据指定数组初始化链表

public class BasicLink {

    public static void main(String[] args) {
        Integer[] a = {1, 2, 3, 4, 5, 6};
        Node<Integer> head = initLinkedList(a);
        String[] strings = {"小红","小敏","小王","小孙"};
        Node<String> head1 = initLinkedList(strings);
        System.out.println(head);
        System.out.println(head1);
    }

    /**
     * val:存放当前结点的值
     * next:存放后继结点的地址
     * Node(int x):构造器,初始化结点
     */
    static class Node<T> {
        public T val;
        public Node<T> next;

        public Node(T x){
            val = x;
            next = null;
        }
    }

    /**
     * 根据指定数组初始化链表
     * @param arr:数组
     * @return 链表头结点的地址
     */
    private static <T> Node<T> initLinkedList(T[] arr){
        Node<T> head = null;
        Node<T> cur = null;

        for(int i = 0; i < arr.length; i++){
            if(i == 0){
                head = new Node<>(arr[0]);
                cur = head;
            }else {
                Node<T> newNode = new Node<>(arr[i]);
                cur.next = newNode;
                cur = newNode;
            }
        }
        return head;
    }

3 链表增加与删除结点

public class BasicLinkList {

    static class Node {
        public int val;
        public Node next;

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

    public static void main(String[] args) {
        // 头部添加节点1
        Node head = new Node(1);
        System.out.println("头部添加节点1:" + BasicLinkList.toString(head));

        System.out.println("链表长度为:" + getLength(head));
        // 尾部添加节点2
        Node node = new Node(2);
        head = BasicLinkList.insertNode(head, node, 2);
        System.out.println("尾部添加节点2:" + BasicLinkList.toString(head));
        System.out.println("链表长度为:" + getLength(head));
        // 中间添加节点3
        node = new Node(3);
        head = BasicLinkList.insertNode(head, node, 2);
        System.out.println("中间添加节点3:" + BasicLinkList.toString(head));

        // 删除中间节点2
        head = BasicLinkList.deleteNode(head, 2);
        System.out.println("删除中间节点3:" + BasicLinkList.toString(head));

        // 删除头部节点1
        head = BasicLinkList.deleteNode(head, 1);
        System.out.println("删除头部节点1:" + BasicLinkList.toString(head));
    }

    /**
     * 遍历链表,获取链表长度
     * @param head
     * @return
     */
    public static int getLength(Node head){
        int length = 0;
        Node cur = head;
        while (cur!=null){
            //当前结点不为空,长度+1
            length++;
            cur = cur.next;
        }
        return length;
    }

    /**
     * 根据position插入结点:
     *      1:表头插入
     *      2:其他位置插入(中间位置插入和尾部插入一样都需要遍历位置之前的链表)
     * @param head:链表头结点
     * @param newNode:待插入结点
     * @param position:待插入位置
     * @return 链表头结点
     */
    public static Node insertNode(Node head, Node newNode, int position){
        //避免空指针异常
        if(head == null){
            return newNode;
        }

        int size = getLength(head);

        //插入位置校验 合法插入:1~n+1
        if(position > size+1 || position < 1){
            System.out.println("IllegalPositionError!");
            return head;
        }

        //1.表头插入
        if(position == 1){
            newNode.next = head;
            head = newNode;

            return head;
        }

        //2.其他位置插入,需要获取要插入位置前1位的Node
        int count = 1;
        Node cur = head;
        while (count < position - 1){//count = position-1时循环终止
            count++;
            cur = cur.next;
        }
        newNode.next = cur.next;
        cur.next = newNode;

        return head;
    }

    /**
     * 链表删除结点
     * @param head
     * @param position
     * @return
     */
    public static Node deleteNode(Node head,int position){
        if(head == null){
            return null;
        }

        int size = getLength(head);

        //删除位置校验,合法位置:1~n
        if(position < 1 || position > size){
            System.out.println("IllegalPositionError!");
            return head;
        }

        //1.头结点删除
        if(position == 1){
            //原先的head因为没有任何引用,被JVM的垃圾回收机制销毁,所以可以不写head = null
            return head.next;
        }

        int count = 1;
        Node cur = head;
        while (count < position - 1){
            cur = cur.next;
            count++;
        }
        cur.next = cur.next.next;//中间位置和尾部位置一样
        return head;
    }

    public static String toString(Node head){
        StringBuilder builder = new StringBuilder();
        Node cur = head;
        while (cur!=null){
            builder.append(cur.val);
            builder.append("\t");
            cur = cur.next;
        }
        return builder.toString();
    }
}

4 双向链表

public class DoubleLinkedList {
    static class Node{
        final int val;
        Node pre;	//前驱结点
        Node next;	//后继结点

        Node(int val){
            this.val = val;
            pre = null;
            next = null;
        }
    }

    public static void main(String args[]){
        // 头部添加节点1
        Node head = new Node(1);
        System.out.println("头部添加节点1:" + toString(head));

        System.out.println("链表长度为:" + getLength(head));
        // 尾部添加节点2
        Node node = new Node(2);
        head = insertNode(head, node, 2);
        System.out.println("尾部添加节点2:" + toString(head));
        System.out.println("链表长度为:" + getLength(head));
        // 中间添加节点3
        node = new Node(3);
        head = insertNode(head, node, 2);
        System.out.println("中间添加节点3:" + toString(head));

        // 删除中间节点2
        head = deleteNode(head, 2);
        System.out.println("删除中间节点3:" + toString(head));

        // 删除头部节点1
        head = deleteNode(head, 1);
        System.out.println("删除头部节点1:" + toString(head));

    }

    /**
     * 获取双向链表长度
     * @param head
     * @return
     */
    public static int getLength(Node head){
        int length = 0;
        Node cur = head;
        while (cur!=null){
            cur = cur.next;
            length++;
        }
        return length;
    }

    /**
     * 双向链表增加结点
     * @param head
     * @param newNode
     * @param position
     * @return
     */
    public static Node insertNode(Node head, Node newNode, int position){
        if (head == null){
            return newNode;
        }

        int size = getLength(head);

        //假如位置从1开始,合法位置为1~n+1
        if(position < 1 || position > size+1){
            System.out.println("IllegalPositionError!");
            return head;
        }

        //1.表头插入
        if(position == 1){
            newNode.next = head;
            head.pre = newNode;
            return newNode;
        }

        //2.非表头插入
        int count = 1;
        Node cur = head;
        while (count < position-1){
            cur = cur.next;
            count++;
        }

        //其他位置插入
        if (position != size + 1){
            newNode.next = cur.next;
            cur.next.pre = newNode;
        }
        cur.next = newNode;
        newNode.pre = cur;

        return head;
    }

    /**
     * 双向链表删除结点
     * @param head
     * @param position
     * @return
     */
    public static Node deleteNode(Node head, int position){
        if(head == null){
            return null;
        }

        int size = getLength(head);

        //假如位置从1开始,合法位置为1~n
        if(position < 1 || position > size){
            System.out.println("IllegalPositionError!");
            return head;
        }

        //表头删除,原head将不可达,被回收
        if(position == 1){
            head = head.next;
            head.pre = null;
            return head;
        }

        int count = 1;
        Node cur = head;

        while (count < position - 1){
            cur = cur.next;
            count ++;
        }

        if(position != size){
            cur.next.next.pre = cur.next.pre;
        }
        cur.next = cur.next.next;

        return head;
    }

    public static String toString(Node head){
        StringBuilder builder = new StringBuilder();
        Node cur = head;
        while (cur!=null){
            builder.append(cur.val);
            builder.append("\t");
            cur = cur.next;
        }
        return builder.toString();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值