Skip to content

Instantly share code, notes, and snippets.

@Youngchangoon
Created May 13, 2019 23:08
Show Gist options
  • Save Youngchangoon/213435e5feb49acba0e5616b8bcb09d5 to your computer and use it in GitHub Desktop.
Save Youngchangoon/213435e5feb49acba0e5616b8bcb09d5 to your computer and use it in GitHub Desktop.
Double linked list
using System;
namespace ConsoleApp1
{
public class Program
{
private static DoubleLinkedList<int> doubleLinkedList;
static void Main(string[] args)
{
doubleLinkedList = new DoubleLinkedList<int>();
// Insert
doubleLinkedList.InsertNode(10);
doubleLinkedList.InsertNode(20);
doubleLinkedList.InsertNode(5, true);
doubleLinkedList.InsertNode(15, 2);
doubleLinkedList.InsertNode(30);
doubleLinkedList.InsertNode(30);
doubleLinkedList.InsertNode(30);
//// Add Fail Case
doubleLinkedList.InsertNode(100, 9);
//// Remove
doubleLinkedList.RemoveNode(20);
doubleLinkedList.RemoveNode(30, true);
doubleLinkedList.RemoveAt(1);
// Remove Fail Case
doubleLinkedList.RemoveAt(100);
doubleLinkedList.PrintNode();
}
}
public class DoubleLinkedList<T>
{
public class Node<T>
{
public Node() { }
public Node(T newData)
{
data = newData;
}
public T data;
public Node<T> prev;
public Node<T> next;
}
private Node<T> head;
private Node<T> tail;
private int totalCount;
public DoubleLinkedList()
{
// 먼저 머리와 꼬리 노드를 만들어준다. ㅁ(head) -> ㅁ(tail)
head = new Node<T>();
tail = new Node<T>();
// (head) -> (tail) -> NULL
head.next = tail;
head.prev = null;
tail.next = null;
tail.prev = head;
totalCount = 0;
}
/// <summary>
/// 맨 앞이나 맨 뒤에 Data를 삽입한다.
/// </summary>
/// <param name="newData"> 새로 넣을 데이터 </param>
/// <param name="addToHead"> 꼬리에 추가할 것인지 </param>
public int InsertNode(T newData, bool addToHead = false)
{
var count = 0;
var addNode = new Node<T>(newData);
var tempNode = addToHead ? head : tail;
if (addToHead)
{
// 앞으로 넣을 때
var nextNode = tempNode.next;
nextNode.prev = addNode;
addNode.prev = tempNode;
addNode.next = tempNode.next;
tempNode.next = addNode;
}
else
{
// 뒤로 넣을 때
var prevNode = tempNode.prev;
prevNode.next = addNode;
addNode.prev = prevNode;
addNode.next = tempNode;
tempNode.prev = addNode;
}
++totalCount;
return count;
}
/// <summary>
/// 원하는 index에 Data를 추가한다.
/// </summary>
/// <param name="newData"></param>
/// <param name="index"></param>
/// <returns></returns>
public int InsertNode(T newData, int index)
{
if (index >= totalCount)
{
Console.WriteLine("Add Fail..(index: " + index + ")");
return 0;
}
var count = 0;
var addNode = new Node<T>(newData);
var isHeadStart = (totalCount / 2) > index;
var tempNode = isHeadStart ? head : tail;
if (isHeadStart)
{
for (var i = 0; i < index; ++i, ++count)
{
if (tempNode == tail)
{
Console.WriteLine("Add Fail..");
return 0;
}
tempNode = tempNode.next;
}
var addNextNode = tempNode.next;
addNextNode.prev = addNode;
addNode.next = tempNode.next;
addNode.prev = tempNode;
tempNode.next = addNode;
}
else
{
for (var i = totalCount; i > index; --i, ++count)
{
if (tempNode == head)
{
Console.WriteLine("Add Fail..");
return 0;
}
tempNode = tempNode.prev;
}
var addPrevNode = tempNode.prev;
addPrevNode.next = addNode;
addNode.next = tempNode;
addNode.prev = addPrevNode;
tempNode.prev = addNode;
}
++totalCount;
return count;
}
/// <summary>
/// 해당 데이터를 만나면 해당 노드를 삭제한다.
/// </summary>
/// <param name="removeNode"></param>
public int RemoveNode(T removeData, bool matchRemoveAll = false)
{
var count = 0;
var deleteNode = head;
while (deleteNode != tail)
{
// 지우려는 데이터가 같다면
if (deleteNode.data.Equals(removeData))
{
// 지우는 로직
var prevNode = deleteNode.prev;
var nextNode = deleteNode.next;
prevNode.next = nextNode;
nextNode.prev = prevNode;
deleteNode = null;
--totalCount;
if (matchRemoveAll)
{
count += RemoveNode(removeData, matchRemoveAll);
break;
}
else
break;
}
deleteNode = deleteNode.next;
++count;
}
return count;
}
/// <summary>
/// 원하는 인덱스의 노드를 삭제한다.
/// </summary>
public int RemoveAt(int index)
{
if (index >= totalCount)
{
Console.WriteLine("Delete Fail..(index: " + index + ")");
return 0;
}
var count = 0;
var isHeadStart = (totalCount / 2) > index;
var deleteNode = isHeadStart ? head.next : tail.prev;
if (isHeadStart)
{
for (var i = 0; i < index; ++i, ++count)
{
if (deleteNode == tail)
{
Console.WriteLine("Delete Fail..");
return count;
}
deleteNode = deleteNode.next;
}
}
else
{
for (var i = totalCount -1; i > index; --i, ++count)
{
if (deleteNode == head)
{
Console.WriteLine("Delete Fail...");
return count;
}
deleteNode = deleteNode.prev;
}
}
var prevNode = deleteNode.prev;
var nextNode = deleteNode.next;
prevNode.next = nextNode;
nextNode.prev = prevNode;
deleteNode = null;
--totalCount;
return count;
}
public void PrintNode()
{
// HEAD TO TAIL
Console.Write("HEAD->");
for (var tempNode = head.next; tempNode != tail; tempNode = tempNode.next)
{
Console.Write(tempNode.data + "->");
}
Console.WriteLine("TAIL");
// TAIL TO HEAD
Console.Write("TAIL->");
for (var tempNode = tail.prev; tempNode != head; tempNode = tempNode.prev)
{
Console.Write(tempNode.data + "->");
}
Console.WriteLine("HEAD");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment