Основная функция вставки связанного списка

Объект Query при запросе на итерацию результатов, представляющих объект, подобный TestSet, выполняет идентификацию в результирующих строках на основе идентификатора объекта, так что если запрос должен был возвращать 100 строк, каждый с тем же TestSet, вы получите только один объект результата. Это поведение проистекает из функции «горячего присоединения» Query, где часто бывает, что многие строки результатов получаются с одинаковым первичным идентификатором, но также содержат переменную вторичную идентификацию соответствующей строки, которая должна быть заполняется в коллекцию по каждой первичной идентичности - в этом очень распространенном случае желательно только один экземпляр первичного идентификатора.

Давайте рассмотрим, что делает distinct(). Предположим, что ваш запрос для объектов 4M возвращает 1000 строк с id = 1, 1000 строк с id = 2 и т. Д. Запрос с лимитом (100) попадает в первые 100 строк с id = 1, Query uniquifies, и вы получаете один результат объект назад, так как все они id = 1. Но с distinct() внезапно мы получаем 100 строк с различными тождествами, то есть «id = 1», «id = 2», «id = 3». Query затем присваивает каждой из этих строк новому TestSet объекту в карте идентификации, и вы получите 100 строк назад.

Параметр echo='debug' на вашем Engine временно покажет, что SQL является а также возвращаемые строки результатов. Когда вы видите много строк результатов с одним и тем же первичным ключом, вы знаете, что Query, когда его попросят вернуть полные объекты, будет уникальным для всех этих избыточных тождеств до одного объекта, представленного для каждой строки.

1
задан Danialz 18 January 2019 в 08:41
поделиться

4 ответа

Здесь вы объявляете headptr и устанавливаете его на NULL:

struct record *headptr = NULL;

Затем вы передаете его insert:

insert(headptr, data);

Итак, ptr в insert равно NULL:

void insert(struct record *ptr, int value)

Затем вы устанавливаете curptr = ptr;, поэтому curptr равно NULL. Затем происходит сбой в этой строке:

while (value >= (curptr->data)) {

Поскольку вы пытаетесь получить доступ к памяти, на которую указывает curptr, то есть NULL на тот момент.

Я предполагаю, что вы хотели выделить память для headptr перед передачей ее в insert. Или обработайте регистр указателя как NULL в insert.

0
ответ дан Blaze 18 January 2019 в 08:41
поделиться

Во-первых, используйте setbuf(stdout, NULL);, если вы хотите, чтобы ваши отпечатки сбрасывались до того, как ваша программа неожиданно завершит работу.

Во-вторых, как уже упоминали другие, вы получаете доступ к элементу указателя NULL в while (value >= (curptr->data)), который вызывает сбой.

В-третьих, ваша insert и print логика также неверна.

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

struct record{
    int data;
    struct record *nextptr;
};

void insert (struct record **ptr,int value);
void printList(struct record *ptr);

int main() {
    setbuf(stdout, NULL);
    struct record *headptr = NULL;
    for (int i = 0; i < 4; ++i) {
        int data;
        printf("Enter your value");
        scanf("%d", &data);
        insert(&headptr, data);
    }
    printList(headptr);


    return 0;
}
void insert (struct record **head,int value){
    printf("WE ARE IN THE INSERT FUNCTION");
    struct record *newptr = (struct record *) malloc(sizeof(struct record));
    newptr->data=value;
    newptr->nextptr=NULL;
    struct record *curptr=*head;
    struct record *prevcurptr=NULL;

    while(curptr!=NULL && value >= (curptr->data)){
        prevcurptr=curptr;
        curptr=curptr->nextptr;
    }
    if (curptr==NULL){
        if (prevcurptr==NULL) {         
            *head=newptr;
        } else {
            newptr->nextptr=prevcurptr->nextptr;
            prevcurptr->nextptr=newptr;
        }
    }
    else{
        newptr->nextptr=curptr;
        if (prevcurptr==NULL)       
            *head=newptr;
        else
            prevcurptr->nextptr=newptr;
    }

}
void printList(struct record *ptr){
    while(ptr != NULL){
        printf("\n %d", ptr->data);
        ptr=ptr->nextptr;
    }
}
0
ответ дан d9ngle 18 January 2019 в 08:41
поделиться

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

[110 ]
0
ответ дан SPlatten 18 January 2019 в 08:41
поделиться

У вас есть две большие проблемы с insert. Сначала вы передаете ptr в качестве указателя struct record. Когда это происходит, ваша insert функция получает копию указателя , которая указывает на то же место в памяти, но сама имеет отдельный адрес, очень отличающийся от указателя, переданного из main() , Что это означает, не имеет значения, что вы делаете с копией указателя в insert, эти изменения никогда не будут видны в main(), потому что вы работаете с копией и не возвращаете значение другим способом. Чтобы решить эту проблему, укажите параметр struct record ** и передайте адрес указателя из main().

Следующая самая большая проблема, с которой вы столкнулись в insert, заключается в том, что вы не можете проверить, является ли curptr NULL (как это будет при первом вызове insert), прежде чем вы начнете разыменовывать curptr - вероятно приводя к segfault или другому запуску мельницы Неопределенное поведение.

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

  1. Вставляю ли я первый узел? (если так, просто назначьте `* ptr = newptr); и
  2. все другие вставки потребуют от вас итерации, чтобы найти подходящие 2-узлы для вставки ваших данных между ними на основе value из data.

Вы можете обрабатывать оба случая просто:

    rec_t *curptr = *ptr,
        *newptr = malloc (sizeof *newptr);
    if (!newptr) {
        perror ("malloc-newptr");
        return;
    }

    newptr->data = value;
    newptr->nextptr = NULL;

    if (curptr == NULL) {       /* handle new-list case and return */
        *ptr = newptr;
        return;
    }

    if (value < curptr->data) {     /* handle new 1st node */
        newptr->nextptr = curptr;
        *ptr = newptr;
        return;
    }

    /* iterate with curptr until value > curptr->nextptr->data */
    while (curptr->nextptr != NULL && value > curptr->nextptr->data)
        curptr = curptr->nextptr;

    newptr->nextptr = curptr->nextptr;      /* wire new node to next node */
    curptr->nextptr = newptr;               /* wire current to new node */

В любой программе, которую вы пишете, которая выделяет память, вы должны сохранить указатель на начало каждого выделенного блока, чтобы он мог быть освобожден, когда память больше не нужна. Как правило, вы захотите написать функцию listfree, чтобы справиться с этим для вас. Вы могли бы написать что-то простое, например:

void freelist (rec_t *head)
{
    while (head) {
        rec_t *victim = head;
        head = head->nextptr;
        free (victim);
    }
}

( примечание: , как освобождаемый узел сохраняется во временном указателе victim до того, как список переходит к следующему узлу). ). [одна тысяча сто тридцать одна]

В целом, вы можете сделать что-то вроде следующего:

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

typedef struct record {
    int data;
    struct record *nextptr;
} rec_t;

void insert (rec_t **ptr, int value);
void printList (rec_t *ptr);
void freelist (rec_t *head);

int main (void) {
    rec_t *headptr = NULL;

    for (int i = 0; i < 4; ++i) {
        int data;
        printf("Enter your value: ");
        scanf("%d", &data);
        insert (&headptr, data);
    }
    printList(headptr);
    freelist (headptr);

    return 0;
}

void insert (rec_t **ptr, int value) 
{
    if ( ptr == NULL ) {
        return;  
    } 

    rec_t *curptr = *ptr,
        *newptr = malloc (sizeof *newptr);  /* don't cast the return */
    if (!newptr) {
        perror ("malloc-newptr");
        return;
    }

    newptr->data = value;
    newptr->nextptr = NULL;

    if (curptr == NULL) {       /* handle new-list case and return */
        *ptr = newptr;
        return;
    }

    if (value < curptr->data) {     /* handle new 1st node */
        newptr->nextptr = curptr;
        *ptr = newptr;
        return;
    }

    /* iterate with curptr until value > curptr->nextptr->data */
    while (curptr->nextptr != NULL && value > curptr->nextptr->data)
        curptr = curptr->nextptr;

    newptr->nextptr = curptr->nextptr;      /* wire new node to next node */
    curptr->nextptr = newptr;               /* wire current to new node */
}

void printList(struct record *ptr)
{
    while (ptr != NULL) {
        printf(" %d", ptr->data);
        ptr = ptr->nextptr;
    }
    putchar ('\n');
}

void freelist (rec_t *head)
{
    while (head) {
        rec_t *victim = head;
        head = head->nextptr;
        free (victim);
    }
}

Пример использования / вывода

$ ./bin/lltcmpl
Enter your value: 1
Enter your value: 8
Enter your value: 5
Enter your value: 7
 1 5 7 8

$ ./bin/lltcmpl
Enter your value: 2
Enter your value: 1
Enter your value: 4
Enter your value: 3
 1 2 3 4

Посмотрите вещи и дайте мне знать если у вас есть вопросы.

0
ответ дан David C. Rankin 18 January 2019 в 08:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: