๋ฐฐ์ด์ ํ์คํ๊ฒ ์ ํด์ง ์์๋ก ๋ฌด์ธ๊ฐ๋ฅผ ์ ์ฅํ ๋๋ ์ ์ฉํ๊ณ , ๊ฐ๋จํ๊ฒ ์ ์ฉ๋ ์ ์์ง๋ง. ์ฝ๊ฐ์ ๋จ์ ์ด ์กด์ฌํ๋ค.
๋ฐฐ์ด์ ๋ณํ์ ์ทจ์ฝํ๋ค. ์๋ฅผ ๋ค์ด ๋ฐฐ์ด์ ๋ฏธ๋ฆฌ ํฌ๊ธฐ n์ ์ ํด์ผ ํ๋ฉฐ ๋ฐฐ์ด์ ํฌ๊ธฐ๋ฅผ ๋ค์ ์ ํ๋ ๊ฒ์ด ์ด๋ ต๋ค. (STL ๋ฒกํฐ์์ ์ด ๋จ์ ์ ํด๊ฒฐ๋๋ค.)
๊ทธ๋ฆฌ๊ณ ์์ ์ถ๊ฐ๋ฅผ ์ํด ์ถ๊ฐ๋ ๊ณต๊ฐ์ ๋ง๋ค๊ฑฐ๋, ์์ ์ ๊ฑฐ ํ์ ๋น ๊ณต๊ฐ์ ์ฑ์ฐ๋ ๋ฑ, ์์๋ค์ ์ด๋์ด ์๊ตฌ๋๊ธฐ ๋๋ฌธ์, ๋ฐฐ์ด์์์ ์ฝ์
๊ณผ ์ ๊ฑฐ์ ์ด๋ ค์์ด ์๋ค.
Singly Linked List, Doubly Linked List and Circularly Linked List
๋งํฌ๋ ๋ฆฌ์คํธ(linked list)์ ๋ ธ๋ ๋ด๋ถ์ next ํฌ์ธํฐ๋ ๋ค๋ฅธ ๋ ธ๋์ ๋ํ link ๋๋ pointer๋ก ๋ณผ ์ ์๋ค. next ์ฐธ์กฐ๋ฅผ ํตํด ํ ๋ ธ๋์์ ๋ค๋ฅธ ๋ ธ๋๋ก ์ด๋ํ๋ ๊ฒ์ link hopping ๋๋ pointer hopping ์ด๋ผ๊ณ ํ๋ค.
๋งํฌ๋ ๋ฆฌ์คํธ์ ์ ์ผ ์ฒ์๊ณผ ๋ง์ง๋ง ๋ ธ๋๋ฅผ ๊ฐ๊ฐ ๊ทธ ๋ฆฌ์คํธ์ head์ tail์ด๋ผ ๊ฐ๊ฐ ๋ถ๋ฅธ๋ค. ๊ทธ๋์ ๋ฆฌ์คํธ๋ฅผ head์์ ์์ํด์ tail๊น์ง ๋ฐฉ๋ฌธํ ์ ์๋ค. null์ ์ฐธ์กฐํ๋ next ๊ฐ์ ๊ฐ์ง node๋ก tail์ ํ์ธํ ์ ์๋ค.
๊ฐ ๋ ธ๋๊ฐ ๋จ์ผ ์ฐ๊ฒฐ์ ์ ์ฅํ๋ฏ๋ก ์ด๋ฌํ ๊ตฌ์กฐ๋ฅผ Singly Linked List๋ผ๊ณ ๋ถ๋ฅธ๋ค.
๋ฐฐ์ด์์์ ๋ง์ฐฌ๊ฐ์ง๋ก Singly Linked List๋ ํน์ ์์๋๋ก ์์๋ค์ ์ ์ฅํ๋ฉฐ, ์ด ์์๋ next ๋งํฌ์ ์ฐ๊ฒฐ๋ก์จ ๊ฒฐ์ ๋๋ค. ๋ค๋ง ๋ฐฐ์ด๊ณผ๋ ๋ค๋ฅด๊ฒ, Singly Linked List๋ ๋ฏธ๋ฆฌ ์ ์ธ๋์ด ๊ณ ์ ๋ ํฌ๊ธฐ๋ฅผ ๊ฐ๋๋ค. ๋ ธ๋๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ์ญ์ ํจ์ผ๋ก์จ ์ฌ์ด์ฆ๋ฅผ ์ฌ์กฐ์ ํ ์ ์๋ค.
Time Complexity : O(1)
Time Complexity : O(n)
Time Complexity : O(1)
Time Complexity : O(2n-1) = O(n)
#include <string>
using std::string;
// Code Fragment 3.13: A node in a singly linked list of strings.
class StringNode
{ // a node in a list of strings
private:
string elem; // element value
StringNode *next; // next item in the list
friend class StringLinkedList; // provide StringLinkedList access
};
// Code Fragment 3.14: A class definition for a singly linked list of strings.
class StringLinkedList
{ // a linked list of strings
public:
StringLinkedList(); // empty list constructor
~StringLinkedList(); // destructor
bool empty() const; // is list empty?
const string &front() const; // get front element
void addFront(const string &e); // add to front of list
void removeFront(); // remove front item list
private:
StringNode *head; // pointer to the head of list
// ๊ตฌํ์ ๋ฐ๋ผ tail์ ๊ตฌํํ๋ ๊ฒฝ์ฐ๋ ์๋ค.
};
// Code Fragment 3.15: Some simple member functions of class StringLinkedList.
StringLinkedList::StringLinkedList() // constructor
: head(NULL)
{
}
StringLinkedList::~StringLinkedList() // destructor
{
while (!empty())
removeFront();
}
bool StringLinkedList::empty() const // is list empty?
{
return head == NULL;
}
const string &StringLinkedList::front() const // get front element
{
return head->elem;
}
// Code Fragment 3.16: Insertion to the front of a singly linked list.
void StringLinkedList::addFront(const string &e)
{ // add to front of list
StringNode *v = new StringNode; // create new node
v->elem = e; // store data
v->next = head; // head now follows v
head = v; // v is now the head
}
// Code Fragment 3.17: Removal from the front of a singly linked list.
void StringLinkedList::removeFront()
{ // remove front item
StringNode *old = head; // save current head
head = old->next; // skip over old head
delete old; // delete the old head
}
Singly Linked List์ tail์์ ์์๋ฅผ ์ง์ฐ๋ ๊ฒ์ ์ฝ์ง ์๋ค. ์ฌ์ค, Singly Linked List์์ ์ง์ฐ๋ ค๋ ๋ ธ๋์ ๋ฐ๋ก ์ด์ ๋ ธ๋๋ก ๋ฐ๋ก ์ ๊ทผํ๊ธฐ ์ํ ๋น ๋ฅธ ๋ฐฉ๋ฒ์ด ์๊ธฐ ๋๋ฌธ์ head์์ ๋ฉ๋ฆฌ ์๋ ๋ ธ๋๋ฅผ ์ง์ฐ๋ ๊ฒ์ ์๊ฐ์ด ๋ง์ด ์๋ชจ๋๋ค.
Linked List์์ ์ ๋ฐฉํฅ๊ณผ ๋ฐ๋ ๋ฐฉํฅ ๋ฑ ์ ๋ฐฉํฅ์ผ๋ก ํ์์ ๊ฐ๋ฅ์ผ ํด์ฃผ๋ Linked List์ ์ข ๋ฅ๊ฐ ์๋ค. Doubly Linked List๋ ์์ ๋ฉค๋ฒ ์ด์ธ์, ๋ฆฌ์คํธ์ ๋ค์ ๋ ธ๋์ ์ด์ ๋ ธ๋๋ฅผ ๊ฐ๊ฐ ๊ฐ๋ฆฌํค๋ next ๋งํฌ์ prev ๋งํฌ๋ฅผ ๊ฐ์ง๋ค. ์ด๋ฌํ ๋ฆฌ์คํธ๊ธ์ ์ด๋ ์์น์์๋ ํจ์จ์ ์ธ ์ฝ์ ๋ฐ ์ ๊ฑฐ๋ฅผ ํฌํจํ ๋ค์ํ ๋น ๋ฅธ ์ ๋ฐ์ดํธ ์ฐ์ฐ์ ์ ๊ณตํ๋ค.
Time Complexity : O(n+1) = O(n)
์ฉ์ด๋ค์ ๊ตฌํ์ ๋ฐ๋ผ ์ฐจ์ด๊ฐ ์์ ์ ์๋ค.
back()
: Return the element referenced by the cursor; error if emptyfront()
: Return the element immediately after the cursor; error if emptyadvance()
: Advance the cursor to the next node in the listadd(e)
: Insert a new node with element e immediately after the cursor; if the list is empty, then this node becomes the cursor and its next pointer points to itselfremove()
: Remove the node immediately after the cursor (so the front); if the list has only one node, the node at cursor is removed; if the list becomes empty, the cursor is set to null#include <string>
using std::string;
// Code Fragment 3.28 : A node of a circularly linked list.
typedef string Elem; // element type
class CNode
{ // circularly linked list node
private:
Elem elem; // linked list element value
CNode *next; // next item in the list
friend class CircleList; // provide CircleList access
};
// Code Fragment 3.29: Implementation of a circularly linked list class.
class CircleList
{ // a circularly linked list
public:
CircleList(); // constructor
~CircleList(); // destructor
bool empty() const; // is list empty?
const Elem &front() const; // element at cursor
const Elem &back() const; // element following cursor
void advance(); // advance cursor
void add(const Elem &e); // add after cursor
void remove(); // remove node after cursor
private:
CNode *cursor; // the cursor
};
// Code Fragment 3.30: The constructor and destructor.
CircleList::CircleList() // constructor
: cursor(NULL)
{
}
CircleList::~CircleList() // destructor
{
while (!empty())
remove();
}
// Code Fragment 3.31: Simple member functions.
bool CircleList::empty() const // is list empty?
{
return cursor == NULL;
}
const Elem &CircleList::back() const // element at cursor
{
return cursor->elem;
}
const Elem &CircleList::front() const // element following cursor
{
return cursor->next->elem;
}
void CircleList::advance() // advance cursor
{
cursor = cursor->next;
}
// Code Fragment 3.32: Inserting a node just after the cursor of a circularly linked list.
void CircleList::add(const Elem &e)
{ // add after cursor
CNode *v = new CNode; // create a new node
v->elem = e;
if (cursor == NULL)
{ // list is empty?
v->next = v; // v points to itself
cursor = v; // cursor points to v
}
else
{ // list is nonempty?
v->next = cursor->next; // link in v after cursor
cursor->next = v;
}
}
// Code Fragment 3.33: Removing the node following the cursor
void CircleList::remove()
{ // remove node after cursor
CNode *old = cursor->next; // the node being removed
if (old == cursor) // removing the only node?
cursor = NULL; // list is now empty
else
cursor->next = old->next; // link out the old node
delete old; // delete the old node
}