자료구조, 알고리즘/개념

[알고리즘] 배열, 동적 배열, 연결 리스트

wnstjd 2024. 7. 7. 22:54

배열

  • 크기가 고정적이며 변경할 수 없다.
  • 요소들이 메모리상에 연속적으로 저장된다.

문제점

  • 유동적으로 사용할 수 없다.

 

동적 배열

  • 크기가 유동적이다.
  • 요소들이 메모리상에 연속적으로 저장된다. 

문제점

  • 크기가 변경될 때 많은 비용이 발생한다.
  • 삽입, 삭제가 어렵다.

해결책

  • 배열이 생성될 때 지정한 크기보다 1.5~2배 정도 더 많은 공간을 미리 차지해둔다.

간단 구현

class MyList<T>
{
    const int DEFAULT_SIZE = 1;
    T[] data = new T[DEFAULT_SIZE];

    public int Count = 0; //실제로 사용되는 공간 개수
    public int Capacity { get { return data.Length; } } //예비 공간 개수

    // O(1)
    public T this[int index]
    {
        get { return data[index]; }
        set { data[index] = value; }
    }

    // O(1)
    public void Add(T item)
    {
        // 1. 공간이 남아있는지 확인
        // 특수한 상황에서만 실행되므로 시간복잡도 무시
        if(Count >= Capacity)
        {
            // 공간 확보
            T[] newArray = new T[Count * 2];
            for(int i = 0; i < Count; i++)
                newArray[i] = data[i];
            data = newArray;    
        }

        // 2. 데이터 삽입
        data[Count] = item;
        Count++;
    }

    // O(n)
    public void RemoveAt(int index)
    {
        for(int i = index; i < Count - 1; i++)
            data[i] = data[i + 1];
        data[Count - 1] = default(T);

        Count--;
    }
}

 

연결 리스트

  • 요소들이 메모리상에 연속적으로 저장되지 않는다.
  •  삽입, 삭제가 유리하다.

문제점

  • 인덱서를 사용할 수 없다.
  • 탐색에 비교적 많은 비용이 든다.

간단 구현

class MyLinkedListNode<T>
{
    public T Data;
    public MyLinkedListNode<T> Next;
    public MyLinkedListNode<T> Prev;
}

class MyLinkedList<T>
{
    public int Count;
    public MyLinkedListNode<T> First = null;
    public MyLinkedListNode<T> Last = null;

    // O(1)
    public MyLinkedListNode<T> AddLast(T data)
    {
        MyLinkedListNode<T> newNode = new MyLinkedListNode<T>();
        newNode.Data = data;

        if(First == null)
            First = newNode;

        if(Last != null)
        {
            Last.Next = newNode;
            newNode.Prev = Last;
        }

        Last = newNode;
        Count++;

        return newNode;
    }

    // O(1)
    public void Remove(MyLinkedListNode<T> node)
    {
        if(First == node)
            First = First.Next;

        if (Last == node)
            Last = Last.Prev;

        if (node.Prev != null)
            node.Prev.Next = node.Next;

        if (node.Next != null)
            node.Next.Prev = node.Prev;

        Count--;
    }
}