Функция записи принимает 2 параметра - указатель головы ИЛИ хвост, а также направление перемещения для связанного списка - PullRequest
0 голосов
/ 02 апреля 2020

Вот как я определил и инициализировал связанный список

struct listrec
{
    struct listrec    *prev;
    float       value;
    struct listrec    *next;
};

listrec *head, *tail;

int main() {
int number;
cin >> number;
float content = 2.0;
    for (float i = 0; i < number; i++)
    {
        if (i == 0)
        {
            head = new listrec;
            head->prev = nullptr;
            head->value = 1.0;
            head->next = nullptr;
            tail = head;
        }
        else
        {
            auto *newNode = new listrec;
            newNode->value = content++;
            newNode->next = nullptr;
            newNode->prev = tail;
            tail->next = newNode;
            tail = tail->next;
        }
    }
return 0;
}

Так выглядит связанный список

enter image description here

Мне нужно " написать функцию, которая принимает два входных параметра - головку указателя ИЛИ хвост, а также параметр направления, по которому необходимо пройти - чтобы пройти по связанному списку и вернуть количество элементов в списке. "

Я понятия не имею, как написать такую ​​функцию…

Я знаю, если я хочу посчитать количество элементов из первого узла, то я могу написать такую ​​функцию:

float listSize(listrec* head)
{
    int count = 0; 
    listrec* current = head; // Initialize current  
    while (current != NULL)
    {
        count++;
        current = current->next;
    }
    return count;
}

Или, если я хочу сосчитать элементы из последнего элемента, то

float listSize2(listrec* tail)
{
    int count = 1;
    listrec* current = tail;
    while (tail->prev != NULL)
    {
        count++;
        tail = tail->prev;
    }
    return count;
}

Но как мне объединить эти два? Любые советы будут оценены!

Ответы [ 2 ]

2 голосов
/ 02 апреля 2020

Вот функция, предполагающая двусвязный список:

enum class Direction {FORWARD, REVERSE};

struct Node
{
    Node * previous;
    Node * next;
};

unsigned int Count(Node * p_begin, Direction traverse_dir)
{
    unsigned int node_count = 0U;
    while (p_begin != nullptr)
    {
        ++node_count;
        if (traverse_dir == FORWARD)
        {
            p_begin = p_begin->next;
        }
        else
        {
            p_begin = p_begin->previous;
        }
    }
    return node_count;
}

В соответствии с требованием, функция принимает 2 параметра, указатель на головной или хвостовой узел и направление и возвращает количество узлы пройдены.

Функция начинается с пройденного указателя, затем идет вперед или назад (в зависимости от параметра направления) и увеличивает счетчик узлов. L oop останавливается, когда встречается нулевой указатель, который обычно сигнализирует о начале или конце списка.

Поскольку используется только класс узла, вы можете наследовать от узла для создания различных типов списка:

struct Integer_Node : public Node
{
    int data;
};

Поле данных не играет роли при обходе списка, поэтому оно было удалено из объекта основного узла.

1 голос
/ 02 апреля 2020

Вам не нужно «объединять» их. Вам нужно позвонить одному или другому в зависимости от направления:

enum class Direction { Forward, Backwards };

int listSize(listrec* p, Direction dir)
{
     if (dir == Direction::Forward)
          return listSize(p);
     else
          return listSize2(p);
}

Это не обзорный сайт, и, как говорится, я не могу с чистой совестью оставить этот ответ без совета для вашего кода:

  • в C ++ вы должны использовать RAII . Следствием этого является то, что вы никогда не должны использовать явные вызовы к new / delete и не должны использовать необработанные указатели.
  • count - это целое число, поэтому в ваших функциях возвращается float без разницы. У данных с плавающей точкой есть свои проблемы, не используйте их для целых чисел.
  • лучше назовите ваши функции. listSize и listSize2 ужасные имена. Ваши функции не список , они просто возвращают размер. Так что лучшее имя getSize. Кроме того, различие между числом по числу является еще одной ужасной идеей. Вы можете использовать getSize и getSizeReverse.
  • . Нет необходимости передавать указатели на вашу функцию. Передача по ссылке или даже по значению в вашем случае предпочтительнее.
  • вам нужны лучшие OOP абстракции. listrec - это запись списка (она же узел списка). Кроме того, вам нужен класс, который абстрагирует список. Он будет содержать указатель на заголовок списка и указатель на конец списка.
  • Вы должны создать функцию для вставки в список (и по одной для каждой операции в списке), а не делать это вручную в основном.
...