数据结构(二)--- 线性表链表(单链表)java实现方式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33127597/article/details/79686517

线性表的链式存储结构:所有元素不考虑相邻位置,哪有空位置就到那里,而只是让每个元素知道它下一个元素的位置在那里,这样,我们可以在第一个元素时,就知道第二个元素的位置(内存地址),而找到它;在第二个元素时,再找到第三个元素的位置,这样所有的元素就可以通过遍历而找到。
这里写图片描述
链表中的第一个结点的存储位置叫做头指针,最后一个结点的指针为空
这里写图片描述
在单链表的第一个结点前附设一个结点,称为头结点
这里写图片描述
单链表的插入和删除
这里写图片描述
删除操作:
插入元素e的结点为s,只需要将s插入到结点P 和p.next之间就行。
s.next=p.next p.next=s
这里写图片描述
如果将p.next=s;再 s.next=p.next; 第一句p.next会覆盖s的地址,就等于s.next=s,真正拥有ai+1数据元素的结点就没上级了,要注意。不能写反。
删除操作:
这里写图片描述
删除ai元素时,只需要将ai+1指向ai-1就可以。
单链表LinkList

package likend;

/**
 * Created by yxf on 2018/3/24.
 * 线性表 单链表
 */
public class LinkList<T> {

    private Node header;//保存头结点
    private int size;  //链表长度

    public class Node<T> {
        private T data;   //数据
        private Node next; //指向下一个节点的引用

        public Node() {
        }

        public Node(T data, Node next) {
            this.data = data;
            this.next = next;
        }
    }

    public LinkList() {
    }

    /**
     * 在头结点插入
     * 链表中第一个结点存储位置叫做头指针 头节点只存储头指针
     * 所以这是插入的是第一个节点
     *
     * @param element
     * @return
     */
    public boolean addHead(T element) {
        //如果第一个链表为空
        if (header == null) {
            header = new Node(element, null);
        } else {
            Node newNode = new Node(element, null);
            Node temp = header;
            newNode.next = temp;    //将新插入的节点的next指向头节点的下一个节点
            header = newNode;  //将新插入的节点指向头结点的下一个节点  链表就链接上了
        }
        size++;
        return true;
    }

    /**
     * 在尾部插入
     *
     * @param element
     * @return
     */
    public boolean add(T element) {
        //如果第一个链表为空
        if (header == null) {
            header = new Node(element, null);
        } /*else {
            int length = getSize();
            Node currentNode = getNodeByIndex(length-1);
            Node newNode = new Node(element, null);
            currentNode.next = newNode;
        }*/ else {
            Node currentNode = header;
            while (currentNode.next != null) {
                currentNode = currentNode.next; //找到添加结点的上一个结点
            }
            Node newNode = new Node(element, null);
            currentNode.next = newNode;
        }
        size++;
        return true;
    }

    /**
     * 获取指定位置结点
     *
     * @param index
     * @return
     */
    public Node getNodeByIndex(int index) {
        if (index < 0 || index > size) {
            throw new IndexOutOfBoundsException("获取位置超过链表长度范围");
        }
        Node current = header; //从链表第一个遍历 因为头结点是指针
        for (int i = 0; i <= size && current != null; i++, current = current.next) {
            if (i == index)
                return current;
        }
        return null;
    }

    /**
     * 获取指定索引处的元素
     *
     * @param index
     * @return
     */
    public T getElement(int index) {
        return (T) getNodeByIndex(index).data;
    }

    public int getIndex(T element) {
        Node current = header;
        for (int i = 0; i < size && current != null; i++, current = current.next) {
            if (current.data.equals(element))
                return i;
        }
        return -1;
    }

    /**
     * 在指定位置插入元素
     *
     * @param index
     * @param element
     * @return
     */
    public boolean insert(int index, T element) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("插入位置超出链表范围");
       /* //如果第一个链表为空
        if (header == null) {
            add(element);
        } else {
            if (index == 0) {
                addHead(element);
            } else {
                //获取插入位置的前一个结点
                Node preNode = getNodeByIndex(index - 1);
                preNode.next = new Node(element, preNode.next);
                size++;
            }
        }*/
        if (index == 0) {
            addHead(element);
        } else {
            Node preNode = header;
            for (int i = 0; i < index - 1; i++) {
                preNode = preNode.next;     //获得插入结点的前驱结点
            }
            Node newNode = new Node(element, null);
            newNode.next = preNode.next;
            preNode.next = newNode;
            size++;
        }
        return true;
    }

    /**
     * 删除元素
     *
     * @param index
     * @return
     */
    public T delete(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("删除位置超出链表范围");
       /* Node delNode = null;
        //删除的是第一个节点
        if (index == 0) {
            delNode = header;
            header = header.next;
        } else {
            Node preNode = getNodeByIndex(index - 1); //获取删除结点的上一个结点
            delNode = preNode.next;                   //获取要删除的结点
            preNode.next = delNode.next;              //将要删除结点的下一个结点赋值给删除结点的上一个结点
        }*/
        Node currentNode = header;
        if (index == 0) {
            header = header.next;
            currentNode.next=null;
        } else {
            Node currentNodeBefore = null;
            for (int i = 0; i < index; i++) {
                currentNodeBefore = currentNode;  //前置结点
                currentNode = currentNode.next;   //要删除的当前结点
            }
            currentNodeBefore.next = currentNode.next;
        }
        size--;
        return (T) currentNode.data;
    }

    /**
     * 获取指定元素的前驱
     *
     * @param currentElem
     * @return
     */
    public T priorElement(T currentElem) {
        int index = getIndex(currentElem);
        if (index == -1)
            return null;
        else {
            if (index == 0) {
                return null;
            } else {
                return (T) getNodeByIndex(index - 1).data;
            }
        }
    }

    /**
     * 获取指定元素的后驱
     *
     * @param currentElem
     * @return
     */
    public T nextElement(T currentElem) {
        int index = getIndex(currentElem);
        if (index == -1)
            return null;
        else {
            if (index == size - 1) {
                return null;
            } else {
                return (T) getNodeByIndex(index + 1).data;
            }
        }
    }

    //删除最后一个元素
    public T remove() {
        return delete(size - 1);
    }

    /**
     * 获取链表大小
     *
     * @return
     */
    public int getSize() {
        return size;
    }

    //检查链表是否为空
    public boolean isEmpty() {
        return size == 0;
    }

    public void clear() {
        header = null;
        size = 0;
    }

    @Override
    public String toString() {
        if (isEmpty())
            return "[]";
        else {
            StringBuilder sb = new StringBuilder("[");
            for (Node current = header; current != null; current = current.next)
                sb.append(current.data + "->").toString();
            int len = sb.length();
            return sb.delete(len - 2, len).append("]").toString();
        }
    }
}

测试 LinkListTest

package likend;

/**
 * Created by yxf on 2018/3/25.
 */
public class LinkListTest {

    public static void main(String[] args) {
        LinkList ls = new LinkList();

        ls.add(2);
        ls.add(4);
        ls.add(5);
        ls.addHead(1);
        System.out.println("添加元素后的链表为: "+ls);
        ls.insert(3,3);
        System.out.println("在链表位置3插入元素: "+ls);
        ls.delete(3);
        System.out.println("在链表位置3删除元素: "+ls);
        ls.remove();
        System.out.println("删除链表中的一个元素: "+ls);
        System.out.println("获得链表位置为2处的元素:   "+ ls.getElement(2));
        System.out.println("获取元素2的前驱元素:    "+ls.priorElement(2));
        System.out.println("获取元素2的后驱元素:    "+ls.nextElement(2));
        ls.clear();
        System.out.println(ls);
    }
}

测试结果

添加元素后的链表为: [1->2->4->5]
在链表位置3插入元素: [1->2->4->3->5]
在链表位置3删除元素: [1->2->4->5]
删除链表中的一个元素: [1->2->4]
获得链表位置为2处的元素:   4
获取元素2的前驱元素:    1
获取元素2的后驱元素:    4
[]

Process finished with exit code 0

猜你喜欢

转载自blog.csdn.net/qq_33127597/article/details/79686517
今日推荐