Go의 단일 체인 테이블
15991 단어 computersciencego
개요
체인 테이블은 선형 정렬을 형성하는 노드의 집합이다.각 노드는 하나의 데이터 필드와 다른 노드를 가리키는 포인터를 저장하는 객체입니다.체인 테이블에는 두 개의 특수 노드가 있습니다.
Head는 목록의 첫 번째 요소를 가리키는 바늘입니다. 목록이 비어 있으면 Head의 값은 0입니다.
끝 부분은 선택 사항이며 마지막 요소를 가리킵니다.우리는 다음 절에서 이 지침의 장점을 볼 것이다.
type Node struct {
Value interface{}
Next *Node
}
type LinkedList struct {
Head *Node
Tail *Node
}
조작하다
다음은 체인 테이블에서 실행할 수 있는 몇 가지 조작 예이다.전체 실현은 Github에서 찾을 수 있다.
앞으로 밀다
이 작업은 체인 테이블 앞에 요소를 추가합니다.이를 위해 필요한 값을 가진 새 노드를 생성해야 합니다
다음 포인터를 목록의 현재 제목으로 설정합니다.
다음에 새로 만든 노드를 가리키기 위해 헤더 포인터를 업데이트해야 합니다.
func (l *LinkedList) PushFront(val interface{}) {
node := &Node{Value: val, Next: l.Head}
l.Head = node
if l.Tail == nil {
l.Tail = l.Head
}
}
요소를 추가할 때 체인 테이블이 비어 있고 꼬리 바늘을 사용하고 있다면, 새로 만든 노드를 가리키기 위해 꼬리 바늘을 업데이트해야 합니다. (이 예에서 이 노드는 목록의 머리를 대표합니다.)팝업 전면
링크 목록의 첫 번째 요소를 삭제하려면 먼저 목록이 비어 있는지 확인해야 합니다.
다음 노드를 가리키도록 목록의 머리를 업데이트해야 합니다.머리가 지금 0을 가리키면 목록이 비어 있고 끝부분을 업데이트해야 합니다.
func (l *LinkedList) PopFront() error {
if l.Head == nil {
return errors.New("can't remove from empty list")
}
l.Head = l.Head.Next
if l.Head == nil {
l.Tail = nil
}
return nil
}
되돌리다
목록의 끝에 원소를 추가하는 것은 매우 비싸다. 왜냐하면 전체 목록을 두루 훑어봐야 마지막 원소를 찾을 수 있기 때문이다.모든 노드는 다음 노드를 가리키는 지침이 있어 처음부터 끝까지 훑어볼 수 있지만 거꾸로 훑어볼 수는 없다.
따라서 목록의 끝에 도달하려면 모든 노드를 교체해야 합니다.
꼬리가 구조를 가리키기 때문에 이런 조작 방식이 더욱 싸다.
func (l *LinkedList) PushBack(val interface{}) {
node := &Node{Value: val, Next: nil}
if l.Tail == nil {
l.Head = node
l.Tail = node
} else {
l.Tail.Next = node
l.Tail = node
}
}
필요한 값을 사용하여 새 노드를 만들고 다음 바늘을nil로 설정합니다.목록이 비어 있으면 머리와 꼬리를 업데이트하여 생성된 노드를 가리킵니다.그렇지 않으면 현재 꼬리의 다음 포인터를 새 노드로 업데이트한 다음 꼬리 포인터 자체를 업데이트합니다.
튕기다
Pop Front 작업과 유사합니다. 목록이 비어 있는지 확인해야 합니다. 그렇지 않으면 오류가 발생합니다.
다음에 목록에 원소가 하나밖에 없으면head와tail을 모두nil로 설정합니다. 열이 비어 있기 때문입니다.
func (l *LinkedList) PopBack() error {
if l.Head == nil {
return errors.New("can't remove from empty list")
}
if l.Head.Value == l.Tail.Value {
l.Head = nil
l.Tail = nil
return nil
}
currentHead := l.Head
for currentHead.Next.Next != nil {
currentHead = currentHead.Next
}
l.Tail = currentHead
currentHead.Next = nil
return nil
}
여기는 더욱 복잡해졌다. 왜냐하면 너는 반드시 꼴찌의 두 번째 요소를 찾아야 하기 때문이다. 앞에서 언급한 바와 같이 단일 링크 목록에서 두루 돌아다닐 수 없기 때문이다.따라서 두 번째 요소를 찾을 때까지 목록을 처음부터 반복해야 합니다.찾으면 마지막 요소를 가리키기 위해 끝부분을 업데이트합니다. (마지막 요소를 제거합니다.)
마지막으로 현재 마지막 요소의 다음 바늘을nil로 설정합니다.
나중에 추가
이 작업은 다른 주어진 노드 다음에 새 노드를 삽입합니다.
따라서 필요한 값을 사용하여 새 노드를 만들고 다음 포인터를 지정된 노드에 현재 지향하는 노드로 설정할 수 있습니다.
새 노드를 가리키기 위해 지정된 노드를 업데이트합니다.주어진 노드가 꼬리 요소일 경우, 새 노드를 가리키기 위해 꼬리를 업데이트합니다.
func (l *LinkedList) AddAfter(node *Node, val interface{}) {
newNode := &Node{Value: val, Next: node.Next}
node.Next = newNode
if l.Tail.Value == node.Value {
l.Tail = newNode
}
}
이전에 추가
이 조작은 가장 복잡하다. 왜냐하면, 당신은 반드시 머리에서 목록을 순환해야만 주어진 노드 이전의 요소에 도달할 수 있기 때문이다.
먼저 목록이 비어 있거나 지정된 노드가 목록의 첫 번째 요소인 경우 Push Front 작업을 반복하여 노드를 목록의 시작으로 삽입할 수 있습니다.
그렇지 않으면 지정된 노드의 이전 요소를 찾을 때까지 목록을 반복해야 합니다.순환 중, 이 두 노드 사이에 새 노드를 삽입해야 하기 때문에 이전 노드와 현재 노드를 추적합니다.
정확한 삽입 위치가 있을 때, 현재 노드가 0인지 확인하고, 두 노드 사이에 새 노드를 삽입해야 합니다.
그렇지 않으면 이미 실행된 Push Back 작업을 통해 노드를 목록 뒤에 추가합니다.
func (l *LinkedList) AddBefore(node *Node, val interface{}) {
if l.Head == nil || l.Head == node {
l.PushFront(val)
} else {
var prev *Node
cur := l.Head
for cur != nil && cur != node {
prev = cur
cur = cur.Next
}
if cur != nil {
prev.Next = &Node{Value: val, Next: cur}
} else {
l.PushBack(val)
}
}
}
운영 비용
헤더 포인터 때문에 목록 앞의 조작 원가가 비교적 낮다.목록 뒤에 요소를 삽입하는 것도 싸다. (꼬리 바늘이 없으면 이 작업은 O (n) 를 쓴다.
마지막 요소를 삭제하면 전체 목록에서 순환해야 하기 때문에 O(n) 형식으로 실행됩니다. 이것은 Add Before 작업에도 적용됩니다.
활용단어참조
꼬리가 없다
띠꼬리
전면 밀어냄 (val)
O(1)
PopFront
O(1)
리셋 (val)
O(n)
O(1)
팝업 ()
O(n)
AddAfter(노드, val)
O(1)
AddBefore(노드, val)
O(n)
마지막으로 목록의 전방향 포인터로 인해 기존 노드가 O(1)에서 다시 실행된 후에 요소를 추가합니다.
언제
기존 어레이에 비해 체인 테이블의 이점은 다음과 같습니다.
그러나 삽입/삭제 비용은 어떻습니까?Bjarne Stroustrup의 한 글은 진열에 비해 이러한 조작은 속도 우위가 전혀 없다는 것을 보여 준다.
따라서 메모리 사용량 증가 (스토리지 바늘) 와 무작위 접근 속도 차이 등 단점만 남았다.
결론
나에게 있어서 바둑에서 단사슬표를 사용하는 것은 실제적인 우세가 없고 단지 슬라이스만 사용하면 된다.
Reference
이 문제에 관하여(Go의 단일 체인 테이블), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/mattgood/singly-linked-list-in-go-3fgp텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)