NOTE
2.3 linkedlist
1. 是什么 2. 数组 vs 链表 数组按照索引查找快,链表插入删除快 3. 单向链表 3.1. 数据结构 - 头节点 - 长度 3.2. API 3.3. 实现 3.3.1. 测试 4. 双向链表 4.1. 数据结构 - 头节点 - 尾节点 - 长度 4.2. API - 同单向链表 4.3.
这是历史学习笔记,可能存在过时或不完整的理解。
1. 是什么
2. 数组 vs 链表
数组按照索引查找快,链表插入删除快
3. 单向链表
3.1. 数据结构
- 头节点
- 长度
3.2. API
type IList interface {
//打印所有元素
String() string
//已使用的长度
Length() int
//是否为空
IsEmpty() bool
//index为0的位置添加一个元素,其他后移
AddFirst(e model.Comparable) error
//index的位置添加一个元素,其他后移
Add(index int, e model.Comparable) error
//index为length-1的位置添加一个元素,其他后移
AddLast(e model.Comparable) error
//获取index位置的元素
Get(index int) (model.Comparable, error)
//获取第一个元素
GetFirst() (model.Comparable, error)
//获取最后一个元素
GetLast() (model.Comparable, error)
//更新index位置的元素为e
Set(index int, e model.Comparable) error
//是否包含e
Contains(e model.Comparable) bool
//找到e,返回下标
Find(e model.Comparable) int
//删除e,返回下标
RemoveElement(e model.Comparable) bool
//index的位置删除一个元素,其他前移
Remove(index int) (model.Comparable, error)
//index为0的位置删除一个元素,其他前移
RemoveFirst() (model.Comparable, error)
//index为length-1的位置删除一个元素,其他前移
RemoveLast() (model.Comparable, error)
}
3.3. 实现
const NonExists = -1
type LinkedListNode struct {
e model.Comparable
next *LinkedListNode
}
func NewLinkedListNode(e model.Comparable, next *LinkedListNode) *LinkedListNode {
return &LinkedListNode{e: e, next: next}
}
func (l *LinkedListNode) String() string {
return fmt.Sprintf("%v", l.e)
}
type LinkedList struct {
dummyHead *LinkedListNode
length int
}
func NewLinkedList() *LinkedList {
return &LinkedList{
dummyHead: NewLinkedListNode(nil, nil),
length: 0,
}
}
func (l *LinkedList) String() string {
str := fmt.Sprintf("length=%v, data=[", l.Length())
node := l.dummyHead.next
for i := 0; i < l.Length(); i++ {
str += fmt.Sprintf("%v->", node)
node = node.next
}
str = strings.TrimRight(str, "->")
str += "]"
return str
}
func (l *LinkedList) Length() int {
return l.length
}
func (l *LinkedList) IsEmpty() bool {
return l.Length() == 0
}
// O(1)
func (l *LinkedList) AddFirst(e model.Comparable) error {
return l.Add(0, e)
}
// O(N)
func (l *LinkedList) Add(index int, e model.Comparable) error {
if index < 0 || index > l.Length() {
return fmt.Errorf("out of bound")
}
node := l.dummyHead
for i := 0; i < index; i++ {
node = node.next
}
node.next = NewLinkedListNode(e, node.next)
l.length++
return nil
}
// O(1)
func (l *LinkedList) AddLast(e model.Comparable) error {
return l.Add(l.Length(), e)
}
// O(N)
func (l *LinkedList) Get(index int) (model.Comparable, error) {
if index < 0 || index > l.Length()-1 {
return nil, fmt.Errorf("out of bound")
}
node := l.dummyHead.next
for i := 0; i < index; i++ {
node = node.next
}
return node.e, nil
}
// O(1)
func (l *LinkedList) GetFirst() (model.Comparable, error) {
return l.Get(0)
}
// O(N)
func (l *LinkedList) GetLast() (model.Comparable, error) {
return l.Get(l.Length() - 1)
}
// O(N)
func (l *LinkedList) Set(index int, e model.Comparable) error {
if index < 0 || index > l.Length()-1 {
return fmt.Errorf("out of bound")
}
node := l.dummyHead.next
for i := 0; i < index; i++ {
node = node.next
}
node.e = e
return nil
}
// O(N)
func (l *LinkedList) Contains(e model.Comparable) bool {
index := l.Find(e)
if index == NonExists {
return false
}
return true
}
// O(N)
func (l *LinkedList) Find(e model.Comparable) int {
node := l.dummyHead.next
for i := 0; i < l.Length(); i++ {
if node.e.CompareTo(e) == 0 {
return i
}
node = node.next
}
return NonExists
}
// O(N)
func (l *LinkedList) RemoveElement(e model.Comparable) bool {
index := l.Find(e)
if index == NonExists {
return false
}
_, _ = l.Remove(index)
return true
}
// O(N)
func (l *LinkedList) Remove(index int) (model.Comparable, error) {
if index < 0 || index > l.Length()-1 {
return nil, fmt.Errorf("out of bound")
}
prev := l.dummyHead
removed := l.dummyHead.next
for i := 0; i < index; i++ {
prev = prev.next
removed = removed.next
}
prev.next = removed.next
removed.next = nil
l.length--
return removed.e, nil
}
// O(1)
func (l *LinkedList) RemoveFirst() (model.Comparable, error) {
return l.Remove(0)
}
// O(N)
func (l *LinkedList) RemoveLast() (model.Comparable, error) {
return l.Remove(l.Length() - 1)
}
3.3.1. 测试
func TestLinkedList(t *testing.T) {
list := NewLinkedList()
fmt.Println(list)
e1 := model.NewElement(1)
e2 := model.NewElement(2)
e0 := model.NewElement(0)
list.AddLast(e1)
list.AddLast(e2)
list.AddFirst(e0)
fmt.Println(list)
list.RemoveFirst()
list.RemoveLast()
fmt.Println(list)
fmt.Println(list.Contains(e1))
fmt.Println(list.Find(e1))
fmt.Println(list.RemoveElement(e1))
fmt.Println(list)
fmt.Println(list.IsEmpty())
}
4. 双向链表
4.1. 数据结构
- 头节点
- 尾节点
- 长度
4.2. API
- 同单向链表
4.3. 实现
package list
import (
"fmt"
"my_algorithm/model"
"strings"
)
type DoubleLinkedListNode struct {
e model.Comparable
prev *DoubleLinkedListNode
next *DoubleLinkedListNode
}
func NewDoubleLinkedListNode(e model.Comparable, prev *DoubleLinkedListNode, next *DoubleLinkedListNode) *DoubleLinkedListNode {
return &DoubleLinkedListNode{e: e, prev: prev, next: next}
}
func (l *DoubleLinkedListNode) String() string {
return fmt.Sprintf("%v", l.e)
}
type DoubleLinkedList struct {
head *DoubleLinkedListNode
tail *DoubleLinkedListNode
length int
}
func NewDoubleLinkedList() *DoubleLinkedList {
return &DoubleLinkedList{
head: nil,
tail: nil,
length: 0,
}
}
func (l *DoubleLinkedList) String() string {
str := fmt.Sprintf("length=%v, head to tail=[", l.Length())
node := l.head
for i := 0; i < l.Length(); i++ {
str += fmt.Sprintf("%v->", node)
node = node.next
}
str = strings.TrimRight(str, "->")
str += "]"
str2 := "]"
node = l.tail
for i := 0; i < l.Length(); i++ {
str2 = fmt.Sprintf("<-%v", node) + str2
node = node.prev
}
str2 = strings.TrimLeft(str2, "<-")
str2 = fmt.Sprintf(", tail to head=[%v", str2)
return str + str2
}
func (l *DoubleLinkedList) Length() int {
return l.length
}
func (l *DoubleLinkedList) IsEmpty() bool {
return l.Length() == 0
}
// O(1)
func (l *DoubleLinkedList) AddFirst(e model.Comparable) error {
newNode := NewDoubleLinkedListNode(e, nil, l.head)
//一个节点都没有
if l.head == nil {
l.head = newNode
l.tail = l.head
} else {
l.head.prev = newNode
l.head = newNode
}
l.length++
return nil
}
// O(N)
func (l *DoubleLinkedList) Add(index int, e model.Comparable) error {
if index < 0 || index > l.Length() {
return fmt.Errorf("out of bound")
}
if index == 0 {
return l.AddFirst(e)
} else if index == l.Length() {
return l.AddLast(e)
} else {
prev := l.head
for i := 0; i < index-1; i++ {
prev = prev.next
}
newNode := NewDoubleLinkedListNode(e, prev, prev.next)
prev.next.prev = newNode
prev.next = newNode
l.length++
return nil
}
}
// O(1)
func (l *DoubleLinkedList) AddLast(e model.Comparable) error {
newNode := NewDoubleLinkedListNode(e, l.tail, nil)
//一个节点都没有
if l.tail == nil {
l.tail = newNode
l.head = l.tail
} else {
l.tail.next = newNode
l.tail = newNode
}
l.length++
return nil
}
// O(N)
func (l *DoubleLinkedList) Get(index int) (model.Comparable, error) {
if index < 0 || index > l.Length()-1 {
return nil, fmt.Errorf("out of bound")
}
node := l.head
for i := 0; i < index; i++ {
node = node.next
}
return node.e, nil
}
// O(1)
func (l *DoubleLinkedList) GetFirst() (model.Comparable, error) {
return l.Get(0)
}
// O(1)
func (l *DoubleLinkedList) GetLast() (model.Comparable, error) {
return l.Get(l.Length() - 1)
}
// O(N)
func (l *DoubleLinkedList) Set(index int, e model.Comparable) error {
if index < 0 || index > l.Length()-1 {
return fmt.Errorf("out of bound")
}
node := l.head
for i := 0; i < index; i++ {
node = node.next
}
node.e = e
return nil
}
// O(N)
func (l *DoubleLinkedList) Contains(e model.Comparable) bool {
index := l.Find(e)
if index == NonExists {
return false
}
return true
}
// O(N)
func (l *DoubleLinkedList) Find(e model.Comparable) int {
node := l.head
for i := 0; i < l.Length(); i++ {
if node.e.CompareTo(e) == 0 {
return i
}
node = node.next
}
return NonExists
}
// O(N)
func (l *DoubleLinkedList) RemoveElement(e model.Comparable) bool {
index := l.Find(e)
if index == NonExists {
return false
}
_, _ = l.Remove(index)
return true
}
// O(N)
func (l *DoubleLinkedList) Remove(index int) (model.Comparable, error) {
if index < 0 || index > l.Length()-1 {
return nil, fmt.Errorf("out of bound")
}
if index == 0 {
return l.RemoveFirst()
} else if index == l.Length()-1 {
return l.RemoveLast()
} else {
prev := l.head
for i := 0; i < index-1; i++ {
prev = prev.next
}
removed := prev.next
prev.next = removed.next
removed.next.prev = prev
removed.next = nil
removed.prev = nil
l.length--
return removed.e, nil
}
}
// O(1)
func (l *DoubleLinkedList) RemoveFirst() (model.Comparable, error) {
if l.head == nil {
return nil, fmt.Errorf("out of bound")
}
removed := l.head
//只有一个节点
if l.head == l.tail {
l.head = nil
l.tail = nil
} else {
l.head = l.head.next
l.head.prev = nil
}
l.length--
return removed.e, nil
}
// O(1)
func (l *DoubleLinkedList) RemoveLast() (model.Comparable, error) {
if l.tail == nil {
return nil, fmt.Errorf("out of bound")
}
removed := l.tail
//只有一个节点
if l.head == l.tail {
l.head = nil
l.tail = nil
} else {
l.tail = l.tail.prev
l.tail.next = nil
}
l.length--
return removed.e, nil
}
4.3.1. 测试
func TestDoubleLinkedList(t *testing.T) {
list := NewDoubleLinkedList()
fmt.Println(list)
e1 := model.NewElement(1)
e2 := model.NewElement(2)
e0 := model.NewElement(0)
list.AddLast(e1)
list.AddLast(e2)
list.AddFirst(e0)
fmt.Println(list)
list.RemoveFirst()
list.RemoveLast()
fmt.Println(list)
fmt.Println(list.Contains(e1))
fmt.Println(list.Find(e1))
fmt.Println(list.RemoveElement(e1))
fmt.Println(list)
fmt.Println(list.IsEmpty())
fmt.Println("===============")
list.AddFirst(e0)
list.AddLast(e2)
list.Add(1, e1)
list.Add(1, e2)
list.Add(1, e1)
fmt.Println(list)
list.Remove(1)
fmt.Println(list)
list.Remove(1)
fmt.Println(list)
fmt.Println("****************")
list.Add(list.Length()-1, e1)
fmt.Println(list)
list.Add(list.Length(), e0)
fmt.Println(list)
}
5. 双向循环链表
5.1. 数据结构
- 头节点
- 尾节点
- 长度
5.2. API
- 同单向链表
5.3. 实现
package list
import (
"fmt"
"my_algorithm/model"
"strings"
)
type CircleDoubleLinkedListNode struct {
e model.Comparable
prev *CircleDoubleLinkedListNode
next *CircleDoubleLinkedListNode
}
func NewCircleDoubleLinkedListNode(e model.Comparable, prev *CircleDoubleLinkedListNode, next *CircleDoubleLinkedListNode) *CircleDoubleLinkedListNode {
return &CircleDoubleLinkedListNode{e: e, prev: prev, next: next}
}
func (l *CircleDoubleLinkedListNode) String() string {
return fmt.Sprintf("%v", l.e)
}
type CircleDoubleLinkedList struct {
head *CircleDoubleLinkedListNode
tail *CircleDoubleLinkedListNode
length int
}
func NewCircleDoubleLinkedList() *CircleDoubleLinkedList {
return &CircleDoubleLinkedList{
head: nil,
tail: nil,
length: 0,
}
}
func (l *CircleDoubleLinkedList) String() string {
str := fmt.Sprintf("length=%v, head to tail=[", l.Length())
node := l.head
for i := 0; i < l.Length(); i++ {
str += fmt.Sprintf("%v->", node)
node = node.next
}
str = strings.TrimRight(str, "->")
str += "]"
str2 := "]"
node = l.tail
for i := 0; i < l.Length(); i++ {
str2 = fmt.Sprintf("<-%v", node) + str2
node = node.prev
}
str2 = strings.TrimLeft(str2, "<-")
str2 = fmt.Sprintf(", tail to head=[%v", str2)
return str + str2
}
func (l *CircleDoubleLinkedList) Length() int {
return l.length
}
func (l *CircleDoubleLinkedList) IsEmpty() bool {
return l.Length() == 0
}
// O(1)
func (l *CircleDoubleLinkedList) AddFirst(e model.Comparable) error {
//一个节点都没有
newNode := NewCircleDoubleLinkedListNode(e, l.tail, l.head)
if l.head == nil {
newNode.next = newNode
newNode.prev = newNode
l.head = newNode
l.tail = l.head
} else {
l.tail.next = newNode
l.head.prev = newNode
l.head = newNode
}
l.length++
return nil
}
// O(N)
func (l *CircleDoubleLinkedList) Add(index int, e model.Comparable) error {
if index < 0 || index > l.Length() {
return fmt.Errorf("out of bound")
}
if index == 0 {
return l.AddFirst(e)
} else if index == l.Length() {
return l.AddLast(e)
} else {
prev := l.head
for i := 0; i < index-1; i++ {
prev = prev.next
}
newNode := NewCircleDoubleLinkedListNode(e, prev, prev.next)
prev.next.prev = newNode
prev.next = newNode
l.length++
return nil
}
}
// O(1)
func (l *CircleDoubleLinkedList) AddLast(e model.Comparable) error {
//一个节点都没有
newNode := NewCircleDoubleLinkedListNode(e, l.tail, l.head)
if l.tail == nil {
newNode.next = newNode
newNode.prev = newNode
l.head = newNode
l.tail = l.head
} else {
l.tail.next = newNode
l.head.prev = newNode
l.tail = newNode
}
l.length++
return nil
}
// O(N)
func (l *CircleDoubleLinkedList) Get(index int) (model.Comparable, error) {
if index < 0 || index > l.Length()-1 {
return nil, fmt.Errorf("out of bound")
}
node := l.head
for i := 0; i < index; i++ {
node = node.next
}
return node.e, nil
}
// O(1)
func (l *CircleDoubleLinkedList) GetFirst() (model.Comparable, error) {
return l.Get(0)
}
// O(1)
func (l *CircleDoubleLinkedList) GetLast() (model.Comparable, error) {
return l.Get(l.Length() - 1)
}
// O(N)
func (l *CircleDoubleLinkedList) Set(index int, e model.Comparable) error {
if index < 0 || index > l.Length()-1 {
return fmt.Errorf("out of bound")
}
node := l.head
for i := 0; i < index; i++ {
node = node.next
}
node.e = e
return nil
}
// O(N)
func (l *CircleDoubleLinkedList) Contains(e model.Comparable) bool {
index := l.Find(e)
if index == NonExists {
return false
}
return true
}
// O(N)
func (l *CircleDoubleLinkedList) Find(e model.Comparable) int {
node := l.head
for i := 0; i < l.Length(); i++ {
if node.e.CompareTo(e) == 0 {
return i
}
node = node.next
}
return NonExists
}
// O(N)
func (l *CircleDoubleLinkedList) RemoveElement(e model.Comparable) bool {
index := l.Find(e)
if index == NonExists {
return false
}
_, _ = l.Remove(index)
return true
}
// O(N)
func (l *CircleDoubleLinkedList) Remove(index int) (model.Comparable, error) {
if index < 0 || index > l.Length()-1 {
return nil, fmt.Errorf("out of bound")
}
if index == 0 {
return l.RemoveFirst()
} else if index == l.Length()-1 {
return l.RemoveLast()
} else {
prev := l.head
for i := 0; i < index-1; i++ {
prev = prev.next
}
removed := prev.next
prev.next = removed.next
removed.next.prev = prev
removed.next = nil
removed.prev = nil
l.length--
return removed.e, nil
}
}
// O(1)
func (l *CircleDoubleLinkedList) RemoveFirst() (model.Comparable, error) {
if l.head == nil {
return nil, fmt.Errorf("out of bound")
}
removed := l.head
//只有一个节点
if l.head == l.tail {
l.head = nil
l.tail = nil
} else {
l.head = l.head.next
l.head.prev = l.tail
l.tail.next = l.head
}
l.length--
return removed.e, nil
}
// O(1)
func (l *CircleDoubleLinkedList) RemoveLast() (model.Comparable, error) {
if l.tail == nil {
return nil, fmt.Errorf("out of bound")
}
removed := l.tail
//只有一个节点
if l.head == l.tail {
l.head = nil
l.tail = nil
} else {
l.tail = l.tail.prev
l.tail.next = l.head
l.head.prev = l.tail
}
l.length--
return removed.e, nil
}
5.3.1. 测试
func TestCircleDoubleLinkedList(t *testing.T) {
list := NewCircleDoubleLinkedList()
fmt.Println(list)
e1 := model.NewElement(1)
e2 := model.NewElement(2)
e0 := model.NewElement(0)
list.AddLast(e1)
list.AddLast(e2)
list.AddFirst(e0)
fmt.Println(list)
list.RemoveFirst()
list.RemoveLast()
fmt.Println(list)
fmt.Println(list.Contains(e1))
fmt.Println(list.Find(e1))
fmt.Println(list.RemoveElement(e1))
fmt.Println(list)
fmt.Println(list.IsEmpty())
fmt.Println("===============")
list.AddFirst(e0)
list.AddLast(e2)
list.Add(1, e1)
list.Add(1, e2)
list.Add(1, e1)
fmt.Println(list)
list.Remove(1)
fmt.Println(list)
list.Remove(1)
fmt.Println(list)
fmt.Println("****************")
list.Add(list.Length()-1, e1)
fmt.Println(list)
list.Add(list.Length(), e0)
fmt.Println(list)
}
6. 刷题套路
6.1. 双指针
- 两个指针指向同一个节点,同向而行
- 一个块一个慢,距离隔开多少
- 两个指针移动速度
fast := head
slow := head
// 判断fast 和 fast.Next都不为nil 避免空指针
for fast != nil && fast.Next != nil {
}
6.2. 递归
6.3. 删除或者插入
先考虑删除一般情况:即非头节点,再考虑删除头节点 或者用一个伪节点统一处理头节点和非头节点