showliuzp 2025-10-18 17:06 采纳率: 84.3%
浏览 3
已结题

golang删除链表节点如何做到不侵入


//链表

//并发安全单链表
type SingleNode struct {
    Data interface{}
    Next *SingleNode
}

type SingleList struct {
    mutex *sync.RWMutex //读写锁

    Head  *SingleNode   //头节点
    Tail  *SingleNode   //尾节点

    Size  uint          //总数
}

func NewList() *SingleList {
    return &SingleList{
        Size:  0,
        Head:  nil,
        Tail:  nil,
        mutex: new(sync.RWMutex),
    }
}

//后插元素
func (List *SingleList) LastAppend(node *SingleNode) bool {
    if node == nil {
        return false
    }

    List.mutex.Lock()

    defer List.mutex.Unlock()

    if List.Size == 0 {
        List.Head = node
        List.Tail = node
        List.Size = 1
        return true
    }

    tail := List.Tail
    tail.Next = node
    List.Tail = node
    List.Size += 1

    return true
}

//删除链表节点
func (List *SingleList) DeleteNode(client_id string) bool {
    if List.Size == 0 {
        return false
    }
    List.mutex.Lock()
    defer List.mutex.Unlock()
    
    var prev *SingleNode = nil
    current := List.Head
    for current != nil {
        conn, ok := current.Data.(ChatWebSocketConn)
        if ok && conn.client_id == client_id {
            if prev == nil {
                List.Head = current.Next
            } else {
                prev.Next = current.Next
            }
            List.Size--
            if List.Size == 0 {
                List.Tail = nil
            }
            return true
        }
        prev = current
        current = current.Next
    }
    return false
}

//链表使用
    //建立账号和连接的绑定关系,并作为链表的一个节点
    item := ChatWebSocketConn{
        user_conn       : tools.WebSocketConnMapOnce.ConnMap[client_id],
        client_id          :   *client_id,
        user_type       : (*user_info).Flag,
        user_id         : (*user_info).Id,
        user_nickname   : (*user_info).NickName,
    }

    linked_node := tools.SingleNode{Data:item}
    linked_list.LastAppend(&linked_node)

//ChatWebSocketConn定义
type ChatWebSocketConn struct{
    user_conn       *tools.WebSocketConn            //已建立的客户端连接,lu_guild_account_list表id
    client_id       string                          //生成的唯一id,标识一个客户端
    user_type       int                             //用户类型,1:会员 2:主播
    user_id         int64                           //用户id
    user_nickname   string                          //用户昵称
}


我在实现单链表的删除节点功能,函数定义DeleteNode,添加节点是通过LastAppend将ChatWebSocketConn做为一个Node节点添加进去的,删除的时候需要遍历该节点存储的client_id并进行比对,但感觉对链表的删除仍有侵入,能否在DeleteNode定义个回调函数,通过回调函数进行对比?
  • 写回答

2条回答 默认 最新

  • 阿里嘎多学长 2025-10-18 17:06
    关注

    阿里嘎多学长整理AIGC生成,因移动端显示问题导致当前答案未能完全显示,请使用PC端查看更加详细的解答过程

    解决方案

    删除链表节点不侵入的关键是找到要删除的节点的前一个节点,然后将前一个节点的 Next 指针指向要删除的节点的下一个节点。

    代码示例

    func deleteNode(head *SingleNode, data interface{}) *SingleNode {
        // 找到要删除的节点
        node := head
        for node != nil && node.Data != data {
            node = node.Next
        }
        
        // 如果找到了要删除的节点
        if node != nil {
            // 如果要删除的节点是头节点
            if node == head {
                head = node.Next
            } else {
                // 找到要删除的节点的前一个节点
                prev := head
                for prev.Next != node {
                    prev = prev.Next
                }
                // 将前一个节点的 Next 指针指向要删除的节点的下一个节点
                prev.Next = node.Next
            }
        }
        
        return head
    }
    

    注意

    • 这个函数会返回链表的新头节点,如果链表中没有找到要删除的节点,则返回原来的链表头节点。
    • 如果链表中有多个节点的值相同,这个函数会删除第一个遇到的节点。
    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 10月18日
  • 创建了问题 10月18日