动态链表 单项链表的实现

一、动态链表

为了表示每个数据元素ai 与其直接后继数据元素ai+1之间的逻辑关系,对
数据元素a1来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息
(直接后的存储位置),我们把 存储 数据元素 信息的域称为数据域,把存储直接后
继位置的称为指针域。针域中存储的信息称做指针或链。这两部分信息组成数据
元素 ai 的存储映像,称为结点(Node)。
n个结点(ai 的存储映像)链结成一个链表,即为线性表(a1,a2,...,an)的链
式存储结构,因为此链表的每个结点中只包一个指针域,所以叫单链表
 

数据域

data

指针域

next


二、头结点VS头指针
头结是指 链表中的第一个结,有真实节点 和 虚拟头节点 之分
真实头节点:其第一个节点用于存储数据(我们这里采用真实头节点
虚拟头节点:其第一个节点不允许存储数据
头指针:仅仅是一个引用变量,存储头节点地址的指针而已

尾指针:同头指针,不过是链表中最后一个节点的指针而已

三、单向链表 LinkedSinglyList

LinkedSinglyList就是线性结构链式存储方式的具体实现,称为单链表
 

四、代码实现

package p3.链式结构;

import p1.接口.List;

import java.util.Comparator;
import java.util.Iterator;

//单向链表
public class LinkedSinglyList<E> implements List<E> {

    //定义一个内部类
    //外部类是链表,内部类是结点
    private class Node {
        E data;//数据域
        Node next;//指针域

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

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

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

        @Override
        public String toString() {
            return data.toString();
        }
    }

    private Node head;//头指针
    private Node tail;//尾指针
    private int size;//元素的个数

    public LinkedSinglyList() {
        head = null;
        tail = null;
        size = 0;
    }

    public LinkedSinglyList(E[] arr) {
        if (arr == null || arr.length == 0) {
            throw new IllegalArgumentException("arr is null");
        }
        for (int i = 0; i < arr.length; i++) {
            add(arr[i]);
        }
    }

    @Override
    public void add(E element) {
        add(size, element);
    }

    @Override
    public void add(int index, E element) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("add index out of range");
        }
        Node n = new Node(element);
        if(size==0){
            head=n;
            tail=n;
        }else if(index==0){//往头部添加,当前指针指向头指针 头指针指向当前指针
            n.next=head;
            head=n;
        }else if(index==size){//往尾部添加,当尾指针指向当前指针 尾指针指向当前指针
            tail.next=n;
            tail=n;
        }else {//往中间某个位置添加  当前指针指向-1位置的指针(此时当前指针指向了下一个) -1位置的指针指向当前
            Node p=head;
            for (int i=0;i<index-1;i++){//将指针移到-1的位置
                p=p.next;
            }
            n.next=p.next;
            p.next=n;
        }
        size++;
    }

    @Override
    public void remove(E element) {
int index=indexof(element);
if(index!=-1){
    remove(index);
}
    }

    @Override
    public E remove(int index) {
        if(index<0 || index>=size){
            throw new IllegalArgumentException("remove index out of range");
        }
        E ret=null;
        if(size==1){//一个元素 先保存值 再将head tail置空
            ret= head.data;
            head=null;
            tail=null;
        }else if(index==0){//头部  保存值 移head 置空
            Node n=head;
            ret=n.data;
            head=n.next;
            n.next=null;
        }else if(index==size-1){//尾部 从头开始找,移动指针p到tail-1 先保存 tail-1位置置空 tail移到p
            Node p=head;
            while (p.next!=tail){
               p= p.next;
            }
            ret=tail.data;
            p.next=null;
            tail=p;
        }else {//中间移除 p移到-1的位置 -1下一个就是当前 将当前的next给-1 保存  则-1指向了下下个 再将当前.next置空
            Node p=head;
            for (int i=0;i<index-1;i++){
                p=p.next;
            }
            Node n=p.next;
            ret=n.data;
            p.next=n.next;
            n.next=null;
        }
        size--;
        return ret;
    }

    @Override
    public E get(int index) {
        if(index<0 || index>=size){
            throw new IllegalArgumentException("get index out of range");
        }
        if(index==0){//头 直接返回头指针的值
            return head.data;
        }else if(index==size-1){//尾 直接返回尾指针的值
            return tail.data;
        }else {//中间 定义一个指针 移到index的位置 (假设是2位置 i=0,i<2 则i取0,1移动两次 0-1-2 刚好到2位置 值为当前指针的data)
            Node p=head;
            for (int i=0;i<index;i++){
                p=p.next;
            }
            return p.data;
        }
    }

    @Override
    public E set(int index, E element) {
        if(index<0 || index>=size){
            throw new IllegalArgumentException("set index out of range");
        }
        E ret=null;
        if(index==0){//头  返回头指针的值,设置头指针的值为当前element
            ret= head.data;
            tail.data=element;
        }else if(index==size-1){//尾 返回尾指针的值,设置尾指针的值为当前element
          ret= tail.data;
          tail.data=element;
        }else {//中间 定义一个指针 移到index的位置 (假设是2位置 i=0,i<2 则i取0,1移动两次 0-1-2 刚好到2位置 值为当前指针的data)
            Node p=head;
            for (int i=0;i<index;i++){
                p=p.next;
            }
            ret=p.data;
            p.data=element;
        }
        return ret;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public int indexof(E element) {//设置指针从head开始,  只要指针的值不等于elemnt 后移,如果p==null说明没找到,返回-1 找到直接返回index即可(index=0 index++ )
        Node p=head;
        int index=0;
        while (!p.data.equals(element)){
            p=p.next;
            index++;
            if(p==null){
                return -1;
            }
        }
        return index;
    }

    @Override
    public boolean contains(E element) {
        return indexof(element)!=-1;//找完返回的值!=-1,就找到了,也就是包含
    }

    @Override
    public boolean isEmpty() {
        return size==0 && head==null && tail==null;
    }

    @Override
    public void clear() {
head=null;
tail=null;
size=0;
    }

    @Override
    public void sort(Comparator<E> c) {
if(c==null){
    throw new IllegalArgumentException("comparator can not be null");
}
//此处为插入排序O(n^3) 同ArrayList  可用,但是时间复杂度太高(里面包含了往回找) 改进顺着找,时间复杂度就会低
        /*
        for (int i = 1; i < size; i++) {
            E e = get(i)
            int j = 0;
            for (j = i; j > 0 && c.compare(get(j-1), e) > 0; j--) {
               set(j,get(j-1));
            }
           set(j,e);
        }
         */

        //选择排序
        if(size==0 || size==1){//一个元素或没有元素 不比较
            return;
        }
        Node nodeA=head;
        Node nodeB=nodeA.next;
        while (true){
            while (true){
                if(c.compare(nodeA.data,nodeB.data)>0){
                    swap(nodeA,nodeB);//交换位置
                }
                if(nodeB==tail){
                    break;//B到了尾部,跳出内层循环
                }
                nodeB=nodeB.next;//指针后移,继续内层比较
            }
            if(nodeA==null){
                break;//A为null,直接跳出外层循环,比较结束
            }
            nodeA=nodeA.next;//A后移,B移到A的后面
            nodeB=nodeA.next;
        }
    }

    private void swap(Node nodeA, Node nodeB) {
        E temp=nodeA.data;
        nodeA.data=nodeB.data;
        nodeB.data=temp;
    }


    @Override
    public List<E> sublist(int fromIndex, int toIndex) {
        if(fromIndex<0 || toIndex>=size || fromIndex>toIndex){
            throw new IllegalArgumentException("must 0<=fromIndex<=toIndex<=size-1");
        }
        LinkedSinglyList<E> list=new LinkedSinglyList<>();
        /*for (int i = fromIndex; i < toIndex; i++) {//O(M)
            list.add(get(i));//O(N)       O(MN)~O(N^2)时间复杂度高
        }*/
        Node nodeA=head;
        for (int i=0;i<fromIndex;i++){
            nodeA=nodeA.next;//移到fromIndex
        }
        Node nodeB=head;
        for (int i=0;i<toIndex;i++){
            nodeB=nodeB.next;//移到toIndex
        }
        Node p=nodeA;
        while (true){
            list.add(p.data);
            if(p==nodeB){
                break;
            }
            p=p.next;
        }
        return list;
    }

    @Override
    public String toString() {
       StringBuilder sb=new StringBuilder();
        sb.append('[');
        if (isEmpty()) {
            sb.append(']');
        } else {
            Node p=head;
           while (true){
                sb.append(p.data);
                if (p==tail) {
                    sb.append(']');
                    break;
                } else {
                    sb.append(',');
                    sb.append(' ');
                    p=p.next;
                }
            }
        }
        return sb.toString();
    }

    @Override
    public Iterator<E> iterator() {
        return new LinkedSinglyListIterator();
    }

    private class LinkedSinglyListIterator implements Iterator<E> {
        private Node cur=head;
        @Override
        public boolean hasNext() {
            return cur!=null;
        }

        @Override
        public E next() {
            E ret= cur.data;
            cur=cur.next;
            return ret;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值