简体   繁体   English

C ++链接列表遗留代码到STL —动态分配链接列表大小

[英]C++ linked-list legacy code to STL — allocating linked list size on the fly

I am working on some legacy code that defines a linked list (not using STL container) 我正在处理一些定义链表的旧代码(不使用STL容器)

I want to convert this code so as to use STL list. 我想转换此代码以便使用STL列表。 As you can see in the following example, the linked list is assigned an initial value for all Ns. 在下面的示例中可以看到,链表为所有N分配了初始值。 Then certain elements in the list are assigned some value. 然后,列表中的某些元素被分配了一些值。 Then the "empty elements" in the list are "cleaned up". 然后,列表中的“空元素”被“清理”。

I am looking for a better way to do this using STL. 我正在寻找使用STL的更好方法。 especially, can this deleting empty elements code be avoided? 特别是,可以避免这种删除空元素的代码吗? I checked STL documentation.. it defines a remove method but thats not exactly what I need here. 我检查了STL文档..它定义了一个remove方法,但这并不是我所需要的。 Is there a way to dynamically allocate linked list size? 有没有办法动态分配链表的大小? I would appreciate your suggestions! 非常感谢您的建议!

Update I have modified the code. 更新我已经修改了代码。 this resembles the main code I have. 这类似于我的主要代码。 But to avoid any confusion, I am writing a pseudo code below to explain how it works. 但是为了避免混淆,我在下面编写了一个伪代码来说明其工作原理。

Steps 脚步

  1. Allocate a size elementIds to the linked list ( struct my_list ) 向链接列表分配大小elementIdsstruct my_list
  2. There is another linked list meshElem and I am interested in some values from meshElem->elem struct. 还有另一个链接列表meshElem ,我对meshElem->elem结构中的某些值感兴趣。
    • For Example : I need elemId = meshElem->elem->id; 例如:我需要elemId = meshElem->elem->id; This elemId is in range 0 to elementIds . elemId0 to elementIds范围内。
    • The elemId will be used as an index to look for a particular element in struct my_list lst eg lst[elemId] elemId将用作索引,以在struct my_list lst查找特定元素,例如lst[elemId]
  3. In the doSomething () function, loop through 0 to elementIds . doSomething ()函数中,将0 to elementIds循环0 to elementIds In this loop, if certain conditions are satisfied, the lst->number is assigned an integer value = someArray[i] where i is in range 0 to N (done in appendElement ) 在此循环中,如果满足某些条件, lst->number分配一个整数值= someArray[i] ,其中i的范围为0 to N (在appendElement完成)
  4. the elements without next entry in struct my_list lst ,are cleaned up ( Question: can this be avoided ? ) 清理了struct my_list lst没有next条目的元素(问题:可以避免吗?)
  5. lst->number value is used further in the code for some other processing. lst-> number值在代码中进一步用于其他处理。

Now the modified code: 现在修改代码:

struct my_list
 {
  int  number;
  struct my_list *prev;
  struct my_list *next;
 }

void doSomething(void){
     const int N = 50000;
     const int elementIds = 10000;
     int i, elemId, node_i;     
     struct my_list *lst;     
     lst = new struct my_list[elementIds];
     int someArray[12];

     meshElem = mesh->next;     

     for(i=0; i<=elementIds; i++) {
        lst[i].num = 0;
        lst[i].next   = NIL;
        lst[i].prev  = NIL;
      }      

    while(meshElem != NIL){
        // Element id (int) 
        // Note that any elemId will be in range [0 - elemId ]
        elemId = meshElem->elem->id;

        // Do some operations to populate "lst"    
        // Note that 'lst' gets values ONLY for certain 
        // values of i
        for (i = 0; i<=N; i++){        
            // if certain conditions are satisfied, 
            // it updates the  linked list element 
            // lst[meshIdx]. foo1(), foo2() are just some conditions...

            if (foo1()){
               appendElement(someArray[i], &lst[meshIdx])
               }
            else if (foo2()){
               appendElement(someArray[i], &lst[meshIdx])           
            }
        }          

      meshElem = meshelem->next;

  } // End of while(meshElem != NIL)

  // Clean up the linked list lst 
  // by removing unassigned items. 

   struct my_list *lst_2

   for(i=1; i<=N; i++) {
     lst_2 = &lst[i];
     while( lst != NIL ) {      
      if( lst->next != NIL && lst->next->number == 0 ) {
        delete lst_2->next;
        lst_2->next = NIL;
      } // end of if loop
      lst = lst_2->next;

    } // end of while while( lst != NIL )

  } // End of for(i=1; i<=N; i++)


  //  Do some more stuff that uses struct my_list lst
  for(i=1;i<=elementIds;i++) {

      while( lst[i] != NIL && (node_i = lst[i]->number) ) {
            if( node_i == 0) {
              lst[i] = lst[i]->next; 
              continue;
            }
            // Use this "node_i" index in some other arrays to
            // do more stuff. 
            //..
            //..
            //..
            lst[i] = lst[i]->next;    
      }

}


void appendElement(int n, struct my_list *lst) {
  int exists = 0;
  while( lst->next != NIL ) {
    if( lst->number == n ) {
    exists = 1;
    lst=lst->next;
  }
  if( exists < 1 ) {
    lst->number = n2;
    insertElemAfter(lst, 0);
  }
}

Your legacy linked list is essentially a threaded sparse vector. 您的旧链表本质上是一个线程稀疏向量。 The array with NULLs is the sparse vector, and the linked list provides the threading. 带有NULL的数组是稀疏向量,而链接列表提供了线程。 The two combined give constant access to individual nodes (random access into the array) and efficient traversal over "valid" nodes (avoiding NULLs). 两者相结合,可以对单个节点进行恒定访问(对阵列的随机访问),并且可以对“有效”节点进行有效遍历(避免使用NULL)。

Assuming both of these aspects are important, and assuming the Data maybe more complex than the simple int you show, then you could create a data structure such as: 假设这两个方面都很重要,并假设数据可能比显示的简单int更为复杂,则可以创建一个数据结构,例如:

class ThreadedSparseVector {
private:
    std::vector<Data*> m_thread;
    std::vector<int> m_sparse_vector;
};

During initialization, you can pre-size m_sparse_vector and initialize the values to -1. 在初始化期间,您可以预设置m_sparse_vector的大小并将其初始化为-1。 As you append elements (or access them), check if it is already "valid" first, adding it to the thread if not: 在追加元素(或访问它们)时,首先检查它是否已经“有效”,如果不是,则将其添加到线程中:

void ThreadedSparseVector::appendElement(int i) {
    if (-1 == m_sparse_vector[i]) {
        // Add new data
        m_sparse_vector[i] = m_thread.size()
        m_thread.push_back(new Data(i));
    }

    Data* data = m_thread[m_sparse_vector[i]];
    // Initialize/update data as necessary
}

If the threading is more important than random access, another option is to simply use an STL map. 如果线程比随机访问更重要,则另一个选择是简单地使用STL映射。 If random access is more important than threading, then you can simply use an STL vector and tolerate NULLs during iteration (or create a custom iterator that automatically skips NULLs). 如果随机访问比线程更重要,那么您可以简单地使用STL向量并在迭代过程中容忍NULL(或创建一个自定义迭代器,以自动跳过NULL)。

Another alternative, depending on your motivation to convert to STL, is to create a wrapper around the legacy code that implements an STL-compatible interface, as opposed to converting the data structure itself to use STL. 根据您转换为STL的动机,另一种选择是围绕实现STL兼容接口的旧代码创建包装器,而不是将数据结构本身转换为使用STL。

A linked list typically do not use contiguous memory, but rather fragmented heap-allocated nodes. 链表通常不使用连续内存,而是使用零散的堆分配节点。 I guess if you provide the std::list constructor with an initial count, at least that many nodes will be contiguous. 我想如果您为std::list构造函数提供初始计数,至少有许多节点是连续的。 Other than that, you'd need to write your own allocator to go with std::list . 除此之外,您还需要编写自己的分配器以与std::list一起使用。

struct my_list {
    int number;
}

void doSomething(void){
    std::list<my_list> lst;
    const int N = 10000;        
    for (int i = 0; i<=N; ++i) {        
        if (1 == foo(N)) { //I'm guessing this is what you meant
            my_list new_element; //Initalize with something;
            lst.push_back(new_element);
        }
    }
}

int
foo(int n) {
    // some function that returns 0 or 1 based on 
    // the value of n
    return 1;
}
std::list<int> lst;

In your logic instead of creating all the nodes in the beginning why dont you run the loop only once and create one elements dynamically for true condition and add it in the list. 用您的逻辑而不是一开始就创建所有节点,为什么不只运行一次循环并为真实条件动态创建一个元素并将其添加到列表中。

for (i = 0; i<=N; i++)
{
    if ( i == foo(N) )
        node = createNode();
    appendElement(node);
}

I think you just want: 我想您只想要:

std::list<int> lst;

for (i = 0; i<=N; i++){        
    if ( i == foo(N) )
    lst.push_back(/*some new value*/);
}  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM