배열 대신 연결된 목록을 사용하기위한 구체적인 규칙은 무엇입니까?


18

요소의 저렴한 삽입 및 삭제를 원할 때와 요소가 메모리에서 서로 나란히 상관되지 않는 경우에는 연결된 목록을 사용할 수 있습니다.

이것은 매우 추상적이며 배열 대신 연결된 목록을 사용해야하는 이유에 대한 구체적인 설명을 원합니다. 나는 프로그래밍 경험이 많지 않아서 실제 경험이 많지 않다.


3
솔직히 말해서, 당신이 무언가를 쓴 경험이 있고 데이터 구조 변경이 코드에 미치는 영향을 볼 때까지 예제가 당신에게 많은 것을 의미한다고 생각하지 않습니다. 관심있는 것을 작성하고 어떤 데이터 구조와 컨테이너가 가장 적합한 지 파악하거나, 기존 코드를 살펴보고 각 컨테이너가 선택된 이유와 변경에 따른 영향에 대해 생각하십시오.
쓸모없는

필자는 여기에서 합리적인 것보다 훨씬 긴 형식의 예제를 사용하지 않고 데이터 구조 선택의 트레이드 오프와 부작용을 (익숙하지 않은) OP에 전달하는 것이 유용하다고 생각하지 않습니다. 답변으로 주어진 예는 훌륭하며 요청에 따라 질문에 대답하지만 실제 이해에 대한 암시 적 요청은 아닙니다.
쓸모없는

답변:


37

여기 예제와 비유 사이에 어떤 부분이 있습니다. 심부름을해야하므로 종이 한 장을 잡고 다음과 같이 작성하십시오.

  • 은행
  • 식료 잡화류
  • 드라이 클리닝 제거

그런 다음 우표도 사야한다는 것을 기억합니다. 당신의 도시의 지리 때문에, 당신은 은행 후에 그것을해야합니다. 전체 목록을 새 종이에 복사 할 수 있습니다.

  • 은행
  • 우표
  • 식료 잡화류
  • 드라이 클리닝 제거

또는 당신이 가진 것에 낙서 할 수 있습니다 :

  • 은행 ............ 스탬프
  • 식료 잡화류
  • 드라이 클리닝 제거

다른 심부름을 생각할 때 목록의 맨 아래에 쓰면되지만 화살표를 사용하여 자신에게 어떤 명령을했는지 알려주십시오.이 목록은 링크 된 목록입니다. 무언가를 추가 할 때마다 전체 목록을 복사하는 것보다 빠르고 쉽습니다.

그런 다음 은행에있는 동안 휴대 전화가 울립니다. "이봐, 나는 우표를 받았는데, 더 이상 줍지 마." STAMPS를 목록에서 벗어나면 STAMPS가없는 완전히 새로운 것을 다시 쓰지 않습니다.

이제 코드로 심부름 목록을 구현할 수 있습니다 (지리를 기반으로 심부름을 순서대로 배치하는 앱일 수 있음). 실제로 코드에서 링크 된 목록을 사용할 가능성이 높습니다. 많은 항목을 추가 및 제거하고 주문이 중요하지만 각 삽입 또는 삭제 후에 전체 목록을 다시 복사하지 않으려 고합니다.



@Dennis 예, 이동 의미론 덕분에 알고 있습니다. 그러나 이것이 모든 언어에 해당되는 것은 아니므로 예제가 그대로 있습니다.
케이트 그레고리

1
@KateGregory는 충분히 공평하지만 여전히 "기본"데이터 구조가 학교 나 다른 곳에서 배우는 멋진 데이터 구조보다 낫다는 점을 지적하는 것이 좋습니다. 나는 새로운 대학원생들이 LL을 모든 곳에서 사용하기를 원하지 않습니다. 왜냐하면 이론적으로 적절하지만 현실적으로 좋지 않은 선택 일 수 있기 때문입니다. 올바른 데이터 구조를 사용하는 것이 중요하며 때로는 사람들이 지나치게 복잡합니다. 데이터 구조에 대한 Jonathan Blow ( "Braid"의 제작자 ) 의이 이야기 는 약간 관련이 있습니다.
Dennis

1
@Ray : 4 개의 요소가 있고 비교가 비교적 저렴한 경우 링크 된 목록이 트리 구조를 능가 할 수 있습니다. 컷오프가 어디에 있는지 정확히 알 수 없습니다. 또한 트리 구조에서는 데이터를 정렬 할 수 있어야하지만 목록 구조에서는 삽입 순서 (또는 임의 순서)를 유지할 수 있습니다.
David Stone

2
나는이 비유가 매우 정확하다고 생각하지 않습니다. 인간으로서 우리는 (적어도 짧은 목록에 대해서는) O (1)에서 요소를 찾을 수 있습니다. 그러나 링크 된 목록에서 임의의 삽입을 수행하려면 삽입하려는 위치를 찾기 위해 O (n)의 비용이 드는 평균 요소의 절반을 횡단해야합니다. 실제 인서트는 O (1)의 비용 만 발생하지만 어레이의 경우 O (n)도 "비용"입니다. 따라서 그 이유는 이동 의미론뿐만 아니라 알고리즘 때문입니다. 그러나 비-인접한 메모리 액세스로 인해 big-O에 의해 숨겨지는 상수는 선호 목록에 비해 훨씬 큽니다.
5gon12eder

18
  • 체인 을 사용 하여 해시 충돌을 해결하는 해시 테이블 에는 일반적으로 해당 버킷의 요소에 대해 버킷 당 하나의 링크 된 목록이 있습니다.
  • 단순 메모리 할당자는 사용 되지 않은 메모리 영역의 사용 가능한 목록 , 기본적으로 사용 가능한 메모리 자체에 목록 포인터가있는 링크 된 목록을 사용합니다.
  • A의 FAT 파일 시스템 , 대용량 파일의 메타 데이터는 FAT 엔트리의 링크 된 목록으로 구성되어있다.

12

C 언어 "호출 스택"은 x86 (및 대부분의 다른) 이진 API에서 링크 된 목록 으로 구현됩니다 .

즉, C 언어 프로 시저 호출은 선입 선출 방식을 따릅니다. (재귀 적) 함수 호출을 실행 한 결과를 "호출 스택"또는 때로는 "스택"이라고합니다.

CALLx86 명령어는 "호출 스택"을 사용하여 링크 된 목록을 implmenting 끝납니다. CALL명령 % EIP 레지스터의 내용, 상기 명령의 어드레스 가압 CALL 위에 적층 메모리. 호출 된 프롤로그는 호출 함수에서 로컬 변수의 가장 낮은 주소 인 % EBP 레지스터의 내용을 스택 메모리로 푸시합니다. 그런 다음 호출 된 함수 프롤로그는 % EBP를 현재 함수의 스택 기반으로 설정합니다.

이는 % EBP가 호출 함수의 % EBP 값의 주소를 보유하는 메모리 위치에 대한 포인터임을 의미합니다. 이는 링크 된리스트에 지나지 않으며, 하드웨어를 통해 부분적으로 구현됩니다 CALL.

이것이 좋은 점은 x86 CPU가 함수 호출을 구현하는 방법, 특히 함수에 자체 인수 사본이있는 함수 호출 및 함수의 로컬 변수입니다. 모든 함수 호출은 "호출 스택"에 대한 일부 정보를 푸시하여 호출 된 함수 또는 호출 함수의 간섭없이 CPU가 호출 함수에서 중단 된 부분을 가져올 수 있도록합니다.


3

연결된 목록을 사용하여 메시지 큐를 구현할 수 있습니다.

메시지 큐는 나중에 처리하기 위해 이벤트에 대한 정보를 저장하는 구조입니다. 예를 들어, 사용자가 키를 누르거나 마우스를 움직이면 이것은 이벤트입니다. 이벤트가 발생하는 순간에 응용 프로그램이 사용 중일 수 있으므로 이벤트가 발생하는 정확한 순간에 이벤트를 처리 할 수 ​​없습니다. 따라서 이벤트는 메시지 큐 (키를 눌렀거나 마우스가 이동 한 위치에 대한 정보)에 배치되고 응용 프로그램에 여유 시간이 있으면 메시지 큐를 확인하고 이벤트 큐에서 이벤트를 가져 와서 처리합니다. 그들. (이것은 밀리 초의 시간 프레임 내에서 발생하므로 눈에 띄지 않습니다.)

방금 설명한 사용 시나리오에서 메시지 큐에 저장된 이벤트에 무작위로 액세스하지 않아도됩니다. 우리는 메시지를 저장하고 검색 할 수 있기만합니다. 따라서 최적의 삽입 / 제거 시간을 제공하는 연결된 목록을 사용하는 것이 좋습니다.

(메시지 대기열이 순환 배열 목록을 사용하여 구현 될 가능성이 높거나 거의 가능성이 있음을 지적하지 마십시오. 기술적 인 세부 사항이며 제한 사항이 있습니다. 제한된 수의 메시지)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.