Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0c85933
Add SquareFreeInteger to maths
iamcodinghere22 Jun 22, 2026
488fa21
fix clang-format issues
iamcodinghere22 Jun 22, 2026
c83cd4f
add newline
iamcodinghere22 Jun 22, 2026
2156b67
Add new test file in test
iamcodinghere22 Jun 22, 2026
3e5e1ab
modified
iamcodinghere22 Jun 22, 2026
d3c1360
delete
iamcodinghere22 Jun 22, 2026
28bfe86
Add DisariumNumbers with test
iamcodinghere22 Jun 22, 2026
90c0e87
Merge branch 'master' into master
DenizAltunkapan Jun 26, 2026
259db0d
feat(datastructures): add SelfOrganizingLinkedList implementation and…
iamcodinghere22 Aug 16, 2026
4809f82
fix checkstyle formatting errors in SelfOrganizingLinkedList includin…
iamcodinghere22 Aug 17, 2026
88d9ba2
Add new Line as per the format
iamcodinghere22 Aug 17, 2026
6e39000
fix(datastructures): prevent null dereference in SelfOrganizingLinked…
iamcodinghere22 Aug 17, 2026
beb01b2
format correction
iamcodinghere22 Aug 17, 2026
5b513e6
format
iamcodinghere22 Aug 17, 2026
2905459
build format
iamcodinghere22 Aug 17, 2026
7d05132
"
iamcodinghere22 Aug 17, 2026
c71cec2
format finally
iamcodinghere22 Aug 17, 2026
3db080e
maybe
iamcodinghere22 Aug 17, 2026
3cab177
done
iamcodinghere22 Aug 18, 2026
67df287
Merge branch 'master' into feat/self-organizing-list
iamcodinghere22 Aug 18, 2026
3a95d85
make corrections and add tests
iamcodinghere22 Aug 20, 2026
bdecac0
format
iamcodinghere22 Aug 20, 2026
f27285e
build correction
iamcodinghere22 Aug 20, 2026
64911e3
done
iamcodinghere22 Aug 20, 2026
1ebe273
pmd done
iamcodinghere22 Aug 20, 2026
53aaad2
Merge branch 'master' into feat/self-organizing-list
iamcodinghere22 Aug 20, 2026
bf9575d
Merge branch 'master' into feat/self-organizing-list
DenizAltunkapan Aug 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package com.thealgorithms.datastructures.lists;

import java.util.Objects;

/**
* A Self-Organizing Linked List implementation using the Move-To-Front (MTF) strategy.
* When an element is searched, it is automatically moved to the head of the list
* to optimize subsequent lookups.
*
* @param <E> the type of elements held in this list
*/
public class SelfOrganizingLinkedList<E> {

/**
* Node structure for the self-organizing linked list.
*
* @param <E> the type of element held in this node
*/
private static class Node<E> {
E value;
Node<E> next;

Node(E value) {
this.value = value;
this.next = null;
}
}

private Node<E> head;
private int size;

public SelfOrganizingLinkedList() {
this.size = 0;
this.head = null;
}

/**
* Inserts a new value at the end of the list.
*
* @param value the element to add
*/
public void insert(E value) {
Node<E> newNode = new Node<>(value);
if (head == null) {
head = newNode;
} else {
Node<E> temp = head;
while (temp.next != null) {
temp = temp.next;
}
temp.next = newNode;
}
size++;
}

/**
* Searches for a value in the list.
* If found, moves the node to the front (head) of the list.
*
* @param key the value to search for
* @return true if the element is present, false otherwise
*/
public boolean search(E key) {
if (head == null) {
return false;
}
// If the key is already at the head, no pointers need to be rewired
if (Objects.equals(head.value, key)) {
return true;
}

Node<E> prev = head;
Node<E> curr = head.next;

while (curr != null && !Objects.equals(curr.value, key)) {
prev = curr;
curr = curr.next;
}

if (curr == null) {
return false;
}

// Unlink curr from its current position and move it to head
prev.next = curr.next;
curr.next = head;
head = curr;
return true;
}

/** Gets the current head value of the list. */
public E getHeadValue() {
return head != null ? head.value : null;
}

/** Returns the size of the list. */
public int getSize() {
return size;
}

/** Returns true if the list contains no elements. */
public boolean isEmpty() {
return size == 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package com.thealgorithms.datastructures.lists;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class SelfOrganizingLinkedListTest {

private SelfOrganizingLinkedList<Integer> list;

@BeforeEach
void setUp() {
list = new SelfOrganizingLinkedList<>();
}

@Test
void testEmptyListAndGetters() {
assertTrue(list.isEmpty());
assertEquals(0, list.getSize());
assertNull(list.getHeadValue());
assertFalse(list.search(10));
}

@Test
void testInsertAndSizeState() {
assertTrue(list.isEmpty());
list.insert(10);
assertFalse(list.isEmpty());
assertEquals(1, list.getSize());

list.insert(20);
assertEquals(2, list.getSize());
}

@Test
void testMoveMiddleElementToFrontPreservesFullListStructure() {
list.insert(10);
list.insert(20);
list.insert(30);
list.insert(40);

// Initial order: [10, 20, 30, 40]
assertTrue(list.search(30));

// Expected order: [30, 10, 20, 40]
assertEquals(4, list.getSize());
assertEquals(30, list.getHeadValue());
Comment thread
DenizAltunkapan marked this conversation as resolved.

// Sequential head tracking to verify middle and tail pointers didn't break
assertTrue(list.search(10)); // [10, 30, 20, 40]
assertEquals(10, list.getHeadValue());

assertTrue(list.search(20)); // [20, 10, 30, 40]
assertEquals(20, list.getHeadValue());

assertTrue(list.search(40)); // [40, 20, 10, 30]
assertEquals(40, list.getHeadValue());
assertEquals(4, list.getSize());
}

@Test
void testMoveLastElementToFrontPreservesFullListStructure() {
list.insert(10);
list.insert(20);
list.insert(30);

// Search tail element '30'
assertTrue(list.search(30)); // Order becomes [30, 10, 20]

assertEquals(30, list.getHeadValue());
assertEquals(3, list.getSize());

// Verify remaining chain order [10, 20]
assertTrue(list.search(20)); // [20, 30, 10]
assertEquals(20, list.getHeadValue());

assertTrue(list.search(10)); // [10, 20, 30]
assertEquals(10, list.getHeadValue());
assertEquals(3, list.getSize());
}

@Test
void testSearchNonExistentElementPreservesStructureAndSize() {
list.insert(10);
list.insert(20);
list.insert(30);

assertFalse(list.search(99));
assertEquals(3, list.getSize());
assertEquals(10, list.getHeadValue());
}

@Test
void testDuplicateValuesMovesFirstMatchedToFront() {
list.insert(10);
list.insert(20);
list.insert(10); // Duplicate '10' at tail
list.insert(30);

// Initial list state: [10, 20, 10, 30]
// Searching '10' hits the head immediately -> no re-linking
assertTrue(list.search(10));
assertEquals(10, list.getHeadValue());
assertEquals(4, list.getSize());

// Searching '20' moves middle element to head: [20, 10, 10, 30]
assertTrue(list.search(20));
assertEquals(20, list.getHeadValue());

// Searching '10' moves the FIRST instance of '10' (index 1) to head: [10, 20, 10, 30]
assertTrue(list.search(10));
assertEquals(10, list.getHeadValue());
assertEquals(4, list.getSize());
}
}
Loading