循环链表
定义
双向链表是在单链表的每个结点中,再设置一个指向前驱结点的指针域。
代码实现
package DoubleLinkling
// 双向链表结点
type DoubleLinkNode struct {
value interface{}
// 上一个结点
prev *DoubleLinkNode
// 下一个结点
next *DoubleLinkNode
}
// 构造结点
func NewDoubleLinkNode(data interface{}) *DoubleLinkNode {
return &DoubleLinkNode{
value: data,
prev: nil,
next: nil,
}
}
// 返回数据
func (node *DoubleLinkNode) Value() interface{} {
return node.value
}
// 返回上一个结点
func (node *DoubleLinkNode) Prev() *DoubleLinkNode {
return node.prev
}
// 返回下一个结点
func (node *DoubleLinkNode) Next() *DoubleLinkNode {
return node.next
}
// 定义双向链表接口
type DoubleLink interface {
// 返回第一个数据结点
GetFirstNode() *DoubleLinkNode
// 插入结点(头插法)
InsertNodeFront(node *DoubleLinkNode)
// 插入结点(尾插法)
InsertNodeBack(node *DoubleLinkNode)
// 插入某结点前
InsertNodeValueFront(dest interface{}, node *DoubleLinkNode) bool
// 插入某结点后
InsertNodeValueBack(dest interface{}, node *DoubleLinkNode) bool
// 获取指定索引上的结点
GetNodeAtIndex(index int) *DoubleLinkNode
// 删除结点
DeleteNode(dest *DoubleLinkNode) bool
// // 删除指定索引上的结点
// DeleteAtIndex(index int) bool
// 返回字符串
String() string
}
// 双链表
type DoubleLinkList struct {
// 头指针
head *DoubleLinkNode
// 长度
length int
}
// 初始化双向链表
func NewDoubleLinkList() *DoubleLinkList {
// 初始化头结点
head := NewDoubleLinkNode(nil)
return &DoubleLinkList{
head: head,
length: 0,
}
}
// 获取链表长度
func (dist *DoubleLinkList) GetLength() int {
return dist.length
}
// 获取第一个数据结点
func (dist *DoubleLinkList) GetFirstNode() *DoubleLinkNode {
return dist.head.next
}
// 获取指定索引上的结点
func (dist *DoubleLinkList) GetNodeAtIndex(index int) *DoubleLinkNode {
// 索引越界
if index > dist.length-1 || index < 0 {
return nil
}
// 备份头结点
bak := dist.head
// 向后循环
for index > -1 {
bak = bak.next
index--
}
return bak
}
// 头部插入
func (dist *DoubleLinkList) InsertNodeFront(node *DoubleLinkNode) {
// 空链表
if dist.head.next == nil {
// 第一个数据结点设为新结点
dist.head.next = node
// 新结点next指针指向nil
node.next = nil
// 新结点prev指针指向头结点
node.prev = dist.head
dist.length++
return
}
// 备份头结点
bak := dist.head
// 新结点的next指针,指向原来的第一个数据结点
node.next = bak.next
// 第一个数据结点的prev指向新结点
bak.next.prev = node
// 头结点的next指针指向新结点
bak.next = node
// 新结点的prev指针指向头结点
node.prev = bak
dist.length++
return
}
// 尾部插入
func (dist *DoubleLinkList) InsertNodeBack(node *DoubleLinkNode) {
// 空链表
if dist.head.next == nil {
// 第一个数据结点设为新结点
dist.head.next = node
// 新结点next指针指向nil
node.next = nil
// 新结点prev指针指向头结点
node.prev = dist.head
dist.length++
return
}
// 备份头结点
bak := dist.head
// 循环到链表末尾
for bak.next != nil {
bak = bak.next
}
// 终端结点的指针指向新结点
bak.next = node
// 新结点的prev指针指向原来的终端结点
node.prev = bak
dist.length++
return
}
// 插入某结点前
func (dist *DoubleLinkList) InsertNodeValueFront(dest interface{}, node *DoubleLinkNode) bool {
// 备份头结点
bak := dist.head
// 循环到末尾,直至找到目标结点
for bak.next != nil && bak.next.value != dest {
bak = bak.next
}
// 找到
if bak.next.value == dest {
// 目标结点的上一个数据结点的next指针,赋值给新结点的指针
node.next = bak.next
// 新结点的prev指针指向bak
node.prev = bak
// 目标结点的prev指针指向node结点
bak.next.prev = node
// 目标结点的上一个数据结点的next指针,指向新结点
bak.next = node
dist.length++
return true
}
return false
}
// 插入某结点后
func (dist *DoubleLinkList) InsertNodeValueBack(dest interface{}, node *DoubleLinkNode) bool {
// 备份头结点
bak := dist.head
// 循环到末尾,直至找到目标结点
for bak.next != nil && bak.next.value != dest {
bak = bak.next
}
// 找到
if bak.next.value == dest {
// 如果目标结点有后续结点
if bak.next.next != nil {
// 目标结点的后续结点的prev指针赋值给新结点
bak.next.next.prev = node
}
// 目标结点的next指针,赋值给新结点的next指针
node.next = bak.next.next
// 目标结点的next指针指向新结点
bak.next.next = node
// 新结点的prev指针,指向目标结点
node.prev = bak.next
dist.length++
return true
}
return false
}
// 删除结点
func (dist *DoubleLinkList) DeleteNode(dest *DoubleLinkNode) bool {
// 备份头结点
bak := dist.head
// 结点为空
if dest == nil {
return false
}
// 循环到末尾,直至找到目标结点
for bak.next != nil && bak.next != dest {
bak = bak.next
}
// 找到
if bak.next == dest {
// 如果目标结点有后续结点
if bak.next.next != nil {
// 目标结点的后续结点的prev指针赋值给当前结点
bak.next.next.prev = bak
}
// 目前结点的指针赋值给目标结点的上一个数据结点的指针
bak.next = bak.next.next
dist.length--
return true
}
return false
}
// 删除指定索引上的结点
func (dist *DoubleLinkList) DeleteAtIndex(index int) bool {
// 索引越界
if index > dist.length-1 || index < 0 {
return false
}
// 备份头结点
bak := dist.head
// 向后循环,找到前一个结点
for index > 0 {
bak = bak.next
index--
}
// 如果目标结点有后续结点
if bak.next.next != nil {
// 目标结点的后续结点的prev指针赋值给前一个结点
bak.next.next.prev = bak
}
// 目前结点的next指针,赋值给目标结点的上一个数据结点的next指针
bak.next = bak.next.next
dist.length--
return true
}
// 返回字符串
func (dist *DoubleLinkList) String() string {
var distString1 string
var distString2 string
// 头结点
p := dist.head
// 循环输出
for p.next != nil {
distString1 += fmt.Sprintf("%v-->", p.next.value)
p = p.next
}
distString1 += fmt.Sprintf("nil")
distString1 += "\n"
for p != dist.head {
distString2 += fmt.Sprintf("<--%v", p.value)
p = p.prev
}
distString1 += fmt.Sprintf("nil")
return distString1 + distString2 + "\n"
}