为什么我无法在链表中输入元素,而函数正在运行?

Why am I unable to enter elements in the linked list while the function is working otherwise?

我写了一个程序将两个排序的链表合并为一个,这个函数是我用来做的,但它不起作用。该函数的代码如下:

void combine(Node **temp, Node *temp_1, Node *temp_2){
   while(temp_1 != NULL || temp_2 != NULL){
      if(temp_1->data > temp_2->data){
         push(temp, temp_2->data);
         temp_2 = temp_2->next;
      }
      else{
         push(temp, temp_1->data);
         temp_1 = temp_1->next;
      }
   }
   while(temp_1 != NULL){
      push(temp, temp_1->data);
      temp_1 = temp_1->next;
   }
   while(temp_2 != NULL){
      push(temp, temp_2->data);
      temp_2 = temp_2->next;
   }
}

现在,此代码不会向最终链表添加任何内容。如果我写类似

push(temp, temp_1->data);

它会很好地添加元素,所以问题肯定不在于推送功能。有人能告诉我上面的代码有什么问题吗?

完整代码如下URL: https://ide.geeksforgeeks.org/FZ8IS4PADE

问题是 while 条件:

while(temp_1 != NULL || temp_2 != NULL){

这将允许在这两个指针中只有 一个 为空时执行循环体,这将导致循环体中第一条语句出现未定义的行为:

    if(temp_1->data > temp_2->data){

|| 应该是 &&。这将解决您的问题。

关于您的代码的其他说明

  • 不要使用 NULL 来比较你的指针变量,但是 nullptr

  • 使用 push 会使您的代码效率低下:在每次推送时,您的代码都会开始遍历整个列表以找到它的结尾。由于您实际上知道最后一个节点是什么(因为它是在循环的前一次迭代中创建的),这是在浪费时间。相反,保留对正在创建的列表的 tail 的引用。由于在 combine 进程开始时没有尾部,因此创建一个位于将返回的真实列表之前的“哨兵”节点可能很有用。

  • 使用更好的变量名。 temp 根本不是临时的。是调用者想要得到的结果:这个名字有误导性。

  • 避免代码重复。除了从中复制的列表外,最后两个循环是相同的,并且此代码再次类似于主循环中的部分。因此,创建一个函数来执行将节点从源列表复制到另一个列表末尾的工作,并使两个指针都前进。

这是它的样子:

void copyNode(Node **source, Node **targetTail) {
   *targetTail = (*targetTail)->next = new Node((*source)->data);
   *source = (*source)->next;
}

void combine(Node **result, Node *head_1, Node *head_2){
   Node *sentinel = new Node(0); // Dummy 
   Node *current = sentinel;
   while(head_1 != nullptr && head_2 != nullptr){
      if(head_1->data > head_2->data){
         copyNode(&head_2, &current);
      }
      else{
         copyNode(&head_1, &current);
      }
   }
   if (head_1 == nullptr) {
      head_1 = head_2;
   }
   while (head_1 != NULL) {
      copyNode(&head_1, &current);
   }
   *result = sentinel->next;
   delete sentinel; 
}