Data Structure-Linear Table (2)

Keywords: Java git Junit

Chain Storage and Implementation of Linear List

  • Another way to implement linear tables is chain storage, which uses pointers to connect the units that store data elements in linear tables in turn. This method avoids the disadvantage of using continuous cells to store elements in arrays, so it is no longer necessary to move elements to make room or fill vacancies when performing insertion or deletion operations. However, the price we pay for this is that we need to set pointers in each cell to represent the logical relationship between elements in the table, thus increasing the overhead of additional storage space.

Singly Linked List

  • A linked list is a series of units that store data elements through pointers, so each unit has at least two domains, one for the storage of data elements and the other for pointers to other units. A storage unit with one data domain and multiple pointer domains is usually referred to as a node.

Node Interface

package com.wjy.Data_Structure.linearlist.common;

public interface Node {
    /**
     * Getting Node Data Domain
     *
     * @return
     */
    public Object getData();

    /**
     * Setting Node Data Domain
     *
     * @param obj
     */
    public void setData(Object obj);
}

Single linked list node definition

package com.wjy.Data_Structure.linearlist.common;

//Single linked list node definition
public class SLNode implements Node {

    private Object element;
    private SLNode next;

    public SLNode() {

    }

    public SLNode(Object ele, SLNode next) {
        this.element = ele;
        this.next = next;
    }

    public SLNode getNext() {
        return next;
    }

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

    /******** Methods of Node Interface **********/
    @Override
    public Object getData() {
        return element;
    }

    @Override
    public void setData(Object obj) {
        element = obj;
    }

}

Realization of Linear List with Single Link List

  • In order to make the program more concise, we usually add a dummy node, also known as the head node, in front of the single linked list when using the single linked list to realize the linear table. No real data objects are stored in the header node. The next domain of the header node points to the node of element 0 in the linear table. The introduction of the header node can make some boundary conditions in the linear table operation easier to handle.
package com.wjy.Data_Structure.linearlist.listslinkimpl;

import com.wjy.Data_Structure.linearlist.common.DefaultStrategy;
import com.wjy.Data_Structure.linearlist.common.List;
import com.wjy.Data_Structure.linearlist.common.SLNode;
import com.wjy.Data_Structure.linearlist.common.Strategy;
import com.wjy.Data_Structure.linearlist.exception.OutOfBoundaryException;

//Realization of Linear List with Single Link List
public class ListSLinked implements List {

    private Strategy strategy; // Data element comparison strategy
    private SLNode head; // Single list header node reference
    private int size;// Number of data elements in a linear table

    public ListSLinked() {
        this(new DefaultStrategy());
    }

    public ListSLinked(Strategy strategy) {
        this.strategy = strategy;
        head = new SLNode();
        size = 0;
    }

    /**
     * Auxiliary Method: Get the precursor node of the node where the data element e is located
     *
     * @param e
     * @return
     */
    private SLNode getPreNode(Object e) {
        SLNode p = head;
        while (p.getNext() != null)
            if (strategy.equal(p.getNext().getData(), e))
                return p;
            else
                p = p.getNext();
        return null;

    }

    /**
     * Auxiliary Method: Get the precursor node of the node where the element with serial number 0<=i<size is located.
     *
     * @param i
     * @return
     */
    private SLNode getPreNode(int i) {
        SLNode p = head;
        for (; i > 0; i--)
            p = p.getNext();
        return p;

    }

    /**
     * Auxiliary method: Obtain the node of the element whose serial number is 0<=i<size
     *
     * @param i
     * @return
     */
    private SLNode getNode(int i) {
        SLNode p = head.getNext();
        for (; i > 0; i--)
            p = p.getNext();
        return p;
    }

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

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

    @Override
    public boolean contains(Object e) {
        return indexOf(e) != -1;
    }

    @Override
    public int indexOf(Object e) {
        SLNode p = head.getNext();
        int index = 0;
        while (p != null)
            if (strategy.equal(p.getData(), e)) {
                return index;
            } else {
                index++;
                p = p.getNext();
            }
        return -1;
    }

    @Override
    public void insert(int i, Object e) throws OutOfBoundaryException {
        if (i < 0 || i > size)
            throw new OutOfBoundaryException("Error, specified insertion number crosses the boundary");
        SLNode p = getPreNode(i);
        SLNode q = new SLNode(e, p.getNext());
        p.setNext(q);
        size++;
        return;

    }

    @Override
    public boolean insertBefore(Object obj, Object e) {
        SLNode p = getPreNode(obj);
        if (p != null) {
            SLNode q = new SLNode(e, p.getNext());
            p.setNext(q);
            size++;
            return true;
        }
        return false;
    }

    @Override
    public boolean insertAfter(Object obj, Object e) {
        SLNode p = head.getNext();
        while (p != null)
            if (strategy.equal(p.getData(), obj)) {
                SLNode q = new SLNode(e, p.getNext());
                p.setNext(q);
                size++;
                return true;
            } else {
                p = p.getNext();
            }
        return false;
    }

    @Override
    public Object remove(int i) throws OutOfBoundaryException {
        if (i < 0 || i >= size)
            throw new OutOfBoundaryException("Error, the specified deletion number crosses the boundary.");
        SLNode p = getPreNode(i);
        Object obj = p.getNext().getData();
        p.setNext(p.getNext().getNext());
        size--;
        return obj;
    }

    @Override
    public boolean remove(Object e) {
        SLNode p = getPreNode(e);
        if (p != null) {
            p.setNext(p.getNext().getNext());
            size--;
            return true;
        }
        return false;
    }

    @Override
    public Object replace(int i, Object e) throws OutOfBoundaryException {
        if (i < 0 || i >= size)
            throw new OutOfBoundaryException("Error. The specified serial number crosses the boundary.");
        SLNode p = getNode(i);
        Object obj = p.getData();
        p.setData(e);
        return obj;
    }

    @Override
    public Object get(int i) throws OutOfBoundaryException {
        if (i < 0 || i >= size)
            throw new OutOfBoundaryException("Error. The specified serial number crosses the boundary.");
        SLNode p = getNode(i);
        return p.getData();
    }

}

Simple test cases

package com.wjy.Data_Structure.linearlist.listslinkimpl;

import org.junit.Test;

import com.wjy.Data_Structure.linearlist.listslinkimpl.ListSLinked;

public class ListSLinkedTest {

    @Test
    public void testInsert() {
        ListSLinked list = new ListSLinked();
        for (int i = 0; i < 10; i++) {
            list.insert(i, i + 1);
        }
        System.out.println("Delete:" + list.remove(0));
        System.out.println(list.contains(1));
        list.insertBefore(2, 100);
        list.insertAfter(2, 101);
        list.replace(list.getSize() - 1, 1000);
        for (int i = 0; i < list.getSize(); i++) {
            System.out.println(list.get(i));
        }

    }

}

Data Structure Learning Code Warehouse:
https://git.oschina.net/wjyonlyone/DataStructure

Posted by kjl-php on Thu, 21 Mar 2019 09:12:52 -0700