double-linkedlist Algorithm

The double-linkedlist algorithm is a data structure that consists of a collection of nodes, where each node contains a data element and two pointers, one to the previous node and one to the next node in the sequence. This allows for a more efficient traversal of the list, as it enables bidirectional movement through the list, making it easier to insert, delete, and search for elements. Double-linked lists are particularly useful when the order of elements is important, and when frequent updates to the list are required. In a double-linked list, the head node is the first element and its previous pointer is set to null, while the tail node is the last element and its next pointer is set to null. To insert an element, we simply create a new node, update the next pointer of the previous node to point to the new node, and update the previous pointer of the next node to point back to the new node. To delete a node, we update the next pointer of the previous node to point to the next node and the previous pointer of the next node to point to the previous node, effectively bypassing the node to be deleted. Searching for an element in a double-linked list involves traversing the list from the head node, following the next pointers until the desired element is found, or the end of the list is reached. Since each node maintains pointers to both its previous and next neighbors, the double-linked list provides greater flexibility and efficiency in performing common list operations compared to its singly-linked counterpart.
// demonstration of doubly linked list in golang

package doublelinkedlist

// package main

import "fmt"

type node struct {
	val  int
	next *node
	prev *node
}

type doublelinkedlist struct {
	head *node
}

// to avoid mistakes when using pointer vs struct for new node creation
func newNode(val int) *node {
	n := &node{}
	n.val = val
	n.next = nil
	n.prev = nil
	return n
}

func (ll *doublelinkedlist) addAtBeg(val int) {
	n := newNode(val)
	n.next = ll.head
	ll.head = n
}

func (ll *doublelinkedlist) addAtEnd(val int) {
	n := newNode(val)

	if ll.head == nil {
		ll.head = n
		return
	}

	cur := ll.head
	for ; cur.next != nil; cur = cur.next {
	}
	cur.next = n
	n.prev = cur
}

func (ll *doublelinkedlist) delAtBeg() int {
	if ll.head == nil {
		return -1
	}

	cur := ll.head
	ll.head = cur.next

	if ll.head != nil {
		ll.head.prev = nil
	}

	return cur.val
}

func (ll *doublelinkedlist) delAtEnd() int {
	// no item
	if ll.head == nil {
		return -1
	}

	// only one item
	if ll.head.next == nil {
		return ll.delAtBeg()
	}

	// more than one, go to second last
	cur := ll.head
	for ; cur.next.next != nil; cur = cur.next {
	}

	retval := cur.next.val
	cur.next = nil
	return retval
}

func (ll *doublelinkedlist) count() int {
	var ctr int = 0

	for cur := ll.head; cur != nil; cur = cur.next {
		ctr += 1
	}

	return ctr
}

func (ll *doublelinkedlist) reverse() {
	var prev, next *node
	cur := ll.head

	for cur != nil {
		next = cur.next
		cur.next = prev
		cur.prev = next
		prev = cur
		cur = next
	}

	ll.head = prev
}

func (ll *doublelinkedlist) display() {
	for cur := ll.head; cur != nil; cur = cur.next {
		fmt.Print(cur.val, " ")
	}

	fmt.Print("\n")
}

func (ll *doublelinkedlist) displayReverse() {
	if ll.head == nil {
		return
	}
	var cur *node
	for cur = ll.head; cur.next != nil; cur = cur.next {
	}

	for ; cur != nil; cur = cur.prev {
		fmt.Print(cur.val, " ")
	}

	fmt.Print("\n")
}

/*
func main() {
	ll := doublelinkedlist{}

	ll.addAtBeg(10)
	ll.addAtEnd(20)
	ll.display()
	ll.addAtBeg(30)
	ll.display()

	ll.reverse()
	ll.display()
	ll.displayReverse()

	fmt.Print(ll.delAtBeg(), "\n")
	fmt.Print(ll.delAtEnd(), "\n")
	fmt.Print("Display")
	ll.display()
	fmt.Print(ll.delAtBeg(), "\n")
	ll.display()
	fmt.Print(ll.delAtBeg(), "\n")
	ll.display()
}
*/

LANGUAGE:

DARK MODE: