연결 목록의 중간에 삽입하는 이유 O (1)?


105

링크드리스트에 대한 위키피디아 기사에 따르면 링크드리스트 중간에 삽입하는 것은 O (1)로 간주됩니다. 나는 그것이 O (n)이라고 생각할 것입니다. 목록의 끝 부분에있을 수있는 노드를 찾을 필요가 없습니까?

이 분석은 노드 작업의 발견 (필수적이지만)과 삽입 자체를 설명하지 않습니까?

수정 :

연결된 목록은 배열에 비해 몇 가지 장점이 있습니다. 목록의 특정 지점에 요소를 삽입하는 것은 일정한 시간 작업이지만 배열에 삽입하려면 요소의 절반 이상을 이동해야 할 수 있습니다.

위의 진술은 나에게 약간 오해의 소지가 있습니다. 내가 틀렸다면 정정하지만 결론은 다음과 같아야한다고 생각합니다.

어레이 :

  • 삽입 / 삭제 지점 찾기 O (1)
  • 삽입 / 삭제 수행 O (n)

연결된 목록 :

  • 삽입 / 삭제 지점 찾기 O (n)
  • 삽입 / 삭제 수행 O (1)

나는 당신이 위치를 찾을 필요가 없을 것이라고 생각한다 (어떤 경우에는 머리와 꼬리처럼) 당신이 그것에 대한 일종의 포인터를 유지하는 것입니다. 따라서 연결 목록이 항상 삽입 / 삭제 옵션에 대해 배열을 능가한다고 단호하게 말할 수는 없습니다.

답변:


113

이 기사는 "인덱싱"을 별도의 작업으로 간주합니다. 따라서 삽입 자체는 O (1)이지만 중간 노드에 도달하는 것은 O (n)입니다.


3
동일한 위치에 두 개 이상의 개체를 삽입 할 때 더 큰 차이를 만듭니다 ...
Has QUIT--Anony-Mousse 2011

@ Anony-Mousse 좀 더 설명해 주 시겠어요? 즉, 여러 개체를 삽입 할 때 삽입 위치를 한 번만 찾아야합니까?
MyTitle

2
기존 목록의 크기는 O (n)이며 여기에서 수행하려는 삽입 횟수가 아닙니다.
Has QUIT--Anony-Mousse

28

삽입 자체는 O (1)입니다. 노드 찾기는 O (n)입니다.


25

아니요, 삽입하기로 결정하면 이미 목록을 반복하는 중이라고 가정합니다.

연결된 목록에 대한 작업은 일반적으로 일반적인 "목록"이 아니라 노드 모음으로 처리되는 방식으로 수행되는 경우가 많습니다. 노드 자체를 주 루프의 반복자로 생각하십시오. 따라서 목록을 살펴보면서 비즈니스 로직의 일부로 새 노드를 추가 (또는 이전 노드를 삭제)해야한다는 사실을 알게되고 그렇게합니다. 한 번의 반복으로 50 개의 노드를 추가 할 수 있으며 각 노드는 인접한 두 노드의 연결을 해제하고 새 노드를 삽입 할 시간이 O (1)입니다.

편집 : 이봐, 당신은 첫 번째 응답자가 아닌 두 번째 단락을 입력하고 갑자기 첫 번째 4와 같은 것을 말하는 5 번째입니다!


1
Ha yeah 그거 짜증나 ... 연결된 목록 삽입 복잡성이 이미 원하는 포인터에 있다는 컨텍스트 내에서 고려된다는 것을 말할 가치가 있기 때문에 나는 당신의 것을 +1했습니다.
Daniel Macias 2015

6

차트가 보여주는 배열과 비교하기 위해 새 노드 이후에 모든 항목을 이동할 필요가 없기 때문에 O (1)입니다.

예, 그들은 당신이 이미 그 노드에 대한 포인터를 가지고 있거나 포인터를 얻는 것이 사소하다고 가정하고 있습니다. 즉, 문제는 " X에 주어진 노드 ,이 노드 뒤에 삽입 할 코드는 무엇입니까?" 삽입 지점에서 시작합니다.


5

연결 목록에 삽입하는 것은 전체를 반복하는 것과 다릅니다. 항목을 찾는 것이 아니라 포인터를 재설정하여 항목을 거기에 넣습니다. 앞쪽 끝이나 끝 근처에 삽입할지 여부는 중요하지 않지만 삽입에는 여전히 포인터가 다시 할당됩니다. 물론 구현 방법에 따라 다르지만 이것이 목록의 강점입니다. 쉽게 삽입 할 수 있습니다. 인덱스를 통해 액세스하는 것은 배열이 빛나는 곳입니다. 그러나 목록의 경우 일반적으로 n 번째 항목을 찾는 것은 O (n)입니다. 적어도 그것이 학교에서 기억하는 것입니다.


3

루핑을 포함하지 않기 때문입니다.

삽입은 다음과 같습니다.

  • 요소 삽입
  • 이전 링크
  • 다음 링크
  • 끝난

이것은 어떤 경우에도 일정한 시간입니다.

따라서 n 개의 요소를 차례로 삽입하는 것은 O (n)입니다.


3

이 분석은 노드 작업의 발견 (필수적이지만)과 삽입 자체를 설명하지 않습니까?

맞아요. 지정된 지점에 삽입하면 다음에 삽입하려는 항목에 대한 포인터가 이미 있다고 가정합니다.

InsertItem(item * newItem, item * afterItem)


2

아니요, 검색을 고려하지 않습니다. 그러나 이미 목록 중간에있는 항목에 대한 포인터를 가지고있는 경우 해당 지점에 삽입하는 것은 O (1)입니다.

검색해야하는 경우 검색 시간을 추가해야하며 O (n)이어야합니다.


0

이 기사는 배열과 목록을 비교하는 것에 관한 것입니다. 배열과 목록 모두에 대한 삽입 위치를 찾는 것은 O (N)이므로 기사에서는이를 무시합니다.


1
배열의 삽입 지점이 O (1)이되지 않습니까? 배열은 인접한 메모리에 저장되므로 오프셋을 추가하기 만하면됩니다.
Rob Sobers

@ vg1890-먼저 오프셋을 찾아야합니다.

0

O (1)은 새 항목을 삽입 할 항목이 있다는 사실에 따라 달라집니다. (이전 또는 이후). 그렇지 않은 경우 해당 항목을 찾아야하기 때문에 O (n)입니다.


0

나는 O () 표기법에 대해 계산하기로 선택한 경우에 불과하다고 생각합니다. 일반 연산을 삽입하는 경우에는 복사 연산입니다. 배열을 사용하여 중간에 삽입하는 것은 해당 위치 위에있는 모든 것을 메모리에 복사하는 것과 관련이 있습니다. 연결된 목록을 사용하면 두 개의 포인터를 설정합니다. 무엇을 삽입하든 위치를 찾아야합니다.


0

연결 목록에 대해 연산 후 삽입 할 노드의 참조가 O (1) 인 경우.
배열의 경우 모든 연속 노드를 이동해야하므로 여전히 O (n)입니다.


0

가장 일반적인 경우는 목록의 시작 부분이나 끝 부분에 삽입하는 것입니다 (목록의 끝 부분을 찾는 데 시간이 걸리지 않을 수 있음).

배열의 시작 또는 끝 부분에 항목을 삽입하는 것과 대조됩니다 (배열이 끝에있는 경우 배열 크기를 조정하고 시작 부분에있는 경우 모든 요소의 크기를 조정하고 이동해야 함).


경우에 따라 삽입이 여전히 O (1) 일지라도 끝에 빈 요소의 버퍼를 유지하면 배열 끝에 항목을 삽입하는 것이 O (1)이 될 수 있습니다. 대부분의 컬렉션이이 작업을 수행합니다. 인덱스 연산자를 변경하여 요소 번호 (n + x) % len을 반환하도록 변경하여 배열의 시작 부분에있는 비활성 항목을 O (1)로 만들 수도 있습니다. 여기서 x는 항목을 시작 부분에 삽입 한 횟수입니다. 목록의. Deques는 때때로 이와 같이 구현됩니다 (하지만 때때로 이중 연결 목록으로 구현됩니다.
Brian
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.