链表中元素比较功能的实现

Posted

技术标签:

【中文标题】链表中元素比较功能的实现【英文标题】:Implementation of element compare function in linked list 【发布时间】:2021-11-27 21:10:45 【问题描述】:

我正在尝试实现一个作为链表结构一部分的函数,但由于某种原因,我的测试中不断出现分段错误。我不确定故障是由我在列表结构中的 compare 定义引起的,还是我在 linked_list_create 函数中实现它的方式。我已经使用 GDB 调试代码很长一段时间了。我可以看到的一件事是测试中的 current_entry 不包含任何值,但我不知道这会如何导致此问题。

//structs

union elem

  int key;
  char *value;
  void *extra;
;

typedef union elem elem_t;


#define int_elem(x) (elem_t)  .key=(x) 
#define val_elem(x) (elem_t)  .value=(x) 
#define ptr_elem(x) (elem_t)  .extra=(x) 

typedef struct link link_t;

typedef struct list list_t;

/// Compares two elements and returns true if they are equal 
typedef bool(*eq_function)(elem_t a, elem_t b);


struct link 

  elem_t element; //data    
  link_t *next; //link
;

struct list

    link_t *first;
    link_t *last;
    eq_function compare;
;

//Function

list_t *linked_list_create(eq_function compare)

  list_t *result = calloc(1, sizeof(list_t)); // allocated memory for list
  if (result)
  
    result->first = result->last = calloc(1, sizeof(struct link));
    result->compare = compare; 
  
  return result;


bool linked_list_contains(list_t *list, elem_t element)

  for (link_t *cursor = list->first->next; cursor; cursor = cursor->next)
    
      if (list->compare(cursor->element, element) == 0) 
      
        return true;
      ;
    

  return false;


void linked_list_append(list_t *list, const elem_t element)

  list->last->next = link_create(element, NULL);
  list->last = list->last->next;

///inserts a link in the list dependent on link index
void linked_list_prepend(list_t *list, const elem_t element)

  linked_list_insert(list, 0, element);


elem_t linked_list_remove(list_t *list, const int index)

  link_t *tmp = list->first; //tmp acts as a cursor

  for (int i = 0; i < (index-1); i++) 
  
    tmp = tmp->next; //at end of loop tmp is the link we wish to remove
  ;

  link_t *to_remove = tmp->next;
  elem_t returnval = to_remove->element;
  link_destroy(to_remove); //destroys the link
  return returnval;



///inserts a link in a list given an index
void linked_list_insert(list_t *list, const int index, const elem_t value)

  link_t *previous = list->first; //first link in list

  for (int i = 0; i < (index-1); i++)
  
    previous = previous->next; 
  ;

  previous->next = link_create(value, previous->next); //inserts created link


//Test

void test_remove1()

   list_t *list = linked_list_create(NULL);
    elem_t valtest = int_elem(7);
   for (int i = 0; i < 8; i++)
    
     linked_list_append(list, int_elem(0));
    ;
   linked_list_insert(list, 5, valtest);
   linked_list_remove(list, 5);
   bool result = linked_list_contains(list, valtest);
   CU_ASSERT_FALSE(result);
   linked_list_destroy(list);

测试在 CUnit 中,由于linked_list_contains 第 95 行的分段错误而未完成。

【问题讨论】:

这些宏 #define int_elem(x) (elem_t) .key=(x) #define val_elem(x) (elem_t) .value=(x) #define ptr_elem(x) (elem_t) .extra=(x) 只会使您的代码不可读。 "我已经使用 GDB 坐了很长时间了"。好的。所以告诉我们你发现了什么。调试器至少会为您提供触发 seg 错误的确切代码行。所以把它放到你的帖子里。 @davdavdav2 这个语句结果->first = result->last = calloc(1, sizeof(struct link));在函数linked_list_create 中也没有任何意义。 @VladfromMoscow 怎么样?它至少使测试更容易,它们只需返回元素的 int、ptr 或 val。 linked_list_create(false); 您正在将compare 函数设置为false。但是false 不是函数。你希望它如何工作?为什么当它使用布尔值作为函数时它会崩溃? 【参考方案1】:

linked_list_create(false)compare 函数设置为false。但是false 不是一个函数,所以它在尝试调用compare 函数时会崩溃也就不足为奇了。

typedef bool(*eq_function)(elem_t a, elem_t b);

这是compare 函数的函数原型。这意味着它是一个接受两个elem_t 参数并返回一个bool 的函数。所以你需要定义一个该类型的函数并相应地设置列表。

例如:

bool my_eq_function (elem_t a, elem_t b)

    // Implement real compare logic here
    return false;

然后设置它:

linked_list_create(my_eq_function);

【讨论】:

以上是关于链表中元素比较功能的实现的主要内容,如果未能解决你的问题,请参考以下文章

双向链表的实现

C中线性表和链表的区别

java算法--链表

已知两个长度为m和n的升序链表,将他们合并为长度为m+n的降序链表,最坏情况下时间复杂度怎样求

<数据结构> 链表 - 链表的概念及结构

删除链表中重复的元素