package main
import "fmt"
type Node struct {
next *Node
val int
}
//결합성 높이고 의존성 줄여~
//관련있는 애들 묶어주자. 하나의 struct으로 묶기
//1. 새 struct만듦
type LinkedList struct {
//루트를 포인트형으로 가지고 있음
root *Node
tail *Node
}
//2. 메서드 3개 추가함 add remove printNode
//LinkedList가 가지고 있는기능, 메서드
func (l *LinkedList) AddNode(val int) {
if l.root ==nil {
//없는 상태면
//루트는, 새로만든 노드의 메모리 주소를 포인트 형태로 갖고 있고
l.root = &Node{val:val}
//테일은 자료가 없으니까 루트랑 똑같음
l.tail= l.root
return
}
//꼬리 다음을 새로운 노드 만들어서 붙이면 됨
l.tail.next = &Node{val:val}
l.tail= l.tail.next
}
func (l *LinkedList) RemoveNode(node *Node ) {
if node == l.root {
l.root = l.root.next
node.next = nil
return
}
prev := l.root
for prev.next != node {
prev = prev.next
}
if node== l.tail {
prev.next = nil
l.tail = prev
} else {
prev.next= prev.next.next
}
node.next = nil
}
func (l *LinkedList) PrintNodes() {
//그다음 노드가 없을때까지 전진
node := l.root
for node.next != nil {
fmt.Printf("%d -> ",node.val)
node = node.next
}
fmt.Printf("%d\n",node.val)
}
func main() {
//이안에 root와 tail 포함되어있어서 따로 만들 필요 없음
list := &LinkedList{}
list.AddNode(0)
// var root *Node
// var tail *Node
// //노드의 주소를 root로 가지고 있음
// root = &Node{val: 0}
// //맨처음꺼 하나만 있을 때는 tail은 root와 같음
// tail= root
for i:=1; i<10; i++ {
// tail= AddNode(tail,i)
list.AddNode(i)
}
list.PrintNodes()
list.RemoveNode(list.root.next)
list.PrintNodes()
list.RemoveNode(list.root)
list.PrintNodes()
list.RemoveNode(list.tail)
list.PrintNodes()
fmt.Printf("tail:%d\n", list.tail.val)
}
// //노드 추가하는 거를 함수로 만들게요 //새로 추가된 노드로 반환값있어야함
// func AddNode(tail *Node, val int) *Node {
// // var tail *Node
// // tail = root
// // for tail.next != nil {
// // tail = tail.next
// // }
// //맨 마지막에 새 노드 추가
// node := &Node{val: val}
// tail.next = node
// return node
// }
// func RemoveNode(node *Node,root *Node, tail *Node ) (*Node, *Node) {
// //내가 지우고자 하는 노드가 맨 앞인 경우
// if node == root {
// //새로운 루트는 기존 루트의 다음이 됨
// root = root.next
// if root == nil {
// tail= nil
// }
// return root, tail
// }
// //이전 노드 다음이 현재 지우고자 하는 노드가 아니면
// //이전을 이전다음으로 보내. 맞게 되면 for문 빠져나가
// prev := root
// for prev.next != node {
// prev = prev.next
// }
// if node== tail {
// prev.next = nil
// tail = prev
// } else {
// prev.next= prev.next.next
// }
// return root, tail
// }
// func PrintNodes(root *Node) {
// //그다음 노드가 없을때까지 전진
// node := root
// for node.next != nil {
// fmt.Printf("%d -> ",node.val)
// node = node.next
// }
// fmt.Printf("%d\n",node.val)
// }
Go
- linkedlist struct로 코드정리 (터커강의 코드) 2021.12.08
- 동적배열 slice개념 (go,append,슬라이스,배열) 2021.12.07
- 함수 호출은 무조건 복사로 이뤄진다 (go강의 중에서) 2021.12.01
linkedlist struct로 코드정리 (터커강의 코드)
동적배열 slice개념 (go,append,슬라이스,배열)
동적배열 종류
c++ STL에 vector / java에는 array list/ c#에는 list / golang에는 slice
동적배열은? <--------------------------> 정적배열(fixed size array 길이 정해진 배열 [10]int)
[]int
길이 변하는 배열
실제 고정 길이의 배열이 따로 있고 그 고정 길이 배열을 가르키고, 포인트하고 있다!!
배열의 길이가 늘어나면 새로운 더 긴 배열을 만든 다음에 거기로 모든 값을 복사시키고 그 배열로 포인트 바꿈
"동적 배열은 실제 배열을 포인트하고 있다."
동적배열선언 만드는 여러 방법들
var a [] int
a:=[]int{초기값}
a:=make([]int,3)
a:=make([ ]int, length, capacity)
length 길이
내가 쓰고 있는 길이
capacity 확보해놓은 공간
(동적배열, 값을 추가할 때 배열 늘리는데 2배씩 확보해놓음 그래서 길이와 cap다를 수 있음)
항목 추가 명령어 append
a:= []int {}
a= append(a,1)
a에 다시 대입
슬라이스 = append(슬라이스,항목)
a[start Index : End Index]
(start ~ end] 마지막은 포함안됨
a[10]int{1,2,3,4,5,6,7,8,9,10}
a[4:6]
a[시작인덱스 5번째 : 6번째]
즉 5번째~6번째까지 슬라이스 의미
a[4: ]
5번째부터~ 끝까지
a[ :4]
처음부터 ~4번째까지
슬라이스는 원래 배열이 있고 그 배열을 가르키는 포인터
슬라이스는 잘라내는 게 아니라 그 일부분을 가르키는 배열!
//추가된 값이 원래길이,확보된 공간 벗어나게 되면
새 메모리 만들어서 거기에 복사됨. 그럼 메모리 주소 바뀜!
코드로 보기
package main
import "fmt"
func main() {
//////////////////////////////////len cap 메모리를 새로 확보해야돼서 주소도 달라짐 새로운 메모리에 담아서
// a:= []int{1,2}
// b:= append(a,3)
// fmt.Printf("%p %p\n",a,b)
// for i := 0; i<len(a); i++{
// fmt.Printf("%d,",a[i])
// }
// fmt.Println()
// for i := 0; i<len(b); i++{
// fmt.Printf("%d,",b[i])
// }
// fmt.Println()
// fmt.Println(cap(a)," ", cap(b))
///////make로 넣기//메모리 같아서 b값 바꾸니까 a도 바뀜
// a:= make([]int, 2,4)
// a[0]=1
// a[1]=2
// b:= append(a,3)
// fmt.Printf("%p %p\n",a,b)
// fmt.Println(a)
// fmt.Println(b)
// b[0]=4
// b[1]=5
// fmt.Println(a)
// fmt.Println(b)
//////처음부터 아예 공간을 다르게 확보하게 싶다면
// a:= []int{1,2}
//
// a := make([]int, 2, 4)
// a[0] = 1
// a[1] = 2
// //슬라이스 새로 만듦
// b := make([]int, len(a))
// for i := 0; i < len(a); i++ {
// b[i] = a[i]
// }
// b = append(b, 3)
// fmt.Printf("%p %p\n",a,b)
}
3가지 경우임
1. 값넘쳐서 새 메모리에 담아짐
2. 값안넘쳐서 메모리 a랑 b같음 b변경될때 그대로인 메모리안에서 바뀌어서 a도 바뀜
3. 아예 슬라이스 새로 만들어서 공간 따로 확보함
//배열 뒤에서 하나씩 지우기
package main
import "fmt"
//뒤에 하나씩 지워나가는 함수//배열 반환,int 맨뒤에 값도 반환
func RemoveBack(a []int) ([]int, int){
//처음부터 a배열길이에서 1뺀것, 즉 맨뒤에를 하나 없앤다
return a[ :len(a)-1], a[len(a)-1]
}
func main() {
a:=[]int{1,2,3,4,5,6,7,8,9,10}
for i :=0; i<5; i++{
var lastlostone int
a, lastlostone= RemoveBack(a)
fmt.Printf("%d,",lastlostone)
}
fmt.Println()
fmt.Println(a)
}
'웹 공부' 카테고리의 다른 글
시퀄라이즈 테이블 코드 자동 생성하는 법(mysql,database,sequelize) (0) | 2022.03.10 |
---|---|
rollbackFailedOptional 문제 (0) | 2022.02.28 |
printf와 println 차이 (0) | 2021.12.07 |
%d , %p의 의미는? (C 언어 변환문자 의미 자료형) (0) | 2021.12.07 |
aws 비용청구 환불은 받았지만 찜찜..(탄력적 IP,사용하지 않는 인스턴스) (3) | 2021.12.05 |
함수 호출은 무조건 복사로 이뤄진다 (go강의 중에서)
함수 호출 과정은 무조건 복사로 이뤄진다
복사 일어날 때 값이 복사되는 거지
그 메모리가 그대로 전달되는 게 아님~~!!!
이걸 해결하기 위해서 포인터가 나옴
//
객체, 구조체에 대해 알아봤고
구조체는 속성 모아놓은거임
기능을 가질 수도 있음 (함수)
속성, 기능 가지고 있는게 구조체