【问题标题】:How to compare linked list nodes?如何比较链表节点?
【发布时间】:2013-08-03 06:55:19
【问题描述】:

GLib 库这样做是为了比较两个单链表节点:

 typedef struct _GSList {
  _GSList *link;
   void *data;
} GSList;

    int g_sListPosition(GSList *list, GSList *llink) {
        int cnt = 0;
        while(list) {
            if(list == llink)  // Note here
                return cnt;
            cnt++;
            list = list->link;
        }

        return -1;
    }

但是当我像这样比较节点时。它返回 false:

int main(void) {
    GSList *list = NULL, *list2 = NULL;
    list2 = g_sListAppend(list2, "def");
    list = g_sListAppend(list, "abc");
    list = g_sListAppend(list, "def");
    list = g_sListAppend(list, "ghi");
    printf("%d", g_sListPosition(list, list2));   // Return -1 ?
}

那么,这里比较的是什么(在DOC中,它是这样写的获取GSList中给定元素的位置),一个节点还是列表中包含的数据?

编辑:感谢所有给出的,我的错误我实际上是以错误的方式做的。我必须比较列表的相同实例。

【问题讨论】:

    标签: c linked-list


    【解决方案1】:

    因为listllink 是节点地址,我们不能有两个不同的节点具有相同的地址,它非常简单的技术可以找到llinklist(first) 中的起始位置。

    假设list 传递给函数是这样的:

      //     0     1    2   3    4   
    list---->[]-->[]-->[]-->[]-->[]---null
             23   42   18  102  324      
    
    addresses are assumption 
    

    如果llink 的值为18,则函数返回2,因为llinklist 中的第三个节点。

    如果未找到llink,则返回-1

    (如数组索引以0 开头的函数计数来自0 的列表中的节点)

    正如你评论的那样,我正在评论代码:

        int cnt = 0;  // initial value of node_count is 0
        while(list) { // search while list not NULL (till end)
            if(list == llink) // if `llink` is a node in `list`
                return cnt;   // return node number  
            cnt++;   // else it may be next node
            list = list->link;
        }
        // control comes here if list == NULL, means llink not found
    
        return -1;  // not found so return -1
                    // negative number can't be a position 
    

    评论:

    我的意思是,如果它真的给出正值,如何测试它

    如下调用你的函数:

     g_sListPosition(list, list->link->link->link);
    //                            0      1    2
    

    它将返回2

    但请注意,您的列表应该由 3 节点组成。

    【讨论】:

    • 那么,为什么它在比较两个链接时返回-1
    • @ashish2expert 我解释的例子你明白了吗?你需要 -1 的例子吗?
    • 不,正如我在上面尝试的那样,但它没有返回正值。我的意思是举一个像上面这样的例子。你给它什么我知道,但我该如何测试呢?
    • 我的意思是,如果它真的给出了积极的价值,如何测试它
    • @ashish2expert give llink value = list wait 中的某个节点地址
    【解决方案2】:

    头部为list2的列表

    +--------+
    |  def   |--->X
    +--------+
       arr1
    

    当函数分配节点时,它将分配一个具有节点大小的空闲内存位置,然后在节点的数据部分(它必须分配字符串)中分配字符串。

    头部为list的列表

    +--------+    +--------+    +--------+
    |   abc  |--->|   def  |--->|  ghi   |--->X
    +--------+    +--------+    +--------+
       addr2         addr3         addr4
    

    这里每次将字符串附加到链表时,都会分配一个新节点,并将字符串复制到数据部分。请注意,每次分配一个新节点时,该节点的地址都是不同的。

    在上面的例子中,第一个数据为“def”的列表的地址为addr1,第二个列表的数据为“def”的节点的地址为addr3。所以如果你尝试用==操作符比较这两个节点,自然比较的结果会是假的,因为相等会比较节点的地址,它们是不同的,因此返回false。

    如果您想特别匹配节点中的数据,则需要对其进行具体比较。即访问list中的每个节点,并将数据部分与另一个节点(list1)进行比较。

    另一方面,如果你已经确定了特定链表中的节点地址,那么你可以使用地址进行比较。例如,如果您遍历列表直到最后并获得最后一个带有“ghi”的节点的地址,地址为addr4,那么您可以稍后使用此地址比较列表中的特定节点,前提是该节点尚未释放并使用相同的数据重新创建。在这种情况下,您可以清楚地看到即使此节点内的数据发生更改,地址也将保持不变。

    【讨论】:

      【解决方案3】:

      我发现,我们实际上必须给出相同的列表实例。下面是一个例子:

      int main(void) {
          RSList *list = NULL;
          list = r_sListAppend(list, "abc");
          list = r_sListAppend(list, "def");
          list = r_sListAppend(list, "ghi");
      
          RSList *list2 = list;
          int i = 2;
          while(i--) {
              list2 = list2->link;
          }
          printf("%d", r_sListIndexOf(list, list2));  // Print 2
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多