Cursor Linked List

package com.thealgorithms.datastructures.lists;

import java.util.Objects;

/**
 * This class implements a Cursor Linked List.
 *
 * A CursorLinkedList is an array version of a Linked List. Essentially you have
 * an array of list nodes but instead of each node containing a pointer to the
 * next item in the linked list, each node element in the array contains the
 * index for the next node element.
 *
 */
public class CursorLinkedList<T> {

    private static class Node<T> {

        T element;
        int next;

        Node(T element, int next) {
            this.element = element;
            this.next = next;
        }
    }

    private final int os;
    private int head;
    private final Node<T>[] cursorSpace;
    private int count;
    private static final int CURSOR_SPACE_SIZE = 100;

    {
        // init at loading time
        cursorSpace = new Node[CURSOR_SPACE_SIZE];
        for (int i = 0; i < CURSOR_SPACE_SIZE; i++) {
            cursorSpace[i] = new Node<>(null, i + 1);
        }
        cursorSpace[CURSOR_SPACE_SIZE - 1].next = 0;
    }

    public CursorLinkedList() {
        os = 0;
        count = 0;
        head = -1;
    }

    public void printList() {

        if (head != -1) {

            int start = head;
            while (start != -1) {

                T element = cursorSpace[start].element;
                System.out.println(element.toString());
                start = cursorSpace[start].next;
            }
        }
    }

    /**
     * @return the logical index of the element within the list , not the actual
     * index of the [cursorSpace] array
     */
    public int indexOf(T element) {

        Objects.requireNonNull(element);
        Node<T> iterator = cursorSpace[head];
        for (int i = 0; i < count; i++) {
            if (iterator.element.equals(element)) {
                return i;
            }
            iterator = cursorSpace[iterator.next];
        }

        return -1;
    }

    /**
     * @param position , the logical index of the element , not the actual one
     * within the [cursorSpace] array . this method should be used to get the
     * index give by indexOf() method.
     * @return
     */
    public T get(int position) {

        if (position >= 0 && position < count) {

            int start = head;
            int counter = 0;
            while (start != -1) {

                T element = cursorSpace[start].element;
                if (counter == position) {
                    return element;
                }

                start = cursorSpace[start].next;
                counter++;
            }
        }

        return null;
    }

    public void removeByIndex(int index) {

        if (index >= 0 && index < count) {

            T element = get(index);
            remove(element);
        }
    }

    public void remove(T element) {

        Objects.requireNonNull(element);

        // case element is in the head
        T temp_element = cursorSpace[head].element;
        int temp_next = cursorSpace[head].next;
        if (temp_element.equals(element)) {
            free(head);
            head = temp_next;
        } else { // otherwise cases

            int prev_index = head;
            int current_index = cursorSpace[prev_index].next;

            while (current_index != -1) {

                T current_element = cursorSpace[current_index].element;
                if (current_element.equals(element)) {
                    cursorSpace[prev_index].next = cursorSpace[current_index].next;
                    free(current_index);
                    break;
                }

                prev_index = current_index;
                current_index = cursorSpace[prev_index].next;
            }
        }

        count--;
    }

    private void free(int index) {

        Node os_node = cursorSpace[os];
        int os_next = os_node.next;
        cursorSpace[os].next = index;
        cursorSpace[index].element = null;
        cursorSpace[index].next = os_next;
    }

    public void append(T element) {

        Objects.requireNonNull(element);
        int availableIndex = alloc();
        cursorSpace[availableIndex].element = element;

        if (head == -1) {
            head = availableIndex;
        }

        int iterator = head;
        while (cursorSpace[iterator].next != -1) {
            iterator = cursorSpace[iterator].next;
        }

        cursorSpace[iterator].next = availableIndex;
        cursorSpace[availableIndex].next = -1;

        count++;
    }

    /**
     * @return the index of the next available node
     */
    private int alloc() {

        // 1- get the index at which the os is pointing
        int availableNodeIndex = cursorSpace[os].next;

        if (availableNodeIndex == 0) {
            throw new OutOfMemoryError();
        }

        // 2- make the os point to the next of the  @var{availableNodeIndex}
        int availableNext = cursorSpace[availableNodeIndex].next;
        cursorSpace[os].next = availableNext;

        // this to indicate an end of the list , helpful at testing since any err
        // would throw an outOfBoundException
        cursorSpace[availableNodeIndex].next = -1;

        return availableNodeIndex;
    }
}
Algerlogo

Β© Alger 2022

About us

We are a group of programmers helping each other build new things, whether it be writing complex encryption programs, or simple ciphers. Our goal is to work together to document and model beautiful, helpful and interesting algorithms using code. We are an open-source community - anyone can contribute. We check each other's work, communicate and collaborate to solve problems. We strive to be welcoming, respectful, yet make sure that our code follows the latest programming guidelines.