Java基础数据结构——链表与顺序表

本文深入探讨了抽象数据类型的定义及其实现方式,包括顺序表、单链表和双向链表的具体实现代码。通过这些实现,读者可以更好地理解如何在Java中创建和使用这些基本的数据结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

抽象数据类型

所谓抽象数据类型,就是带有一组操作的对象的集合。一般常有的操作是增(add)、删(delete)、包含(contains)、查(find)。我们常用的一些数据结构类型有表、栈、队列等等,这也是数据结构中最为基本的类型。
这些东西老是没法熟记,要写的时候虽然也能憋出来,总觉得不够畅快。
这里先说下表,表一般是两种类型,以数组为核心的顺序表和以抽象节点为核心的链表。
先说下顺序表。

顺序表以一个数组作为存储数据对象的容器,一个int作为下标,一个int属性作为容量。具有增、删、查、包含等基本操作功能,除此之外,需要具备校验下标是否有效、是否超界等基本功能。
/**
 * Created by ASCEND on 2016/12/1.
 */
public class ArrayList <E>{

    private static int DEFAULT_CAPACITY=10;
    private int size;
    private E[] data;

    public ArrayList(){
        clear();
    }

    private void clear() {
        size=0;
        ensureCapacity(DEFAULT_CAPACITY);
    }

    public int size(){
        return size;
    }

    public boolean isEmpty(){
        return size==0;
    }

    public void trimToSize(){
        ensureCapacity(size());
    }

    public E get(int index){
        validateIndex(index);
        return data[index];
    }

    public void set(int index,E element){
        validateIndex(index);
        data[index]=element;
    }

    public boolean add(E element) {
        data[size+1]=element;
        size++;
        return true;
    }

    public void insert(int index, E element) {
        if (data.length==size())
            ensureCapacity(size()*2-1);
        for (int i = size; i > index; i--) {
            data[i]=data[i-1];
        }
        data[index]=element;
        size++;
    }

    public boolean remove(int index){
        validateIndex(index);
        for (int i = index; i <size-1 ; i++) {
            data[i]=data[i+1];
        }
        size--;
        return true;
    }

    private void validateIndex(int index) {
        if (index<0||index>size){
            throw new ArrayIndexOutOfBoundsException();
        }
    }

    
public void ensureCapacity(int newCapacity) {
    if (newCapacity<size)
        return;
    E [] old=data;
    data= (E[]) new Object[newCapacity];
    for (int i = 0; i < size; i++) {
        data[i]=old[i];
    }
}
}
Java Collection类库中的表都实现了Iterable接口,这边其实也可以实现。但是偷懒,懒得写了。
下面是LinkedList的实现。链表的实现关键在于实现一个节点,这个节点应当有后继,当然还有双链表,也就是说,既有前驱,也有后继。节点能够存储数据,同时还能够存储到下一个节点的指针。依照严肃的说法,即是说,具有数据域和指针域两个部分组成。链表的头和尾节点应当是null。
package ADT;

/**
 * Created by ASCEND on 2016/11/3.
 */
class Node<E>{
    private E e;
    private Node next;

    public Node(){

    }

    public Node(E e){

    }

    public E getValue(){
        return e;
    }
    public void setValue(E e){
        this.e=e;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }

    public String toString(){
        return ""+e;
    }
}
public class LinkedList<E> {
    private Node<E> head=null;
    private Node<E> tail=null;
    private int size=0;

    LinkedList(){
        head=new Node<E>();
        tail=head;
    }

    public boolean add(E e){
        Node<E> node=new Node<E>(e);
        tail.setNext(node);
        ++size;
        return true;
    }

    public boolean insert(int index,E e){
        validateIndex(index);
        Node<E> newNode=new Node<E>(e);
        Node preNode=getNode(index-1);
        newNode.setNext(preNode.getNext());
        preNode.setNext(newNode);
        return true;
    }

    public Node<E> getNode(int index){
        validateIndex(index);
        Node<E> node=head;
        for (int p = 0; p <=index ; p++) {
            node.getNext();
        }
        return node;
    }

    public E get(int index){
        validateIndex(index);
        Node<E> node=getNode(index);
        return node.getValue();
    }

    private void validateIndex(int index){
        if (index<0||index>size){
            throw new RuntimeException("无效的下标:"+index);
        }
    }

    public boolean delete(int index){
        Node<E> curNode=null;
        if (0==index){
            curNode=head.getNext();
            Node<E> nextNode=curNode.getNext();
            head.setNext(nextNode);
        }else{
            validateIndex(index);
            curNode=getNode(index);
            Node<E> preNode=getNode(index-1);
            preNode.setNext(curNode.getNext());
        }
        curNode.setNext(null);
        return true;
    }
}
下面是双向链表
package ADT.DoubleLinkList;

/**
 * Created by ASCEND on 2017/3/2.
 */

public class DoubleLinkList<T> {
    private class DualNode<T>{
        private DualNode<T> prior;
        private DualNode<T> next;
        private T data;

        public DualNode(){

        }

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

        public DualNode getPrior() {
            return prior;
        }

        public void setPrior(DualNode prior) {
            this.prior = prior;
        }

        public DualNode getNext() {
            return next;
        }

        public void setNext(DualNode next) {
            this.next = next;
        }

        public T getData() {
            return data;
        }

        public void setData(T data) {
            this.data = data;

        }
    }

    private int size;
    private DualNode beginMarker;
    private DualNode endMarker;
    private int modCount;


    public int size(){
        return size;
    }

    public boolean isEmpty(){
        return size==0;
    }

    public boolean add(T x){
        add(size,x);
        return true;
    }

    private void add(int idx, T x) {
        addBefore(getDualNode(idx),x);
    }
    public T get(int idx){
        return getDualNode(idx).data;
    }

    public T set(int idx,T newVal){
        DualNode p=getDualNode(idx);
        T oldVal= (T) p.data;
        p.data=newVal;
        return oldVal;
    }

    public T remove(int idx){
        return remove(getDualNode(idx));
    }

    private T remove(DualNode<T> p){
        p.next.prior=p.prior;
        p.prior.next=p.next;
        size--;
        modCount++;
        return p.data;
    }

    private DualNode<T> getDualNode(int idx) {
        DualNode<T> p;
        if (idx<0||idx>size){
            throw new IndexOutOfBoundsException();
        }
        if (idx<size()/2){
            p=beginMarker.next;
            for (int i=0;i<idx;i++)
                p=p.next;
        }else{
            p=endMarker;
            for (int i=size();i>idx;i--)
                p=p.next;
        }
        return p;
    }

    private void addBefore(DualNode<T> p,T data){
        DualNode<T> newNode=new DualNode<T>(data,p.prior,p);
        newNode.prior.next=newNode;
        p.prior=newNode;
        size++;
        modCount++;
    }

    public void clear(){
        beginMarker=new DualNode(null,null,null);
        endMarker=new DualNode(null,beginMarker,null);
        beginMarker.next=endMarker;
        size=0;
        modCount++;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值