简体   繁体   English

插入到排序位置的链表

[英]insert to sorted position linked list

I have question quite much related to this one I asked a while ago 我有一个问题与我刚才问过的问题有关

place a value in the sorted position immediately 立即在排序位置放置一个值

I wonder if you can use the same approach in that you step backward in a linked list to find the position it should be inserted into. 我想知道您是否可以使用相同的方法,即在链接列表中向后退一步以查找应插入的位置。

If it is possible how do you loop a linked list backward? 如果有可能,如何将链表向后循环? I can't figure it out because it seems not possible since it should be a double linked listed then if I'm not wrong? 我无法弄清楚,因为似乎不可能,因为它应该是列出的双重链接,那么如果我没记错的话? Anyway I'm working with singly linked list. 无论如何,我正在使用单链表。

EDIT 编辑

I think I'm going for the look forward approach, this is what I made so far. 我想我正在寻找一种前瞻性的方法,这就是我到目前为止所做的。 I'm stuck at that point in how I should save the previous (key, value). 在这一点上,我被困在如何保存上一个(键,值)的位置上。 Here's the code so far of what's done. 到目前为止,这是完成的代码。 The for-loop is used to look for the position I want to insert to. for循环用于查找要插入的位置。 And I have peek forward, which will break in case it reach the end. 我向前看,万一到达终点,它将打破。

OK so far, now I want to insert the value to the correct position. 到目前为止,还可以,现在我想将值插入正确的位置。 It is here I'm stuck. 在这里我被卡住了。 How should it be done? 应该怎么做? Now when I insert keys: 2, 1, 0, 3 , it will only print out 1, 3 现在,当我插入钥匙: 2, 1, 0, 3 ,只会打印出1, 3

struct my_list
{
  /* a pointer to the first element of the list */
  struct list_link* first;
};

struct list_link
{
   int key;                // identifies the data
   double value;           // the data stored
   struct list_link* next; // a pointer to the next data
};

struct list_link* create(int key, double value, struct list_link* next)
{
   // creates the node;
   struct list_link * new_link;
   new_link = new struct list_link;

   // add values to the node;
   new_link->key = key;
   new_link->value = value;
   new_link->next = next;

   return new_link; // Replace this, it is just to be able to compile this file
}

void list_insert(struct my_list* my_this, int key, double value)
{
   if(my_this->first == NULL)   // add if list empty
      my_this->first = create(key, value, my_this->first);   
   else
   {      
      struct my_list* curr;
      struct my_list* prev;         
      struct my_list start;

      start.first = my_this->first;
      curr = my_this;

      cout << "Too be appended: ";
      cout << key << " " << value << endl;
      for(curr->first = my_this->first; 
          key > curr->first->key; 
          curr->first = curr->first->next)
      {
         if(curr->first->next == NULL) //peek at front if empty
            break;
      }
      cout << "append here " << key << " > " << 
          curr->first->key << endl << endl;
      //perform some surgery
      if(curr->first->next == NULL)
      {     
         curr->first->next = create(key, value, my_this->first->next);
      }
      else
      {       
         curr->first = start.first; //move back to start of list
         my_this->first = create(key, value, my_this->first);
      }      
   }  
}

You can't traverse a singly-linked list backward, but you can keep a pointer to the last two elements you have seen instead of just one. 您不能向后遍历单链接列表,但是可以保持指向您看到的最后两个元素的指针,而不仅仅是一个。

So, traverse the list from the front, and keep two pointers: current, and previous. 因此,从头开始遍历列表,并保留两个指针:当前指针和前一个指针。 If the element you are inserting is less than current, then update previous to point to it. 如果您要插入的元素小于当前元素,则更新之前的内容以指向它。

没有一个单链列表不能向后移动。

Here's my understanding of what you're asking: when you search for an insert position in a singly linked list you find it by discovering that you've gone one node too far, then, how to go back? 这就是我对您要问的问题的理解:当您在单链列表中搜索插入位置时,通过发现您离一个节点太远而找到了该位置,然后如何返回?

Well, there are two main solutions: 好吧,有两个主要解决方案:

  • peek one node ahead while searching (a different viewpoint of the same idea is to keep a "trailing" pointer), or 在搜索时偷看一个节点(相同想法的不同观点是保持“尾随”指针),或者

  • make sure that there's an artifical tail-node (so that you always have a real next node), and that there are no other "external" pointers into the list than your search pointer. 确保有一个人为的尾节点(这样,您始终会有一个真正的下一个节点),并且除了搜索指针外,列表中没有其他“外部”指针。 Insert your new node after the node with higher value. 在值较高的节点之后插入新节点。 Swap the contents of the two nodes. 交换两个节点的内容。

The second solution is a little brittle because of the assumption of no other "external" pointers into the list. 第二种解决方案有些脆弱,因为假定列表中没有其他“外部”指针。 But it's sort of ingenious. 但这有点巧妙。 I learned it from Donald Knuth's "The Art of Computer Programming". 我是从Donald Knuth的“计算机编程艺术”中学到的。

Alternatively to these singly linked list solutions, you can just double-link your list. 除了这些单链列表解决方案之外,您还可以双链列表。

Cheers & hth., 干杯,……

You can use recursion to traverse a singly linked list backwards. 您可以使用递归向后遍历单个链接列表。

void traverse_backwards(NODE node)
{
    if (node->next != null && !node->is_marked)
    {
        node->is_marked = 1;
        traverse_backwards(node->next);
    }
    else
    {
        // logic goes here
    }
}

Its easier to take an example 举个例子比较容易

10 -> 20 -> 30 -> NULL

Traverse the list with two pointers: (i) currentNode and (ii) nextNode . 用两个指针遍历列表:(i) currentNode和(ii) nextNode

Start with currentNode = NULL and nextNode = <10> . currentNode = NULLnextNode = <10> Move both of them forward in a loop as long as nextNode->key < insertkey is true. 只要nextNode->key < insertkey为true,则将它们向前循环移动。

Upon exit from loop (example: for insertKey == 25, currentNode = <20>, nextNode = <30> ): 从循环退出时(例如:对于insertKey == 25, currentNode = <20>, nextNode = <30> ):

  1. create newNode with newNode->key = insertKey and newNode->value = insertValue 使用newNode->key = insertKeynewNode->value = insertValue创建newNode

  2. "Insert" newNode between currentNode and nextNode by doing 通过执行以下操作在currentNodenextNode之间“插入” newNode

    2.1 currentNode->next = newNode 2.1 currentNode->next = newNode

    2.2 newNode->next = nextNode 2.2 newNode->next = nextNode

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

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