数据结构(三) 链表

 

 

package com.company;

public class LinkedList<E> {
    private class Node{
        public E e;
        public Node next;

        public Node(E e, Node next){
            this.e = e;
            this.next = next;
        }

        public Node(E e){
            this(e, null);
        }
        public Node(){
            this(null, null);
        }

        @Override
        public String toString(){
            return e.toString();
        }
    }
    private Node dummyhead;
    private int size;

    public LinkedList(){
        dummyhead = new Node(null, null);
        size = 0;
    }
    //获取链表中元素的个数
    public int getSize(){
        return  size;
    }
    //链表是否为空
    public boolean isEmpty(){
        return size == 0;
    }
    //在链表头添加元素
    public void addFirst(E e){
        add(e,0);
    }
    //在链表中间index位置添加元素
    public void add(E e, int index){
        if(index <0 || index > size)
            throw new IllegalArgumentException("added failed");
        else{
            Node pre = dummyhead;
            for(int i=0; i <index; i++ )
                pre = pre.next;
            //Node node = new Node(e);
            //node.next = pre.next;
           // pre.next = node;
            pre.next = new Node(e, pre.next);
            size++;
        }
    }

    public void addLast(E e){
        add(e, size);
    }

    //获得链表第index位置的元素
    public E get(int index){
        if(index <0 || index > size)
            throw new IllegalArgumentException("get failed");

        Node cur = dummyhead.next;
        for(int i= 0; i<index; i++){
            cur = cur.next;
        }
        return cur.e;
    }
    //获得链表第一个元素
    public E getFirst(){
        return get(0);
    }
    public E getLast(){
        return get(size-1);
    }
    //修改链表第index位置的元素
    public void set(int index, E e){
        if(index <0 || index > size)
            throw new IllegalArgumentException("set failed");

        Node cur = dummyhead.next;
        for(int i= 0; i<index; i++){
            cur = cur.next;
        }
        cur.e = e;
    }
    //查找是否存在元素e
    public boolean contain(E e){
        Node cur = dummyhead.next;
        while(cur != null){
            if(cur.e.equals(e))
                return true;
            cur =cur.next;
        }
        return false;
    }

    @Override
    public String toString(){
        StringBuilder res = new StringBuilder();
        Node cur = dummyhead.next;
        while(cur != null){
            res.append(cur + "->");
            cur = cur.next;
        }
        res.append("null");
        return res.toString();
    }

    //删除index位置的元素
    public E remove(int index){
        if(index <0 || index > size)
            throw new IllegalArgumentException("remove failed");

        Node pre = dummyhead;
        for(int i= 0; i<index; i++){
            pre = pre.next;
        }
        Node retnode = pre.next;
        pre.next = retnode.next;
        retnode = null;
        size--;
        return retnode.e;
    }

    public E removeFirst(){
        return remove(0);
    }
    public E removelast(){
        return remove(size);
    }

}

二 时间复杂度分析

三 链表实现栈

package com.company;

public class LinkedListStack<E> implements Stack<E> {
    LinkedList<E> list;

    public LinkedListStack(){
        list = new LinkedList<>();
    }

    @Override
    public int getSize(){
        return list.getSize();
    }

    @Override
    public boolean isEmpty(){
        return list.isEmpty();

    }

    @Override
    public void push(E e){
        list.addFirst(e);
    }

    @Override
    public E pop(){
        return list.removeFirst();
    }

    @Override
    public E peek(){
        return list.getFirst();
    }

    @Override
    public String toString(){
        StringBuilder res = new StringBuilder();
        res.append("stack: top ");
        res.append(list);
        return  res.toString();
    }

    public static void main(String[] args){
        LinkedListStack<Integer> stack = new LinkedListStack<>();
        for(int i = 0; i< 5; i++){
            stack.push(i);
            System.out.println(stack);
        }

        stack.pop();
        System.out.println(stack);
    }

}

四 链表实现队列

package com.company;

public class LinkedListQueue<E> implements Queue<E> {

    private class Node {
        public E e;
        public Node next;

        public Node(E e, Node next) {
            this.e = e;
            this.next = next;
        }

        public Node(E e) {
            this(e, null)
        }
        public Node() {
            this(null, null);
        }
        @Override
        public String toString(){
            return e.toString();
        }
        ;
    }



    private Node head, tail;
    private int size;
    private LinkedListQueue() {
        head = null;
        tail = null;
        size = 0;
    }

    @Override
    public int getSize(){
        return size;
    }
    @Override
    public boolean isEmpty(){
        return size == 0;
    }
    @Override
    public void enqueue(E e){
        if(tail == null) { //意味着head也为空
            tail = new Node(e);
            head = tail;
        }else{
            tail.next = new Node(e);
            tail  = tail.next;
        }
        size++;
    }

    @Override
    public E dequeue(){
        if(isEmpty())
            throw new IllegalArgumentException("can not dequeue from  an empty queue");
        Node retNode = head;
        head = head.next;
        retNode.next = null;
        if(head == null) // 出队列最后为空了
            tail = null;
        size--;
        return retNode.e;
    }

    public E getFront(){
        if(isEmpty())
            throw new IllegalArgumentException("can not getFront from  an empty queue");
        return head.e;
    }

    public String toString(){
        StringBuilder res = new StringBuilder();
        res.append("Queue: front");
        Node cur = head;
        while(cur != null){
            res.append(cur + "->");
            cur = cur.next;
        }
        res.append("null tail");
        return res.toString();

    }

    
}

五 链表和递归

删除链表中的元素

import java.util.List;

public class Solution {
    public ListNode removeElements(ListNode head, int val){
        while(head != null && head.val == val) {   //假若头节点就是要删除的元素(if) 再后的节点也是 那就到第一个不是要删除元素的节点
            ListNode delNode =head;
            head = head.next;
            delNode = null;
        }
        if(head == null)         //删除完变成空了
            return  null;

        ListNode prev =head;
        while(prev.next != null){
            if(prev.val == val){
                ListNode delNode = prev;
                prev = prev.next;
                delNode = null;
            }
            else
                prev = prev.next;    

        }
        return head;
    }
}

使用虚拟头节点

public class Solution {
    public ListNode removeElements(ListNode head, int val){
        ListNode dummyhead = new ListNode(-1);
        dummyhead.next = head;              //无需对头节点进行特殊处理

       // while(head != null && head.val == val) {   //假若头节点就是要删除的元素(if) 再后的节点也是 那就到第一个不是要删除元素的节点
       //     ListNode delNode =head;
       //     head = head.next;
        //    delNode = null;
        // }
        //if(head == null)         //删除完变成空了
        //    return  null;

        ListNode prev =dummyhead;
        while(prev.next != null){
            if(prev.val == val){
                ListNode delNode = prev;
                prev = prev.next;
                delNode = null;
            }
            else
                prev = prev.next;

        }
        return head;
    }
}

六 链表和递归

public class Solution3 {
    public ListNode removeElements(ListNode head, int val){
        if(head == null)
            return null;
        ListNode res = removeElements(head.next, val);
        if(head.val == val)
            return res;
        else{
            head.next = res;
            return head;
        }
    }

七 递归函数的微观解读

调试样例:

public class Solution3 {
    public ListNode removeElements(ListNode head, int val, int depth){   //删除所有重复的节点 所以最后递归到null
                                                              //如果是删除某个节点递归结束条件可以改一哈
        String depthString = generateDepthString(depth);
        System.out.println(depthString);
        System.out.println("Call: remove" + val + " in " +head);
        if(head == null){
            System.out.print(depthString);
            System.out.println("Return:" + head);
            return null;
        }
        
        ListNode res = removeElements(head.next, val, depth+1);
        System.out.print(depthString);
        System.out.println("After remove:" + val + ":" + res);

        ListNode ret;
        if(head.val == val)
            ret = res;
        else{
            head.next = res;
            ret = head;
        }
        return ret;

    }x

    private String generateDepthString(int depth){
        StringBuilder res = new StringBuilder();
        for(int i=0; i< depth; i++){
            res.append("--");
        }
        return res.toString();
    }


    public static void main(String[] args){
        int[] nums ={1,2,6,3,4,5,6};
        ListNode head = new ListNode(nums);
        System.out.println(head);
        ListNode res = (new Solution3()).removeElements(head,6,0);
        System.out.println(res);
    }
}
public class ListNode {

    public ListNode next;
    public int val;

    public ListNode(int val){
        this.val = val;
    }

    //链表节点的构造函数
    //使用arr为参数 创建一个链表 当前lsitnode为链表头节点
    public ListNode(int[] arr){
        if(arr == null || arr.length == 0){
            throw new IllegalArgumentException("arr  can not  be empty");
        }
        this.val = arr[0];
        ListNode cur = this;
        for(int i=1; i<arr.length; i++){
            cur.next = new ListNode(arr[i]);
            cur = cur.next;
        }
    }
    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        ListNode cur = this;
        while (cur != null){
            sb.append(cur.val + "-->");
            cur = cur.next;
        }
        sb.append("null");
        return  sb.toString();
    }


}

八 更多和链表有关的问题

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值