繁体   English   中英

C++ 茎叶图。 我不明白如何制作链表的链表

[英]C++ Stem and Leaf Plot. I don't understand how to make a linked list of linked lists

我有一个项目,用链表制作茎叶图,但我不断收到我什至不明白的错误。 你如何制作链表的链表? 我必须以这种方式完成作业,所以我不能以其他方式完成,我必须从下面的文件中工作。 我的顶部词干链表有效,但它似乎没有访问叶部分,并且出现以下错误:

“0x0000000000404050 处的指令在 0x000000000000001E 处引用。无法读取内存。”

这是我的代码:

* Driver.cpp
*/

#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>

using namespace std;

#include "StemAndLeaf2.h"

int main()
{

 ifstream fin("input.txt");

 int x;
 unsigned short leafunit, stemunit;

 fin >> leafunit >> stemunit;

 StemAndLeaf one;
 one.setLeafUnit(leafunit);
 one.setStemUnit(stemunit);

 while (fin >> x)
 {
   one.addTerm(x);
   cout << "Insert: " << x << endl;
   cout << "StemAndLeafPlot: " << endl;
   cout << one << endl;
 }

 cout << "The smallest term: " << one.getSmallestTerm() << endl;
 cout << "The largest term: " << one.getLargestTerm() << endl;
 
   return 0;
}
/*
* SteamAndLeaf2.h
*/

#ifndef STEAMANDLEAF2_H_
#define STEAMANDLEAF2_H_

#include <math.h>
#include <list>
#include <ostream>
// DO NOT REMOVE THE LINE BELOW
/* CMSC341_TEST_INCLUDES */

#include "Stem2.h"

class StemAndLeaf
{
   // DO NOT REMOVE THE LINE BELOW
   /* CMSC341_FRIEND_CLASSES */
public:
   StemAndLeaf(){FRONT_ptr = NULL; REAR_ptr = NULL;};
   ~StemAndLeaf()
   {
       while(FRONT_ptr != NULL)
       {
           Cursor = FRONT_ptr;
           FRONT_ptr = Cursor->getNext();
           delete Cursor;
       }
   }

   unsigned short getLeafUnit() const { return leafUnit; }
   void setLeafUnit(unsigned short leafUnit) { this->leafUnit = leafUnit; }
   unsigned short getStemUnit() const { return stemUnit; }
   void setStemUnit(unsigned short stemUnit) { this->stemUnit = stemUnit; }

   /**
    * @brief Get the smallest term in the datastructure. The term MUST be reconstructed
    *
    * @return unsigned short
    */
   unsigned short getSmallestTerm() const
   {
       return ((FRONT_ptr->getValue()*10))+(FRONT_ptr->findSmallestValue()));
   }

   /**
    * @brief Get the largest term in the datastructure. The term MUST be reconstructed
    *
    * @return unsigned short
    */
   unsigned short getLargestTerm() const
   {
       return ((REAR_ptr->getValue()*10))+(REAR_ptr->findLargestValue()));
   }


   /**
    * @brief Adds the term to the data structure. Insertion MUST be ordered, both for Stem and the Leaf
    *
    * @param term the value to add
    */
   void addTerm(unsigned short term)
   {
       Insert = new Stem();
       Insert->setValue(term/10);
       Insert->setLeafList(Insert->getLeafLink());
       if(isEmpty())
       {
           Insert->setLeafCount(1);
           Insert->insert(term%10);
           FRONT_ptr = Insert;
           REAR_ptr = Insert;
       }
       else
       {
           for(Cursor = FRONT_ptr; Cursor != NULL; Prev = Cursor, Cursor = Cursor->getNext())
           {
               Insert->setLeafCount(1);
               Insert->insert(term%10);
               if((Cursor == FRONT_ptr) && (Cursor->getValue() > Insert->getValue()))
               {
                   Insert->setNext(Cursor);
                   FRONT_ptr = Insert;
               }
               else if((Cursor == REAR_ptr) && (Cursor->getValue() < Insert->getValue()))
               {
                   Cursor->setNext(Insert);
                   REAR_ptr = Insert;
               }
               else if((Prev->getValue() < Insert->getValue()) && (Cursor->getValue() > Insert->getValue()))
               {
                   Prev->setNext(Insert);
                   Insert->setNext(Cursor);
               }
               else if(Insert->getValue() == Cursor->getValue())
               {
                   if(!Cursor->insert(term%10))
                   {
                       Cursor->incrementLeafCount();
                   }
               }
               break;
           }
       }
   }

   /*
    * Used to display/debug the StemAndLeaf diagram
    * will look exactly like this (using example in project):
    *
    * 0 | 0:1
    * ...
    * 2 |
    * 3 | 6:2 9:1
    *
    * You will not be given too much data to overrun 80 characters
    */
   friend std::ostream &operator<<(std::ostream &out, const StemAndLeaf &x)//;
   {
       out << x.FRONT_ptr->getValue() << " | ";
       return out;
   }

private:
   unsigned short leafUnit; // increment of each leaf in this particular structure
   unsigned short stemUnit; // increment of each stem in this particular structure

   Stem *FRONT_ptr, *REAR_ptr, *Insert, *Prev, *Cursor;

   inline bool isEmpty() const { return FRONT_ptr == nullptr; }

};
#endif /* STEAMANDLEAF2_H_ */

/*
 * Steam2.h
 */
#ifndef STEM2_H_
#define STEM2_H_
#include <ostream>
#include <list>
// DO NOT REMOVE THE LINE BELOW
/* CMSC341_TEST_INCLUDES */

#include "Leaf2.h"

class Stem
{
    // DO NOT REMOVE THE LINE BELOW
    /* CMSC341_FRIEND_CLASSES */

public:
    Stem(){FRONT_ptr = NULL; REAR_ptr = NULL;}
    virtual ~Stem(){};

    unsigned short getLeafCount() const { return m_LeafCount; }
    void setLeafCount(unsigned short LeafCount) { m_LeafCount = LeafCount; }
    void incrementLeafCount() { m_LeafCount++; }
    void decrementLeafCount() { m_LeafCount--; }

    Leaf *getLeafLink() const {return FRONT_ptr;}
    void setLeafList(Leaf *LeafList) { FRONT_ptr = LeafList; }

    unsigned short getValue() const { return m_Value; }
    void setValue(unsigned short value) { m_Value = value; }

    Stem *getNext() const { return m_Next; }
    void setNext(Stem *next) { m_Next = next; }

    /**
     * @brief Add the value to the stem. Returns trues if a new lef was created
     *
     * @param value The number to insert
     * @return true if a new leaf was created
     * @return false if we've seen the value before
     */
    bool insert(unsigned short value)
    {
        Insert = new Leaf();
        Insert->setValue(value);
        if(FRONT_ptr = NULL)
        {
            FRONT_ptr = Insert;
            REAR_ptr = Insert;
            return true;
        }
        else
        {
            for(Cursor = FRONT_ptr; Cursor != NULL; Prev = Cursor, Cursor = Cursor->getNext())
            {
                if(Cursor->getValue() == Insert->getValue())
                {
                    Cursor->incrementCount();
                    return false;
                }
                else
                {
                    if((Cursor == FRONT_ptr) && (Cursor->getValue() > Insert->getValue()))
                    {
                        Insert->setNext(Cursor);
                        FRONT_ptr = Insert;
                    }
                    else if((Cursor == REAR_ptr) && (Cursor->getValue() < Insert->getValue()))
                    {
                        Cursor->setNext(Insert);
                        REAR_ptr = Insert;
                    }
                    else if((Prev->getValue() < Insert->getValue()) && (Cursor->getValue() > Insert->getValue()))
                    {
                        Prev->setNext(Insert);
                        Insert->setNext(Cursor);
                    }
                    return true;
                }
            }
        }
    }
    unsigned short findSmallestValue()
    {
        if(FRONT_ptr != NULL){
        return FRONT_ptr->getValue();}
        else {return 0;}
    }
    unsigned short findLargestValue()
    {
        if(REAR_ptr != NULL){
        return REAR_ptr->getValue();}
        else {return 0;}
    }

private:
    // they are given the code for a L.L.
    Leaf *FRONT_ptr, *REAR_ptr, *Insert, *Prev, *Cursor;

    /**
     * Stem Value
     */
    unsigned short m_Value;

    /**
     * How many leaves in this stem
     */
    unsigned short m_LeafCount;

    /**
     * Pointer to the next stem
     */
    Stem *m_Next;
};
#endif /* STEM2_H_ */
/*
*Leaf2.h
*/

#ifndef LEAF2_H_
#define LEAF2_H_

#include <ostream>
// DO NOT REMOVE THE LINE BELOW
/* CMSC341_TEST_INCLUDES */


struct Leaf
{
    // DO NOT REMOVE THE LINE BELOW
    /* CMSC341_FRIEND_CLASSES */

    Leaf()
        : m_Count(1)
    {
    }

    unsigned short getValue() const { return m_Value; }
    void setValue(unsigned short value) { m_Value = value; }

    unsigned short getCount() const { return m_Count; }
    void setCount(unsigned short count) { m_Count = count; }
    void incrementCount() { m_Count++; }
    void decrementCount() { m_Count--; }

    Leaf *getNext() const { return m_Next; }
    void setNext(Leaf *next) { m_Next = next; }

    /**
     * @brief Operator overload to print the Leaf in a nice format According to
     * the project description the format should be "value:count"
     *
     * @param out
     * @param leaf
     * @return std::ostream&
     */
    friend std::ostream &operator<<(std::ostream &out, const Leaf &leaf)
    {
        out << leaf.m_Value << ":" << leaf.m_Count;
        return out;
    }

private:
    unsigned short m_Value;
    unsigned short m_Count;
    Leaf *m_Next;
};
#endif /* LEAF2_H_ */

输入文件是具有以下值的 .txt 文件:

1
10
22
13
8
23

即使我将“添加术语”调用后的所有内容都转换为注释,我也会收到错误,并且我知道叶部分不起作用,因为当我运行“findSmallestTerm”和“findLargestTerm”时,它只给我词干值。 除了叶值的错误之外,我的代码还有很多错误,但我不是在询问整个项目的答案,如果有意义的话,我只需要帮助获取茎和叶列表的连接。 很抱歉在这里转储所有代码,但我不知道问题的哪一部分,所以我不知道什么是相关的或不相关的。

更新:我删除了一些不必要的代码并添加了输入文件的信息。

崩溃是由未初始化的数据成员和错误的检查语句引起的:

if(FRONT_ptr = NULL)

这应该是:

if(FRONT_ptr == NULL)

Stem::m_Next 应该被初始化:

Stem *m_Next=NULL;

Stem::m_Next 应该被初始化:

Leaf *m_Next=NULL;

变量Prev应该在进入 for 循环后初始化:

void addTerm(unsigned short term) {
    // Prev should be inited or the crash happens
    for (Prev = Cursor, Cursor = FRONT_ptr; Cursor != NULL;
         Prev = Cursor, Cursor = Cursor->getNext()) {
}
}


Stem 类应该有析构函数以避免内存泄漏:

virtual ~Stem() {
  while (FRONT_ptr != NULL) {
    Cursor = FRONT_ptr;
    FRONT_ptr = Cursor->getNext();
    delete Cursor;
  }
};

该代码还有其他一些难闻的气味和错误:

  • 临时变量不应是数据成员:INsert、Prev、Cursor
  • Stem::Insert , StemAndLeaf::Insert当数据已经存在于链表中时存在内存泄漏,新的元素还没有插入链表,指针应该被删除
  • 在访问之前忘记检查指针是否为 NULL: getSmallestTerm , getLargestTerm

暂无
暂无

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

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