Түйіндерді дөңгелек екі рет байланыстырылған тізімде рекурсивті түрде санауға тырысу қатесі

Міне, менің есептеуді жүзеге асыру:

int count(node *start)
{
    static int l ;
    node *current;            /* Node for travelling the linked list*/
    current=start;
    if(current->next!=start)
    {
        l = 1 + count ( current->next ) ;
        return ( l ) ;
    }


    else
    {
        return(1);
    }
}

Міне, мен оның негізгі функциясының фрагменті:

void main()
{
    node *head;
printf ( "Length of linked list = %d", count ( head ) ) ;
}

Міне, құрылым:

struct cirdoublelinklist
{
    struct cirdoublelinklist *prev;  /** Stores address of previous node **/
    int value;                   /** stores value **/
    struct cirdoublelinklist *next;  /** stores address of next node **/
};

/** Redefining list as node **/
  typedef struct cirdoublelinklist node;

Тізімнің ұзындығын көруге және көруге тырысқанда, ол жадтан тыс қалады. Пожалуйста, маған көмектесті, мен бұл туралы ұзақ уақыт бойы жұмыс істедім.

Бірінші түйінді қосу әдісі:

void initialize(node *start)
{
    start->prev=start;
    printf("\nEnter Value\n");
    scanf("%d",&start->value);
    start->next=start;
}

Көрсетілген орыннан кейін келесі түйіндерді қосу әдісі:

void insert_after(node *start)
{
    int num;                  /* value for inserting a node */
    int flag=0;
    node *newnode;            /* New inputed node*/
    node *current;            /* Node for travelling the linked list*/
    newnode=(node*)malloc(sizeof(node));
    printf("\nEnter the value after which you want to insert a node\n");
    scanf("%d",&num);
    init(newnode);
    current=start;
    while(current->next!=start)
    {

        if(current->value==num)
        {
            newnode->next=current->next;
            current->next->prev=newnode;
            current->next=newnode;
            newnode->prev=current;
            flag=1;
        }
        current=current->next;
    }
    if(flag==0 && current->next==start && current->value==num)
    {
        /***  Insertion checking for last node  ***/
        newnode->next=current->next;     /* Start is being copied */
        current->next->prev=newnode;
        current->next=newnode;
        newnode->prev=current;
        flag=1;
    }
    if(flag==0 && current->next==NULL)
        printf("\nNo match found\n");
} 
0
Неге сіз l статикасын жасадыңыз? Бұл функция толығымен рентген болып қалуына кедергі келтіреді, бұл әдетте тиісті рекурсияға қойылатын талап болып табылады.
қосылды автор Ignacio Vazquez-Abrams, көзі

4 жауаптар

Мәселе мынада, сіз негізгі функцияны NULL көрсеткіші бойынша шақырасыз. Infact түйін * head; деп жарияланды, бірақ бірдеңеге тағайындалмайды. Сондықтан сіз осы жолды орындаңыз:

if(current->next!=start)

the program crashes because it will check for NULL->next that, obviously, doesn't exist.

1
қосылды
@ user1017072 Ал бұл жағдайда сіз бізге деректерді қосатын функцияны көрсетуіңіз керек. Сонымен қатар, сызықты статикалық int l; себебі ол пайдасыз және 1 + count (current-> next) қайтару кезінде өзгертеді; бұл рекурсивті функцияны алудың дұрыс жолы.
қосылды автор Aurelio De Rosa, көзі
Сондай-ақ, менде түйінге деректер мәндерін енгізетін әдіс бар. Бірақ жаңа түйіндер жасағаннан кейін тіпті сәтсіздікке ұқсайды. Бірінші түйін үшін ол 1 ұзындығын береді (яғни, басқа блокқа өтеді), ал екіншісіне егер ол (ағымдағы -> келесі! = Бастау) жетсе, ол құлап қалады, түйіндер жасайтын функциядағы кейбір инициализациялар? Көмегіңіз үшін рақмет
қосылды автор user1017072, көзі
Сәлеметсіздер ме, мәселені бастапқы түйінді және одан кейінгі түйінді кірістіру әдістерімен жасадым. Мен сіз көрсеткендей статистиканы алып тастауға тырыстым, бірақ ол әлі де бірдей еске сақтау мәселесімен сәтсіздікке ұшырады. Қандай ұсыныстар көп? Сіздің уақытыңыз бен қолдауыңызға рахмет
қосылды автор user1017072, көзі

Every time you call count, it has a new start, so current->next!=start is always comparing a node to its successor, which will only ever end if the list has length 1. What you most likely want to do is have two functions:

int count(node *start)
{
    if(start == NULL)
        return 0;
    return count_helper(start, start);
}

int count_helper(node *start, node *current)
{
    static int l;
    if(current->next!=start)
    {
        l = 1 + count (start, current->next);
        return ( l ) ;
    }
    else
    {
        return(1);
    }
}

Басқалар айтқандай, статикалық айнымалы қажет емес. count_helper деп аталатынымды жазудың жақсы тәсілі:

int count_helper(node *start, node *current)
{
    if(current->next!=start)
    {
        return 1 + count (start, current->next);
    }
    else
    {
        return 1;
    }
}

Ақырында, неғұрлым тиімді іске асыру рекурсивтілік болмайды:

int count(node *start)
{
    if(start == NULL)
        return 0;
    node *current = start->next;
    int c = 1;
    while(current != start)
    {
        c++;
        current = current->next;
    }
    return c;
}
1
қосылды
@ user1017072 Ұзындығы = 0 жағдайын ұстау үшін, рекурсивті емес нұсқаға түзетуді ескеріңіз. Сондай-ақ, сіз өзіңіздің сұрағыңызға ең жақсы жауап беретін жауапты қабылдағаныңыз пайдалы.
қосылды автор Aaron Dufour, көзі
@CVega Жақсы ұстау. Бұл жауапты (2 жаста!) Есіме түсірмеймін, бірақ c кодын 1 деп баптандыруға негізделген, менің ойымша current бастау үшін start-> next . Бұл мағынасы бар ма?
қосылды автор Aaron Dufour, көзі
@ Аарон-дуфур Мен рекурссивтік емес нұсқа дұрыс емес деп ойлаймын. уақыт циклінің алдында ағымдық және start тең болғанға дейін, ол циклге кірмейтін болады, бұл do-while циклі болуы керек.
қосылды автор Carlos Vega, көзі
Ия, енді ол бекітілді;)
қосылды автор Carlos Vega, көзі
Ааронға өте рахмет, бұл шынында да пайдалы болды. Енді менің түсінігім тазартылды
қосылды автор user1017072, көзі

Insert_after функциясында меңзерді бастау үшін көрсеткішті өту керек

void insert_after(node **start)

орнына

void insert_after(node *start)

Әйтпесе, сіз * бастаудың жергілікті көшірмесін жаңартасыз.

Сол сияқты инициализация үшін

void initialize(node **start)
1
қосылды

Басқаша айтқанда, рекурсиялық қоңыраулар түпнұсқалық бастапқы түйінді білмейді. Екінші түйінін * дәлелін қосуыңыз керек және ол арқылы бастапқы түйінді жіберіңіз.

0
қосылды
Функцияның прототипінде. Функция шақыруында.
қосылды автор Ignacio Vazquez-Abrams, көзі
Hi Ignacio, онда екінші түйінді қосып, бастапқы түйінді қалай жіберемін? Мен нооб сияқты дыбысталу үшін өкінемін, бірақ оны қалай түзетуге болатынын көрсете аласыз ба, түсінбеймін. Сіздің көмегіңіз үшін үлкен рахмет
қосылды автор user1017072, көзі