-
스위프트 : 연결리스트 (2 / 3) : #LinkedList : #값 추가하기, push, append : #값 삽입하기,insert: #swift스위프트: Swift/자료구조 : Data Strutures in Swift 2018. 9. 12. 16:15
안녕하세요 ! 씩이 입니다!
저는 Swift 와 iOS 를 공부하고 연구하는 대딩 ( 대학생 ) 이구요!
같은 분야를 공부하는 분들에게 조금이라도 도움이 됬으면 좋겠습니다.
공유가 미래 라고 생각합니다.
한국의 모든 개발자분들 존경합니다!
- Swift version : Swift 4.2 ( 18.09. 01 ~ ) Swift 언어
- 참고한 것들
( 제 깃허브에 iOS, Swift 관련 정보들 정리되어 있습니다!! )
- 스위프트로 구현한 자료구조 : DataStructures in Swift4
- Swift 주제별 분류
- Swift4 : 프로토콜 2 : #델리게이트 패턴 : #델리게이션 (2 / 2)
연결리스트에 값 추가하기 (2 / 3)
- 어떤 종류가 있어?
- push : 리스트의 맨 앞에 값 추가하기.
- append : 리스트의
- insert(after:) : 리스트의 특정 노드 뒤에 값 추가( 삽입 )하기.
- push 구현.
- push(value: ) : 리스트의 맨 앞에 값 추가하기
12345678public mutating func push(_ value: Value) {// mutating 을 붙인 이유는 LinkedList 가 구조체 이기 때문입니다. 이 메소드는 LinkedList 구조체 하위에 들어가는 것입니다.// 구조체는 클래스와는 른 '값 타입' 이기 때문에 구조체 인스턴스 내부에서 값을 수정하고 싶으면 mutating 키워드를 붙여야 합니다.head = Node(value: value, next: head) // head 생성 , head 에 Node 인스턴스의 참조정보 저장 됨을 유의. Node 는 클래스 이기 때문에.if tail == nil {tail = head// head 의 참조정보를 tail 에 할당.// 참조 정보라고 해서 어렵게 들릴 수도 있지만 이게 정확한 것입니다. Node 는 클래스라서 그의 인스턴스에는 참조 정보가 저장될 뿐이라는 것 !}}cs ( 구조체, 클래스, 참조정보 등이 이해가 안가신다면 '클래스와 구조체' 글을 먼저 봐주세요! )
- push 실행
12345678910111213example(of: "push") { // 처음이라 각 단계마다 자세하게 설명합니다. 여기서 놓치면 뒤에 어려워요! 잘 따라오세요var list = LinkedList<Int>()list.push(3)// value = 3 인 노드의 참조정보가 list.head 에 할당되고, tail == nil 이므로 tail 에 head 의 참조정보가 할당됩니다.// 현재 value 3 , next nil 이고 head 와 tail 은 위치가 같습니다.list.push(2)// value = 2 인 노드의 참조정보가 list.head 에 할당되고 tail 은 nil 이 아니므로 새로 값이 설정되지 않는다.// 현재 value 2 , next 에는 이전 단계의 head 인 value 3 노드의 참조정보가 들어있겠죠?// tail 은 변함이 없으므로 그대로 value 3 인 노드의 참조정보가 있습니다.// 즉 ! 새로운 노드가 앞으로 가고, tail 노드는 가만있으면 자동으로 뒤로 가게 되니까 push 과정이 일어난 것이죠.list.push(1) // 마찬가지..^^print(list)}cs - 결과
- append 구현. ( 헷갈릴 수 있음!! )
- append(value: ) : 리스트의 끝에 값 추가하기.
1234567891011121314public mutating func append(_ value: Value) {guard !isEmpty else{ // 연결리스트가 비어있는지 체크 후 비어있다면 push 메소드 실행. 첫 번째 노드 추가하는 것 동일push(value)return}// 자 여기서 부터는 두 번째 이상 노드를 추가할 때 실행되는 과정.tail!.next = Node(value: value)// tail 은 head 와 같은 Node(1,nil) 인스턴스를 참조하고 있음을 유의// tail.next 에 새로운 Node 인스턴스 할당 하면 같은 참조정보를 가진 head.next 도 바뀌게 되겠죠?tail = tail?.next// tail 이라는 변수에 원래는 head 와 같은 첫 번째 노드 인스턴스의 참조를 가지고 있었지만// 새로 들어온 노드 인스턴스의 참조정보 할당해준다.// 그럼 자연스럽게 추가하는 노드를 tail 변수가 참조하게 되고 tail 이 뒷부분을 차지하는 것 처럼 된다.}cs - append 실행
- 이 부분이 헷갈리시죠? 클래스와 구조체가 값을 대하는 방식을 모르면 아예 이해가 않을 겁니다.
- 따라하면 그대로 되겠지만, 스스로 생각해보면 왜 이렇게 되는지 모르게 됩니다. 하나마나 인거죠 ㅠㅠ..
- 클래스와 구조체가 값을 대하는 방식에 대해선 여기에서 학습하세요
123456789101112131415example(of: "append") {var list = LinkedList<Int>()list.append(1) // 첫 노드니까 push(1) 과 동일한 과정이 실행되겠죠?list.append(2) // 여기서 부터 긴장// 두 번째 노드(값이 2) 가 추가됩니다. tail.next = Node(2) 가 실행되겠죠?// tail.next 는 tail 에 있는 참조정보를 이용해서 next 에 접근하는 것이죠?// 그 곳에 Node(2) 라는 새로운 노드 인스턴스를 할당합니다.// 현재 상태는 tail.next와 head.next 둘 다 Node(2) 를 가리키는 상태입니다.// tail 과 head 가 같은 Node(1) 을 가리키고 있었기 때문에 tail 로 접근해도 head 도 같이 바뀝니다. (참조의 특성이죠?)// tail = tail.next 가 실행됩니다.// 원래는 tail 과 head 가 같은 Node(1) 의 참조정보 가지고 있었는데 tail 에 tail.next 에 있는 Node(2) 의 참조정보 할당합니다.// 이로써 head 는 앞에꺼!, tail 은 뒤에 노드의 참조정보를 따로 가지게 되는 것이죠.// 이러면 연결리스트의 뒤에 추가 되고 append 과정이 수행되는 것입니다.list.append(3) // 마찬가지}cs - 결과
- insert 구현
- 리스트의 특정 노드 뒤에 값 추가( 삽입 )하기는 2 과정으로 수행됩니다.
- 첫째! 연결리스트의 특정 노드를 찾고
- 둘째! 찾은 노드 뒤에 새로운 노드를 추가하기.
- 첫 째 : 특정 노드 찾기.
1234567891011121314// Insert 1 - 삽입을 원하는 노드의 위치 ( index ) 찾기public func node(at index: Int) -> Node<Value>? { // 매개변수에 원하는 번째 노드 넣으면 노드 반환해줌^^var currentNode = head // 탐색하기 전 시작포인트 설정해주기. head 는 연결리스트의 첫 노드!var currentIndex = 0 // 시작 포인트 0 부터!while currentNode != nil && currentIndex < index {// 헤드노드가 nil 이 아니고 : 빈 노드인지 확인// 현재 노드 탐색하고 끝 포인트가 매개변수로 들어온 index 보다 작을 때 까지 무한반복.currentNode = currentNode!.next // 현재 노드가 다음 노드가 됨 -> 탐색맞쥬?currentIndex += 1 // 인덱스 하나 올라감. -> 하나하나 탐색!}return currentNode// 반환하는 현재 노드는 매개변수 index 의 값 번째 Node 가 된다.}cs - 둘 째 : 찾은 노드 위에 노드 삽입하기
12345678910111213141516171819// Insert 2 - 값을 삽입하기.public mutating func insert(_ value: Value, after node: Node<Value>) {// 두 번째 매개변수에 먼저 알아낸, 내가 원하는 특정 노드 넣어서 그 뒤에 값 삽입하기.guard tail !== node else {// tail 과 node 둘 모두 클래스의 인스턴스라서 참조정보를 가지고 있죠?// 그러므로 ==, != 는 할 수 없습니다. 값이 아니라 참조정보를 비교해야 하니까요.// ===, !== 를 이용해서 해당 인스턴스를 비교하는 방법을 이용합니다.// 내가 넣어준 두 번째 매개변수 node 가 tail 노드라면 append() 쓰면 됩니다.append(value)// return tail! -> 새로 들어간 노드 반환하고 싶으면 요거 쓰시면 됨.return}node.next = Node(value: value, next: node.next)// 특정 노드의 인스턴스를 알고 있는 상태입니다. (탐색해서 두 번째 매개변수로 넣어주었으니까요.)// 그 노드의 다음 노드에 삽입하고자 하는 새로운 노드의 인스턴스 할당합니다.// 새로운 노드의 next 는 삽입하기 전 노드의 다음노드를 넣어줍니다.// 이러면 가운데 쏙 들어가게 되겠죠?//return node.next! -> 새로 들어간 노드 반환하고 싶으면 요거 쓰삼.}cs - insert 실행
12345678910example(of: "insert at a particular index"){var list = LinkedList<Int>()list.push(3)list.push(2)list.push(1) // 1, 2, 3 인 연결리스트print(" 삽입 전 리스트 \(list)")list.insert(-1, after: list.node(at: 1)!) // 인덱스 1 번째 노드 (컴퓨터에선 2번째 겠죠?) 뒤에 -1 삽입print(" 삽입 후 리스트 \(list)")}cs - 결과
'스위프트: Swift > 자료구조 : Data Strutures in Swift' 카테고리의 다른 글
댓글