【问题标题】:How can I insert linked list nodes in numerical order?如何按数字顺序插入链表节点?
【发布时间】:2020-02-07 09:40:43
【问题描述】:

我已经非常接近完成这个学校的链接列表作业,但我正在努力完成最后一个功能。这个函数的目的是把已经从文本文件中读入的数字按数字顺序放入链表中。我试图让它遍历列表,只要值大于前一个数字但达到分段错误,就会添加节点。我已经被困在这个问题上很长一段时间了,我会感谢任何人的帮助。以下是我正在使用的文件以及一个名为 insertStrategic 的函数的可怕混乱,该函数应该按数字顺序获取列表。

主要

#include "linkedlist.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>


using namespace std;

int main (){

    NodePtr newNode = NULL;

    // after you implemented your functions in .cpp file 
    // - use the code below for testing your linked list. 
    // Demonstrate that ALL functions are working correctly.

    // After that add code for reading data from input file.
    // Every time you read an integer, create a node and insert it
    // in the ascending order into the list.

    int num;

    FILE *fptr;

    // make sure file exists, give message and exit otherwise
        if ((fptr = fopen("input.txt","r")) == NULL){
            printf("Error! opening file");
            exit(1);
        }

    // while we still have items to read
        while( fscanf(fptr,"%d", &num) != EOF){
            newNode = makeNewNode(num);
            insertStrategic(newNode);
    }

    fclose(fptr);  // close the file  

    // At the end print the entire list to show that your code 
    // functions correctly.



    printList();

    cout << "After DeleteFromFront: " << endl; 
    deleteFromFront();
    printList();

    NodePtr seven = makeNewNode(7);     
    insertAtEnd(seven);
    cout <<"Inserting seven at END" << endl;
    printList();

    NodePtr eight = makeNewNode(8);     
    insertAtEnd(eight);
    cout <<"Inserting eight at END" << endl;
    printList();

    cout << "After deleting eight: " << endl; 
    deleteFromEnd();
    printList();

    cout << "After deleting seven:" << endl;
    deleteFromEnd();
    printList();



  return 0;
}

链接列表文件

#include "linkedlist.h"
#include <stdlib.h>
#include <iostream>


using namespace std;

   NodePtr head = NULL;
   NodePtr tail = NULL;


bool isEmpty(){
   return (head == NULL);
}

NodePtr makeNewNode(int number){
   NodePtr newNode = (NodePtr) malloc(sizeof(Node));
   if(newNode != NULL){
      newNode->data = number;
      newNode->next = NULL;
   }
   return newNode;
}

void insertAtFront(const NodePtr newPtr){
    if (isEmpty()){
        head = newPtr;
        tail = newPtr;
   }
   else{ // not empty
        newPtr->next = head;
        head = newPtr;
   }

}

void insertAtEnd(const NodePtr newPtr){

    NodePtr end = head;
    newPtr->next = NULL;

        while (end->next != NULL){
            end = end->next; 
        }

        end->next = newPtr; 
}



void insertStrategic(const NodePtr newPtr){

        if (isEmpty()){
            head = newPtr;
            tail = newPtr;
        }
        else {
            NodePtr traverse = head;
            newPtr->next = NULL;

                while ((traverse->next = NULL)){
                    while ((traverse->data < newPtr->data)){
                        traverse = traverse->next;
                    }
                    traverse = traverse->prev;
                    traverse->next = newPtr;
                    break;
                }
        } 
}   

void deleteFromFront( ){

    NodePtr temp = head;
    head = head->next;

}

void deleteFromEnd( ){

    NodePtr temp = head;
    NodePtr secTemp;

        while(temp->next != NULL) {
            secTemp = temp;
            temp = temp->next;
        }

        free(secTemp->next);
        secTemp->next = NULL;  
}



void printList( ){
   if (isEmpty()){
     cout << "List is empty" << endl;
   }
   else {
     NodePtr temp = head;
     while (temp != NULL){
       cout << " The data is: " << temp->data << endl;
       temp = temp->next;
     }
   }
}

头文件

#ifndef MYLIST_H
#define MYLIST_H

#include <cstddef>

   struct listNode {
        int data;
        struct listNode* prev;
        struct listNode* next;
   };

   typedef struct listNode Node;
   typedef Node* NodePtr;


   static int nodeCount = 0;

   bool isEmpty();
   NodePtr makeNewNode(int); 

   void insertAtFront(const NodePtr);
   void insertAtEnd(const NodePtr);
   void insertStrategic(const NodePtr);

   void deleteFromFront( );
   void deleteFromEnd( );

   void printList();


#endif

要读入的文本文件

3
5
11
2
7
1
65
12
3
45
6

【问题讨论】:

  • 仔细考虑while ((traverse-&gt;next = NULL))中的条件。 (如果您添加括号以消除编译器警告,则应重新考虑该选择。警告很重要。)
  • 你可能应该将node-&gt;prev初始化为null(或者实现一个构造函数并使用new而不是malloc),事实上你似乎根本没有设置prev
  • 请不要输入定义指针。这是一种不好的做法,您所做的只是隐藏信息而没有任何好处;同样using namespace std...
  • 您将问题标记为 C++。你为什么不把你的结构命名为Node?那么你就不需要那个typedef了。 struct Node { Node* prev; Node* next; }; 在 C++ 中是完全合法的(不像 C,你需要 struct 关键字...)。
  • 关于设计:您可以考虑在列表中添加尾指针,这样您就不必遍历整个列表来添加新节点。照原样,您只能以这种方式实现一个单链表。也许你想上课LinkedList?然后您可以一次拥有多个列表。您现在拥有的所有这些独立功能都将获得成员功能,例如:class LinkedList { Node* head; Node* tail; public: void insertAtFront(Node const* ptr); /*... */ };

标签: c++ linked-list traversal doubly-linked-list


【解决方案1】:

下面是一个简单的解决方案,可能不是最好的,但很有效。此函数将按升序插入元素。

请注意,我们不会在此函数中更新列表的“尾部”。

void insertOrdered(const NodePtr newPtr){
        if (isEmpty()){
            head = newPtr;
            return;
        }

        NodePtr lastNode, whereToInsert = head;

        while (whereToInsert){
            if (whereToInsert->data > newPtr->data){
                break;
            }
            lastNode = whereToInsert;
            whereToInsert = whereToInsert->next;
        }

        if (whereToInsert == head){
            newPtr->next = head;
            head->prev = newPtr;
            head = newPtr;
        }
        else if (whereToInsert) {
            newPtr->next = whereToInsert;
            whereToInsert = whereToInsert->prev;
            newPtr->prev = whereToInsert;
            whereToInsert->next = newPtr;
        }
        else {
            lastNode->next = newPtr;
            newPtr->prev = lastNode;
        }
}

另外,请避免使用如下代码:

if ((fptr = fopen("input.txt","r")) == NULL){

改为在单独的代码行中使用:

fptr = fopen("input.txt","r")
if (fptr == NULL){ /* your stuff */ } 

【讨论】:

    【解决方案2】:

    你可以在 insertStrategic(); 2次,而不需要

    while ((traverse->next != NULL)){
      if(traverse->data < newPtr->data)){
        traverse = traverse->next;
      }
      else{
        traverse->prev->next = newPtr;
        newPtr->next = traverse;
        break;
      }
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-25
      • 2014-03-12
      • 2021-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-23
      相关资源
      最近更新 更多