• 单链表


    链表
     *  链表由节点组成,节点是由next域连接起来的,每个节点=data+next

     *  同时链表在内存中是不连续的。
      练习1:单链表的增、删、查、改

     *  1)访问某个特定的节点,从头开始去找
     *  2)删除、添加某一个特定的节点到某一个位置,只需要找到前一个节点,即可直接添加/删除
     *  3)链表是一种内存上不连续的数据结构

    class SingleLinekdListTakeHead<E> {
    
        protected Node<E> head;//头节点
    
        class Node<E> {
            protected E data;//数据域
            protected Node<E> next;//next引用域
    
            public Node(E data, Node<E> next) {
                this.data = data;
                this.next = next;
            }
        }
    
        //初始化head
        public SingleLinekdListTakeHead() {
            head = new Node(new Object(), null);
        }
    
        //在head之后直接插入一个节点,头插法
        public void addHead(E element) {
            Node<E> newNode = new Node(element, null);
            newNode.next = head.next;//先让新添加的节点的下一个指向原head节点指向的
            head.next = newNode;//再让head节点指向新节点
        }
    
        //尾插法
        public void addTail(E element) {
            Node<E> newNode = new Node(element, null);
            Node<E> tail = head;//定义一个节点从头走到尾
            //tail走到当前链表的尾部
            while (tail.next != null) {
                tail = tail.next;
            }
            tail.next = newNode;
            newNode.next=null;
        }
    
        /**
         * 固定位置插入一个节点
         * 判断参数合法性
         * 找到pos位置的前一个节点
         * @param pos  固定位置
         * @param element  元素
         */
        public void addPos(int pos, E element) {
            if (pos <= 0 || pos > getLength()) {
                return;
            }
            Node<E> prev = head.next;
            int index = 1;
    
            while (index++ < pos - 1) {
                prev = prev.next;
            }
            Node<E> newNode = new Node<>(element, null);
            newNode.next = prev.next;
            prev.next = newNode;
        }
        //删除元素为element的节点
        public boolean remove(E element) {
            //如果只有一个头结点,返回false
            if (head.next == null) {
                return false;
            }
            //找到该元素所对应的节点 + 该元素所对应的节点的前一个
            //从头结点开始遍历
            Node<E> tmp = head;
    
            while (tmp != null) {
                if (tmp.next != null && tmp.next.data == element) {
                    //tmp.next是我们要删除的节点 tmp是删除节点的前一个
                    tmp.next = tmp.next.next;
                    return true;
                }
                tmp = tmp.next;
            }
            return false;
        }
      //设置某个位置的值为newElement
        public void set(int pos, E newElement){
            if(pos <= 0 || pos > getLength()){
                return;
            }
            //找pos位置的节点
            Node<E> tmp = head.next;
            for(int i=1; i < pos; i++){
                tmp = tmp.next;
            }
            tmp.data = newElement;
        }
         //得到某个元素的值
        public E get(E element){
            Node<E> tmp = head.next;//从有效节点开始遍历
    
            while(tmp != null){
                if(tmp.data == element){
                    return tmp.data; //找到的话,返回该节点
                }
                tmp = tmp.next;
            }
            return null;
        }
        //返回长度
        public int getLength() {
            Node<E> tmp = head.next;
            int length = 0;
            while (tmp != null) {
                length++;
                tmp = tmp.next;
            }
            return length;
        }
         //打印栈
        public String toString() {
            StringBuilder strs = new StringBuilder();
    
            Node<E> tmp = head.next;
            while (tmp != null) {
                strs.append(tmp.data + " ");
                tmp = tmp.next;
            }
            return strs.toString(); //strs是StringBuilder类型,应该添加toString方法,才能返回String类型的
        }
    }
    
    public class Linked {
        public static void main(String[] args) {
            SingleLinekdListTakeHead<Integer> list=new SingleLinekdListTakeHead();
            list.addHead(3);
            list.addHead(5);
            list.addHead(8);
            System.out.println(list.toString());//8 5 3
    
            list.addTail(1);
            list.addTail(2);
            list.addTail(4);
            System.out.println(list.toString());//8 5 3 1 2 4
    
            list.addPos(2, 100); //在2 号位置加入元素100
            System.out.println(list.toString());
            list.addPos(0, 1000);
            System.out.println(list.toString());
    
            list.remove(4);
            System.out.println("删除值为4的元素:"+list.toString());
    
            list.set(2,2);//true,把2号元素的值改为2
            System.out.println("把2号元素的值改为2:"+list.toString());
            System.out.println(list.get(3));
        }
    
    }

     

     具体操作的画图分析:

     练习2:在链表中开始添加n个元素,将链表逆置输出

    public class SingleLinkListExercise {
        public static <E> void reversePrint(Node<E>  head){
            if(head == null){
                return;
            }
            //提取重复的逻辑
            reversePrint(head.next);
            System.out.println(head.data);
        }
        public static void main(String[] args) {
            SingleLinkList<Integer> list = new SingleLinkList<>();
            for(int i=0;i<10;i++) {
    list.add(i);
    }
    reversePrint(list.head);
     }
    }

     练习3:双向链表的增加、删除

    //双向链表的增加、删除
    //双向链表的增加、删除

    /**show方法有空指针异常:需要判断当前节点和它的下一个节点是否都为空
    * @param <E>
    */
    class DoubleLinkList<E>{
    protected Node<E> head;
    protected Node<E> tail;
    class Node<E> {
    protected E data;
    protected Node<E> prev;
    protected Node<E> next;
    public Node(E data,Node<E> prev,Node<E> next){
    this.data = data;
    this.prev = prev;
    this.next = next;
    }
    }
    //尾插法
    public void add(E data){
    Node<E> last=tail;//把目前链表的最后一个节点给last
    Node<E> newNode=new Node<>(data,last,null);//创建新节点的前驱是last,后继为null
    if(last==null){
    head=newNode;
    }else {
    tail.next=newNode;//让tail指向newNode
    }
    tail=newNode;//再把newNode赋给新的tail
    }


    public boolean remove(E data){
    if (head==null){
    return false;
    }
    if(head.next==null){
    head=null;
    tail=null;
    return true;
    }

    //如果删除的是第一个节点
    else if(head.data.equals(data)){
    head=head.next;
    head.prev=null;
    return true;
    }
    //如果删除的是最后一个节点
    else if(tail.data.equals(data)){
    tail=tail.prev;
    tail.next=null;
    return true;
    }else {
    //如果删除的是正常节点
    Node<E> prev = head;
    Node<E> current = head.next;
    while (current != null) {
    if (current.data.equals(data)) { //如果当前节点数据是要找的节点
    prev.next = current.next; //将前一个的节点的next指向当前节点的下一个
    current.next.prev = prev;//当前节点的下一个的前驱指向要删除节点的前一个
    current = null; //将要删除的节点置为null
    return true;
    }
    prev = current;//将两个节点继续向下走
    current = current.next;
    }
    }
    return false;
    }
    //打印链表
    public void show(){
    Node<E> current=head;//定义一个current变量,将head指向current
    while ( current!=null &&current.next!=null){ //需要判断当前节点和下一个都不为空的情况下才能打印链表
    System.out.print(current.data+" ");
    current= current.next;
    }
    if(head!=null){ //如果头结点不为空
    System.out.print(current.data); //将最后一个节点打印
    }else {
    System.out.println("当前链表空!!");
    }
    System.out.println();
    }
    // public void show(){
    // Node<E> current = head;
    //
    // while(current != null){
    // System.out.print(current.data+ " ");
    // current = current.next;
    // }
    // System.out.println();
    // }
    }
    public class DoubleLinkListTest {
    public static void main(String[] args) {
    DoubleLinkList<Integer> d=new DoubleLinkList<>();
    d.add(3);
    d.add(4);
    d.remove(3);
    d.remove(4);
    d.show();

    // System.out.println(d.remove(3));
    // System.out.println(d.remove(5));
    // System.out.println(d.remove(7));
    // System.out.println(d.remove(10));
    // d.show();

    //链表为空后,再一次添加时,要求tail也置为null,再从开始添加
    for(int i=0;i<4;i++) {
    d.add(i+1);
    }
    d.show();
    }
    }

     练习4:单向循环链表

    //不带头节点的单向循环链表
    class LoopSingleLinkedList<E>{
    
        protected Node<E> head;
    
        class Node<E>{
            protected E data;
            protected Node<E> next;
    
            public Node(E data){
                this.data = data;
            }
        }
    
        public void add(E data){
            Node<E> newNode=new Node<>(data);
            //链表为空
            if(head == null){
                head = newNode;
                newNode.next = head;
            }
            //遍历至尾节点
            Node<E> tail = head;
            while(tail.next != head){
                tail = tail.next;
            }
            newNode.next = tail.next;
            tail.next = newNode;
        }
    //输出为data的数据
        public boolean remove(E data){
            //如果头结点为空,返回false
            if (head == null) {
                return false;
            }
            //这里需要判断,如果当前只有一个节点,则将链表置空,直接删除
            if(head.next==head){
                head=null;
                return false;
            }
            //如果删除的是头结点,要先找到尾节点,让尾节点指向头结点的下一个
            Node<E> tail=head;
             if (tail.data == data) {
                while (tail.next != head) {
                    tail=tail.next;
                }
                head=head.next;
                tail.next=head;
    
                return true;
            }
            //删除正常节点
            Node<E> prev = head;//定义一个节点指向头
            Node<E> current = head.next;//再定义要删除的结点指向下一个
            while(current != head){
                if(current.data == data){
                    prev.next = current.next;
                    current = null;
                    return true;
                }
                prev = current;
                current = current.next;
            }
            return false;
        }
    //从头结点开始遍历打印,需要定义一个索引指向头结点
        public void show(){
            Node<E> current=head;
            while (current!=null&&current.next!=head){
                System.out.print(current.data+" ");
                current=current.next;
            }
            if(head==null){
                System.out.println("链表空!");
            }else {
                System.out.println(current.data);
            }
    
        }
    }
    public class LoopSingleLinkedListTest {
        public static void main(String[] args) {
            LoopSingleLinkedList<Integer> l=new LoopSingleLinkedList();
            l.add(3);
            l.add(4);
            l.add(5);
            l.show();
            l.remove(3);
            System.out.println(l.remove(5));
            l.remove(4);
            l.show();
    
        }
    }

  • 相关阅读:
    poj 3258
    CodeForces 367E Sereja and Intervals
    Codeforces Round #240 (Div. 2) C Mashmokh and Numbers
    Codeforces Round #240 (Div. 2) D
    zoj 3768 Continuous Login
    2014/4/4做题感悟
    HDU 1878 欧拉回路
    HDU 3018 Ant Trip
    POJ 3694 Network
    Codeforces Round #239 (Div. 2)
  • 原文地址:https://www.cnblogs.com/laurarararararara/p/11861676.html
Copyright © 2020-2023  润新知