Почему я не могу получить простые множители заданного числа в связанном списке? Я добавил структуру, функцию, main и функцию print - PullRequest
0 голосов
/ 24 марта 2020

Я пытаюсь найти простые факторы заданного числа N и вернуть их в объединенный список. Нет проблем с поиском простых факторов, но у меня есть проблема с возвращением их в связанный список ... I я не получаю сообщение об ошибке, когда я запускаю код, но я получаю только первый простой множитель в качестве вывода, не могу получить остальное, например, если N равно 72, я получаю 2 в качестве вывода, но не могу остальные факторы

    #include <stdio.h>
    #include <stdlib.h>
    //This is my structure
    typedef struct SinglyLinkedListItem
    {
        int data;
        struct SinglyLinkedListItem*next;
    }SLLI;

    //This is my function to find the prime factor and return in  a linked list
   SLLI*PrimeFactor(SLLI*prime,int N)
   {
    SLLI*pList=NULL;
    int i,j,isPrime;
    for (i = 2; i <= N; i++)
    {
        if(N % i == 0)
        {
            isPrime = 1;
            for (j = 2; j <= i/2; j++)
            {
                if(i % j == 0)
                {
                    isPrime = 0;
                    break;
                }
            }
            //Most probably problem is after this part of the code
            if(isPrime == 1)
            {
                //Adding first factor to the list
                if(pList==NULL)
                {
                    pList=malloc(sizeof(SLLI));
                    pList->data=i;
                    pList->next=NULL;
                    prime= pList;
                }

                //Trying to add rest of them but can't
                else
                {
                    pList->next = malloc(sizeof(SLLI));
                    pList->next->data = i;
                    pList->next->next = NULL;
                    pList = pList->next;
                }
            }
        }
   }
    return prime;
}

 void Printlist(SLLI*pHead)
 {
    SLLI*temp=pHead;
    while(temp!=NULL)
    {
        printf("%d\t",temp->data);
        temp=temp->next;
    }
  }

  int main()
  {
    SLLI*pHead=NULL;

    pHead=PrimeFactor(pHead,72);

    Printlist(pHead);


  }

1 Ответ

2 голосов
/ 24 марта 2020

Я подозреваю, что вы просто не распечатываете их правильно, трудно сказать, так как вы не включили этот код, но, если вы добавите main таким образом:

int main(void) {
    SLLI * x = PrimeFactor(NULL, 72);
    while (x != NULL) {
        printf("%d\n", x->data);
        x = x->next;
    }
    return 0;
}

, тогда вы будете получите как 2 , так и 3, которые являются единственными простыми коэффициентами 72: 72 = 2<sup>3</sup>3<sup>2</sup> (8 x 9).

Аналогично, 120 дает вам 2, 3 и 5: 120 = 2<sup>3</sup>3<sup>1</sup>5<sup>1</sup> (8 x 3 x 5).


Несколько других моментов для рассмотрения:

  • Я не уверен, почему вы проходите в prime к функции, так как вы все равно перезаписываете ее. Вы должны удалить это из определения функции и просто иметь локальную переменную для хранения информации.

  • При проверке на простоту вам не нужно go, чтобы вдвое уменьшить значение, просто на его площадь root. Таким образом, лучшим значением l oop будет: for (j = 2; j * j <= i; j++).

  • Чётный лучше проверяет, что кроме 2 и 3 каждое простое число имеет вид 6n + 1 или 6n + 5. Это потому, что:

    • 6n + 0 = 6n, кратное шести;
    • 6n + 2 = 2(3n + 1), кратное двум;
    • 6n + 3 = 3(2n + 1), кратное трем ;
    • 6n + 4 = 2(3n + 2), кратное двум;

, оставляя только 6n + 1 и 6n + 5 в качестве кандидатов (не каждый один из них является простым числом (например, 6(4) + 1 = 25), но простые числа могут быть извлечены исключительно из этого набора).

Таким образом, еще лучшим тестом на простоту является следующая функция:

// Function for checking primality.

int isPrime(int number) {
    // Special cases.

    if ((number == 2) || (number == 3)) return 1;
    if ((number % 2 == 0) || (number % 3 == 0)) return 0;
    if (number < 5) return 0;

    // Efficient selection of candidate primes, starting at 5, adding
    // 2 and 4 alternately: 5, 7, 11, 13, 17, 19, 21, 25, 27, ...

    for (
        int candidate = 5, add = 2;
        candidate * candidate <= number;
        candidate += add, add = 6 - add
    ) {
        if (number % candidate == 0) {
            return 0;
        }
    }

    return 1;
}

Использование этой функции и добавление некоторых дополнительных функций для выгрузки и освобождения списка, а также предоставление тестового набора main дает следующую полную программу:

#include <stdio.h>
#include <stdlib.h>

typedef struct sListItem
{
    int data;
    struct sListItem *next;
} ListItem;

// Function for checking primality.

int isPrime(int number) {
    // Special cases.

    if ((number == 2) || (number == 3)) return 1;
    if ((number % 2 == 0) || (number % 3 == 0)) return 0;
    if (number < 5) return 0;

    // Efficient selection of candidate primes, starting at 5, adding
    // 2 and 4 alternately: 5, 7, 11, 13, 17, 19, 21, 25, 27, ...

    for (int candidate = 5, add = 2; candidate * candidate <= number; candidate += add, add = 6 - add)
        if (number % candidate == 0)
            return 0;

    return 1;
}

// Function for returning list of prime factors.

ListItem *primeFactorList(int number) {
    ListItem *retVal = NULL;
    ListItem *lastItem;

    // Analyse possible factors, up to half of number.

    for (int divisor = 2; divisor <= number / 2 + 1; divisor++) {
        if ((number % divisor == 0) && isPrime(divisor)) {
            if (retVal == NULL) {
                // Adding first item to list.

                retVal = lastItem = malloc(sizeof(ListItem));
                lastItem->data = divisor;
                lastItem->next = NULL;
            } else {
                // Adding subsequent items to list.

                lastItem->next = malloc(sizeof(ListItem));
                lastItem = lastItem->next;
                lastItem->data = divisor;
                lastItem->next = NULL;
            }
        }
    }

    return retVal;
}

// Dump a list.

void dumpList(int value, ListItem *head) {
    printf("%d:", value);
    while (head != NULL) {
        printf(" -> %d", head->data);
        head = head->next;
    }
    putchar('\n');
}

// Free a list.

void freeList(ListItem *head) {
    while (head != NULL) {
        ListItem *toDelete = head;
        head = head->next;
        free(toDelete);
    }
}

// Test program.

int main(int argc, char *argv[]) {
    static int data[] = { 10, 24, 72, 120, 125, -1 };
    for (int *ptr = &(data[0]); *ptr >= 0; ptr++) {
        ListItem *list = primeFactorList(*ptr);
        dumpList(*ptr, list);
        freeList(list);
    }
    return 0;
}

И компиляция и запуск, который показывает результаты тестового набора (с моими добавленными комментариями справа, и не стесняйтесь добавлять любые дополнительные значения в массив data, если вы хотите больше тестирования):

10: -> 2 -> 5                   2 x 5
24: -> 2 -> 3                   2^3 x 3
72: -> 2 -> 3                   2^3 x 3^2
120: -> 2 -> 3 -> 5             2^3 x 3 x 5
125: -> 5                       5^3
...