Взаимосвязанные проблемы списка? - PullRequest
0 голосов
/ 19 ноября 2011

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

Hello\nAll\n.
.\nAll\nHello

Идея состоит в том, чтобы пройти мой список, пока не будет найден '\n', затем пойти в обратном направлении и распечатать это, вернитесь туда, куда я ушел, продолжайте движение до следующей новой строки, затем снова идите вперед и напечатайте и т. д.

Тем не менее, моя текущая реализация не может работать, и я попал в кирпичстены, а советы и подсказки приветствуются!

typedef struct L { 
char val;
struct L *next;
struct L *prev;
}List;

List *insertList(char val, List *t1 );
List *createList(void);

int main(void) {
  List *z = createList();
  List *pos = z;
  while (pos != NULL) {
    while ( z->val != '\n' ) {
        if (z == NULL)
            break;
            z = z->next;
            pos = z;
}
    while (z != NULL) {
        printf("%c", z->val);
        z = z->prev;
    }
}
return 0;
}
List *createList(void) {
  List *h = NULL;
  char c;
  do { 
    c =(char)getchar();
    h = insertList(c, h);
  }while(c != '.');
  return h;
 }
List *insertList( char val, List *t1) {
  List *t = calloc(1, sizeof( List ));
  t->prev = NULL;
  t->val = val;
  t->next = t1;
    if (t1 != NULL) {
     t1->prev = t;
  }
return t;
}

Ответы [ 4 ]

1 голос
/ 19 ноября 2011

Я думаю, что ваша структура должна быть изменена, и нет причин иметь двойной список для решения вашей проблемы.

ваша структура должна содержать

struct node {
char *word;
struct node *next;
};

Тогда ваш основной цикл должен выглядеть примерно так:

1) Read character data until delimiter into expandable buffer. Add NULL string terminator.
2) When delimiter is reached create node that points to buffer.
3) Insert NODE at HEAD of list.
4) When '.' is reached print each string starting from head of list.
1 голос
/ 19 ноября 2011

Вместо этого попробуйте эти циклы while [ИЗМЕНЕНО, чтобы отметить комментарий Криса о проверке конца LL]:

while (pos != NULL) {
    while (z != NULL) {
        // if you've reached the line feed or the end of the linked list
        if ((z->val == '\n') || (z->next == NULL)) {
            pos = z->next; // store list position just after this char for next time through
            break;
        }
        z = z->next;
    }
    while (z != NULL) {
        printf("%c", z->val);
        z = z->prev;
        // don't print more than just this word!:
        if ((z != NULL) && (z->val == '\n'))
            break;
    }
    // reset z for top inner while loop
    z = pos;
}

Основная проблема заключалась в том, что z не сбрасывался, когда внешний цикл while обернулся;вторая проблема заключалась в том, что конец связанного списка не выходил из первого внутреннего цикла while;Третья проблема заключалась во втором внутреннем, в то время как цикл не проверял конец слова, которое печатал.

Вам также нужно освободить связанный список в конце, иначе это будет утечка памяти.Вам также следует проверить возвращаемое значение calloc(), чтобы убедиться, что оно не возвращает ноль.

0 голосов
/ 10 мая 2013
#include<stdio.h>
#include<conio.h>
#include<malloc.c>
struct dnode{
int data;
struct dnode *prev,*next;
};
typedef struct dnode DNODE;
DNODE *first;
DNODE *last;

DNODE* createDnode(int ele){
DNODE *nnode;
nnode=(DNODE *)malloc(sizeof(DNODE));
nnode->data=ele;
nnode->next=NULL;
nnode->prev=NULL;
return nnode;    

}

//Insert First

DNODE *insertFirst(int ele){
DNODE *nnode;
nnode=createDnode(ele);
if(first==NULL){ //if node is creating first time
    first=last=nnode;
    return;    
}
nnode->prev=NULL;
nnode->next=first;
first=nnode;
return first;
} 

//Insert Last

DNODE *insertLast(int ele){
DNODE *nnode;
nnode=createDnode(ele);
if(first==NULL){ //if node is creating first time
    first=last=nnode;
    return;    
}
last->next=nnode;
nnode->prev=last;
last=nnode;
return last;    
}

 //Insert Before an Element

DNODE *insertBefore(int ele,int key){
DNODE *nnode,*curr,*pre;
nnode=createDnode(ele);
if(first==NULL){ //if node is creating first time
    first=last=nnode;
    return;    
}
if(first->data==key){  // if key is found at first node
    nnode->next=first;
    first=nnode; 
    return first;   
}
curr=first;
while(curr && curr->data!=key){
    pre=curr;
    curr=curr->next;   
}   
if(!curr){   //if search not found then curr will be NULL, it's means the node is added at last
    last->next=nnode;
    nnode->prev=last;
    last=nnode;
    return last;
}
    curr->prev->next=nnode;
    nnode->prev=curr->prev;
    nnode->next=curr;
    curr->prev=nnode;
    return;
  }

 // Insert After an Element

  DNODE *insertAfter(int ele,int key){
  DNODE *nnode,*curr,*pre;
  nnode=createDnode(ele);
  if(first==NULL){ //if node is creating first time
    first=last=nnode;
    return;    
}
curr=first;
while(curr && curr->data!=key){
    //pre=curr;
    curr=curr->next;   
}   
if(!curr){   //if search not found then curr will be NULL, it's means the node        is added at last
    last->next=nnode;
    nnode->prev=last;
    last=nnode;
    return last;
}
nnode->next=curr->next;
curr->next->prev=nnode;
nnode->prev=curr;
curr->next=nnode;
return;    

}

// Удалить функцию

int removeNode(int key){
DNODE *curr;
if(first==NULL){ //if node is creating first time
    printf("\n\nList is Empty");
    return -1;    
}
curr=first;
if(first->data==key){  //if first node has key
   first=first->next;
   first->prev=NULL;
   curr->next = NULL;
   free(curr);
   return;
}

while(curr && curr->data!=key){
    curr=curr->next;   
} 
if(!curr){   //if search not found then curr will be NULL, 
    return -1;
}

curr->prev->next=curr->next;
curr->next->prev=curr->prev;
curr->next = curr->prev = NULL;
printf("\n\n%d is Successfully Deleted: ",curr->data);
free(curr);
return;
}

void display(){
DNODE *curr;
if(first==NULL)
    printf("\n\nNothing to Display\n\n");
curr=first;
printf("\n\n\tElement in List\n\n\t");
while(curr){
    printf("%d ",curr->data);
    curr=curr->next;    
  }
 }
 main(){
int ele,ch,key;
do{
    printf("\nEnter Your Choice: \n");
    printf("1-Insert First\t2-Insert Last\n3-Insert Before\t4-Insert After\n5-Remove  \t6-Display\n");
    scanf("%d",&ch);
    switch(ch){
        case 1:
            printf("Enter Element To Insert: ");
            scanf("%d",&ele);
            insertFirst(ele);
            break;  
        case 2:
            printf("Enter Element To Insert: ");
            scanf("%d",&ele);
            insertLast(ele);
            break;
         case 3:
            printf("Enter Element To Insert: ");
            scanf("%d",&ele);
            printf("\nEnter Key: ");
            scanf("%d",&key);
            insertBefore(ele,key);
            break;  
        case 4:
            printf("Enter Element To Insert: ");
            scanf("%d",&ele);
            printf("\nEnter Key: ");
            scanf("%d",&key);
            insertAfter(ele,key);
            break; 
        case 5:
            printf("Enter Key to Delete: ");
            fflush(stdin);
            scanf("%d",&key);
            removeNode(key);
            break;
        case 6:
            display();
            break;
    }  
}while(ch!=7);
getch();
return 0;    

}

0 голосов
/ 21 ноября 2011

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

typedef struct L { 
    char val;
    struct L *next;
    struct L *prev;
} List;

List* insertList( char val, List *t1 ) {
    List *t = calloc(1, sizeof( List ));
    t->prev = NULL;
    t->val = val;
    t->next = t1;
    if (t1 != NULL)
        t1->prev = t;
    return t;
}

List* createList( void ) {
    List *h = NULL;
    char c;

    do {
        c =(char)getchar();
        h = insertList( c, h );
    } while (c != '.');

    return h;
}

void freeList( List *list ) {
    // free the linked list
    if (list != NULL) {
        freeList( list->next );
        free( list );
    }
}

int main( void ) {
    // create list
    List *head = createList();
    List *pos = head, *currentChar = NULL, *wordStart = NULL;

    while (pos != NULL)
    {
        // find next word
        wordStart = NULL;
        while (pos != NULL)
        {
            // gone past the beginning of a word yet?
            if ((pos->val == '\n') || (pos->next == NULL)) 
            {
                wordStart = (pos->next == NULL) ? pos : pos->prev; // note where this word starts
                pos = pos->next; // jump over \n, or go to end of list (null), for next time into this loop
                break; // jump out of this loop so we can output the word
            }
            else // not found end of word yet - on to next char
                pos = pos->next;
        }

        // have we found a word? if so, output it!
        if (wordStart != NULL)
        {
            currentChar = wordStart; // start at first char in the word
            while (currentChar != NULL)
            {
                printf( "%c", currentChar->val ); // output this char
                currentChar = currentChar->prev; // on to next char in the word
                if ((currentChar != NULL) && (currentChar->val == '\n')) 
                    break; // stop after last char of the word
            }
            // print the line-feed just before wordStart (if there is one)
            if (wordStart->next != NULL)
                printf( "%c", wordStart->next->val );
        }
        else // we've reached the end - stop
            break; // not really necessary - pos should be NULL at this point anyway
    }

    freeList( head ); // free linked list memory

    return 0;
}

Основное изменение - это способ вывода перевода строки.Я понял, что это НЕ перевод строки после каждого нужного вам слова, а тот, который ДО ТОГО, как он (не совсем логично - интересно, так ли это изначально предполагалось в вопросе?).Но теперь он выводит именно то, что вам нужно.И я добавил функцию для освобождения памяти связанного списка в конце тоже для вас.:)

...