각 노드가 데이터와 포인터를 가지며, 원형 형태로 연결되어 있는 방식으로 데이터를 저장하는 자료구조
일반 연결리스트와 거의 비슷한 구조이지만, 마지막 node가 다시 첫번째 노드를 가리킨다는 것에서 차이점이 있다.
function Node(value) {
this.data = data;
this.next = null;
}
function CircularLinkedList() {
this.head = null;
this.length = 0;
}
CircularLinkedList.prototype.size = function() {
return this.length;
}
CircularLinkedList.prototype.isEmpty = function() {
return this.length === 0;
}
CircularLinkedList의 경우, 마지막 node가 head를 가리키기 때문에,
node = this.head부터 할 수 없다.
그래서 처음에 node의 data를 하나 출력한 이후, head.next부터 출력한다.
CircularLinkedList.prototype.printNode = function() {
process.stdout.write("head -> ");
if (this.length != 0) {
process.stdout.write(`${this.node.data} -> `);
for (let node = this.head.next; node != this.head; node = node.next) {
process.stdout.write(`${node.data} -> `);
}
}
console.log("null");
}
** 다른 과정의 경우 LinkedList와 동일하며, node.next에 this.head를 추가한다.
CircularLinkedList.prototype.append = function(value) {
let node = new Node(value), current = this.head;
if (this.head === null) {
this.head = node;
} else {
while (current.next != this.head) {
current = current.next;
}
current.next = node;
}
node.next = this.head;
this.length++;
}
CircularLinkedList.prototype.append = function(value) {
let node = new Node(value), current = this.head;
if (this.head === null) {
this.head = node;
} else {
while (current.next != this.head) {
current = current.next;
}
current.next = node;
}
node.next = this.head;
this.length++;
}
CircularLinkedList.prototype.insert = function(value, position = 0) {
if (position < 0 || position > this.length) {
return false;
}
let node = new Node(value);
let current = this.head, index = 0, prev;
if (position === 0) {
node.next = current;
if (this.isEmpty()){
current = node;
} else {
while (current.next != this.head) {
current = current.next;
}
}
this.head = node;
current.next = this.head;
} else {
while (index++ < position) {
prev = current;
current = current.next;
}
prev.next = node;
node.next = current.next;
if (node.next === null) {
node.next = this.head;
}
}
this.length++;
return true;
}
CircularLinkedList.prototype.remove = function(value) {
let current = this.head, prev = current, data;
while (current.data != value && current.next != this.head) {
prev = current;
current = current.next;
}
if (current.data !== value) {
return null;
}
data = current.data;
if (current === this.head) {
while (current.next != this.head) {
current = current.next;
}
this.head = this.head.next;
current.next = this.head;
} else {
prev.next = current.next;
}
this.length--;
return data;
}
position값으로 구별하는 점을 제외하고는, 위의 remove와 동일하다.
CircularLinkedList.prototype.removeAt = function(position = 0) {
if (position < 0 || position > this.length) {
return null;
}
let current = this.head, index = 0, prev, data;
if (position === 0) {
data = current.data;
while(current.next != this.head) {
current = current.next;
}
this.head = this.head.next;
current.next = this.head;
} else {
while (index++ < position) {
prev = current;
current = current.next;
}
data = current.data;
prev.next = current.next;
}
this.length--;
return data;
}
처음에 current가 this.head를 가리키고 있기 때문에 do while 구문을 이용해서, 먼저 실행되고 이후에 반복되도록 한다.
CircularLinkedList.prototype.indexOf = function(value) {
let current = this.head, index = 0;
do{
if (current.data === value) {
return index;
}
index++;
current = current.next;
} while (current != this.head);
return -1;
}
관련 전체 코드는 Git에 업로드 해두었습니다.
Github_CircularLinkedList