删除空终止双向链表

时间:2017-09-17 03:00:55

标签: c doubly-linked-list

我在破坏以空终止的双向链表中的所有节点时遇到问题(这是一个列表,其中2个指针的头部和尾部指向节点,第一个节点的prev和最后一个节点的下一个为空)。以null结尾的双重列表看起来像这样  Null terminated doubly linked list)。

代码适用于小输入,但对于非常大的输入,它给出了 损坏的大小与前缀大小错误

>>Input1 : 12312312312123123123123123123123
>>Input2 : 1
>>Addition : 12312312312123123123123123123124
>>Inside Destroy
*** Error in `./savan': corrupted size vs. prev_size: 0x0000000002066c40 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f88ba43a7e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x83781)[0x7f88ba446781]
/lib/x86_64-linux-gnu/libc.so.6(realloc+0x179)[0x7f88ba447839]
./savan[0x401073]
./savan[0x401369]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f88ba3e3830]
./savan[0x400749]

这是我破坏所有节点和结构定义的代码。

结构定义

typedef struct node{
        char ch;
        struct node *next,*prev;
}node;

typedef struct Integer{
        node *p, *q;
}Integer;

destroyInteger的代码

 void destroyInteger(Integer *a){
    node *tmp = NULL;
    printf("Inside Destroy");
        if(a->p == NULL) //if the Integer is empty then do nothing
            return;
        while(a->p->next != NULL){ //while integer's next not null loop
            tmp = a->p;        //assign to temp and free it
            a->p = a->p->next; // move the pointer ahead
            free(tmp);
        }
        tmp = a->p; //for last node or if only one node as it is double null terminated list
        free(tmp);  
        a->p = NULL; //make the integer null as in initInteger
        a->q = NULL;
    }

Integer.c ADT整码

#include<stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <limits.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include<unistd.h>
#include<string.h>
#include<ctype.h>
#include "integer.h"
void initInteger(Integer *a){
    a->p = NULL;
    a->q = NULL;
}

void addDigit(Integer *a, char c){
    node *temp;
    if(isdigit(c)){
        temp = (node*)malloc(sizeof(node));
        temp->ch = c;
        temp->next = NULL;
        if(a->p == NULL){
            temp->prev = NULL;
            a->p = temp;
            a->q = temp;
        }
        else{
            a->q->next = temp;
            temp->prev = a->q;  
            a->q = temp;
        }
    }
    else
        return;
}
void printInteger(Integer a){
    char c;
    if(a.p == NULL){
        printf("0\n");
        return;
    }
    while(a.p->next != NULL){
        c = a.p->ch;
        putchar(c);
        a.p = a.p->next;
    }
    c = a.p->ch;
    putchar(c);
    putchar('\n');
}
Integer createIntegerFromString(char *str){
    int i = 0, flag = 0;
    char ch;
    Integer res;
    initInteger(&res);
    while(*(str + i) != '\0'){
        if(isdigit(*(str + i))){
            ch = *(str + i);
            addDigit(&res, ch);
            flag = 1;
            i++;
        }
        else
            break;          
    }   
    if(flag == 0){
        addDigit(&res, '0');
    }
    return res;
}
Integer addIntegers(Integer a, Integer b){
    Integer c;
    char num1, num2, *revString = (char*)malloc(sizeof(char));
    int n1, n2, carry = 0, counter = 0, sum = 0, flag1 = 0, flag2 = 0, mainflag = 0, i;
    initInteger(&c);
    if(a.p == NULL && b.p == NULL){
        addDigit(&c, '0');
        return c;
    }
    else if(a.p == NULL && b.p != NULL)
        return b;       
    else if(a.p != NULL && b.p == NULL)
        return a;

    else{
        do{     n1 = n2 = 0;
            num1 = num2 = '\0';
            if(a.q->prev == NULL && b.q->prev == NULL)
                mainflag = 1;
            //for a
            if(a.q->prev == NULL && flag1 == 0){
                num1 = a.q->ch;
                n1 = num1 - '0';
                flag1 = 1;
            }
            else if(a.q->prev != NULL){
                num1 = a.q->ch;
                n1 = num1 - '0';
                a.q = a.q->prev;
            }
            else
                n1 = 0;
            //for b
            if(b.q->prev == NULL && flag2 == 0){
                num2 = b.q->ch;
                n2 = num2 - '0';
                flag2 = 1;      
            }
            else if(b.q->prev != NULL){
                num2 = b.q->ch;
                n2 = num2 - '0';
                b.q = b.q->prev;
            }
            else
                n2 = 0; 
            sum = n1 + n2 + carry;
            if(sum >=  10){
                revString[counter++] = (sum % 10) + '0';
                carry = 1;
                sum = 0;
            }
            else{
                revString[counter++] = sum + '0';
                carry = 0;
            }
        revString = (char*)realloc(revString, counter + 1);
        }while(mainflag != 1);
        if(carry == 1){
            revString[counter++] = '1';
        }
        for(i = counter; i > 0; i--){
            addDigit(&c, revString[i-1]);
        }
    }
    free(revString);
    return c;
}
Integer substractIntegers(Integer a, Integer b){
    Integer c;
    char num1, num2, *revString = (char*)malloc(sizeof(char));
    int n1, n2, carry = 0, counter = 0, sum = 0, flag1 = 0, flag2 = 0, mainflag = 0, i, len1, len2;
    len1 = length(a);
    len2 = length(b);
    initInteger(&c);
    if(len1 < len2){
        addDigit(&c, '0');
        return c;
    }
    if(a.p == NULL && b.p == NULL){
        addDigit(&c, '0');
        return c;
    }
    else if(a.p == NULL && b.p != NULL)
        return b;       
    else if(a.p != NULL && b.p == NULL)
        return a;

    else{
        do{     n1 = n2 = 0;
            num1 = num2 = '\0';
            if(a.q->prev == NULL && b.q->prev == NULL)
                mainflag = 1;
            //for a
            if(a.q->prev == NULL && flag1 == 0){
                num1 = a.q->ch;
                n1 = num1 - '0';
                flag1 = 1;
            }
            else if(a.q->prev != NULL){
                num1 = a.q->ch;
                n1 = num1 - '0';
                a.q = a.q->prev;
            }
            else
                n1 = 0;
            //for b
            if(b.q->prev == NULL && flag2 == 0){
                num2 = b.q->ch;
                n2 = num2 - '0';
                flag2 = 1;      
            }
            else if(b.q->prev != NULL){
                num2 = b.q->ch;
                n2 = num2 - '0';
                b.q = b.q->prev;
            }
            else
                n2 = 0; 
            sum = n1 - n2 - carry;
            if(sum <  0){
                sum += 10;
                revString[counter++] = sum  + '0';
                carry = 1;
                sum = 0;
            }
            else{
                revString[counter++] = sum + '0';
                carry = 0;
            }
        revString = (char*)realloc(revString, counter);
        }while(mainflag != 1);

        if(carry == 1){
            revString[counter++] = '1';
        }
        for(i = counter; i > 0; i--){
            addDigit(&c, revString[i-1]);
        }
    }
    free(revString);
    return c;
}
int length(Integer l) {
    int len = 0;
    node *tmp;
    tmp = l.p;
    if(!tmp)
        return 0;
    while(tmp->next != NULL){
        tmp = tmp->next;
        len++;
    }
    return len+1;
}
void destroyInteger(Integer *a){
    node *tmp = NULL;
    if(a->p == NULL)
        return;
    while(a->p->next != NULL){
        tmp = a->p;
        a->p = a->p->next;
        free(tmp);
    }
    tmp = a->p;
    a->p = NULL;
    a->q = NULL;
    free(tmp);
}

用于调用的Main.c以及我在其他文件中的integer.h

Integer a, b, c;
    char ch;
    char str[64]; /* This size may change */

    initInteger(&a);
    initInteger(&b);

    while((ch = getchar()) != '\n')
        addDigit(&a, ch);
    scanf("%s", str);
    b = createIntegerFromString(str);
    c = addIntegers(a, b); 
    printInteger(c);
    destroyInteger(&c);

Integer.h文件

typedef struct node{
    char ch;
    struct node *next,*prev;
}node;

typedef struct Integer{
    node *p, *q;
}Integer;

/*Functions*/
void initInteger(Integer *a);
void addDigit(Integer *a, char c);
void printInteger(Integer a);
Integer createIntegerFromString(char *str);
Integer addIntegers(Integer a, Integer b);
Integer substractIntegers(Integer a, Integer b);
void destroyInteger(Integer *a);
int length(Integer a);

任何帮助都将不胜感激。谢谢。

1 个答案:

答案 0 :(得分:3)

我注意到的一件事是addIntegers中的代码:

else if(a.p == NULL && b.p != NULL)
    return b;       

如果您设置

c = addIntegers(a, b)

此代码会使c成为b的副本,但cb都将指向相同的节点。如果你然后销毁c(或b),那么另一个将指向已释放的内存,这是一个失败的秘诀。