没有自我参照结构的帮助,是否有可能建立一个链表?

时间:2015-06-16 03:47:40

标签: c data-structures singly-linked-list

是否可以在没有自引用结构的帮助下构建链表?即像这样只使用指针:

struct list{
    int data;
    int *nxt;
};

而不是

struct list{
    int data;
    struct list *nxt;
};

4 个答案:

答案 0 :(得分:2)

是的,这是可能的。

你提出的是type punning,你可能会在大多数平台上使用大多数编译器来解决这个问题,但是没有一个很好的理由可以在第一个地方和很多很好的理由不去。

答案 1 :(得分:0)

您可以查看如何在Linux内核中实现链接列表。

与传统链接列表相比:

struct my_list{
    void *myitem;
    struct my_list *next;
    struct my_list *prev;
};

使用linux内核中的链表如下:

struct my_cool_list{
    struct list_head list; /* kernel's list structure */
    int my_cool_data;
};

Source

答案 2 :(得分:0)

不确定。您可以使用void *代替struct list *作为nxt成员。例如:

struct list {
    int data;
    void *nxt;
};

或者,如果您准备建立一个保证列表的节点将存储到一个数组(这对缓存局部性和插入速度很好),您可以使用size_t。< / p>

struct list {
     int data;
     size_t nxt;
};

如果您的实施提供uintptr_t(来自<stdint.h>),您可以将这两种类型合并为一种:

struct list {
    int data;
    uintptr_t nxt;
};

答案 3 :(得分:-1)

另一种方法是使用并行数组作为“堆” 1 ,其中一个数组包含数据(无论是标量还是结构),另一个数组存储下一个“节点”的索引在列表中,如:

int data[N];
int next[N];

你需要两个“指针” - 一个指向列表中的第一个元素,另一个指向“堆”中第一个可用的“节点”。

int head;
int free;

您将初始化“next”数组中的所有元素以“指向”下一个元素,但最后一个指向“null”的元素除外:

for ( int i = 1; i < N-1; i++ )
  next[i-1] = i;
next[N-1] = -1;
free = 0;  // first available "node" in the heap
head = -1; // list is empty, head is "null" 

在列表中插入新元素看起来像这样(假设有序列表):

if ( free != -1 )
{
  int idx = free;    // get next available "node" index;
  free = next[free]; // update the free pointer 
  data[idx] = newValue;
  next[idx] = -1;

  if ( head == -1 )
  {
    head = idx;
  }
  else if ( data[idx] < data[head] )
  {
    next[idx] = head;
    head = idx;
  }
  else
  {
    int cur = head;    
    while ( next[cur] != -1 && data[idx] >= data[next[cur]] )
      cur = next[cur];
    next[idx] = next[cur];
    next[cur] = idx;
  }
}

删除idx处的元素非常简单:

int cur = head;
while ( next[cur] != idx && next[cur] != -1 )
  cur = next[cur];

if ( next[cur] == idx )
{
  next[cur] = next[idx];  // point to the element following idx
  next[idx] = free;       // add idx to the head of the free list
  free = idx;             
}

这种方法的优点:

  1. 没有动态内存管理;
  2. 没有自我参照结构;
  3. 数据项连续存储在内存中,这可能会带来更好的缓存性能。
  4. 缺点:

    1. 在这种简单的方法中,列表大小是固定的;
    2. 任何有用的大型数组都必须声明为static,这意味着您的二进制文件可能占用空间很大;
    3. 使用-1作为“null”的约定意味着您必须为索引使用带符号的类型,这会减少给定数组类型的可用元素数。
    4. 您当然可以将0用作“null”并计算1的所有索引;这允许您使用诸如size_t之类的无符号类型作为索引,这意味着您可以使阵列与系统允许的一样大。只是0是一个有效的数组索引而-1(通常)不是,这就是我为此示例选择它的原因。

      <小时/> 1。欢迎来到我的数据结构课程,ca。 1987年,使用Fortran 77进行了教学。并行数组几乎是所有内容的答案(列表,树,队列等)