实现循环列表以及如何删除列表中的中间节点

时间:2018-12-17 15:48:47

标签: c list extract bidirectional circular-list

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

struct cir{

    int info;
    struct cir* next;

};

struct cir* create(int num){

    struct cir* temp;

    temp=(struct cir*)malloc(sizeof(struct cir));

    temp->info=num;
    temp->next=NULL;

    return(temp);
}


struct cir* insertlast(struct cir** head0, struct cir* new1){

    struct cir* temp;

    temp=(*head0);

    if(temp==NULL){

        new1->next=new1;

        return(new1);
    }

    else{

        while(temp->next !=(* head0) ){

            temp=temp->next;

        temp->next=new1;
        new1->next=(*head0) ; }

    }

    return(*head0);

}

void vizualize(struct cir* head0){

    struct cir* temp;

    temp=head0;

    printf("Lista:");

    while(head0->next != temp ){

        printf("[%d]-->", head0->info);
        head0 =head0 ->next;

    }

    printf("%d(testa)", head0->info);



}

int main(){

    struct cir* head;
    int i,n1,n2;
    struct cir* new1;


    printf("Insert the number of elements you want to put in  the list:\n\n");
    scanf("%d", &n1);

    for(i=0;i<n1;i++){

        printf("Insert the element you want to insert in the list:\n\n");
        scanf("%d", &n2);

        new1=create(n2);

        insertlast(&head,new1);
    }

    vizualize(head);

}

你好!我已经编写了这段代码来实现CIRCULAR列表,但是当我尝试运行该代码时,它就会崩溃。

我已经创建函数struct cir* create(int num)来创建单个元素,方法是调用函数struct cir* insertlast(struct cir** head0, struct cir* new1将元素插入循环列表中。

此外,为了保护双向列表:

 if(temp->next!=NULL){

        (temp->next)->prev=NULL;

做什么

(temp->next)->prev=NULL;

做什么?

最后一个问题,是否有人可以在此处编写代码以删除单向列表中间的元素? 我已经尝试过任何方法,但是每次我尝试删除一个元素时,程序都会崩溃,或者列表也以相同的方式变成Vizualize!

非常感谢!

ps。从列表中删除和提取元素之间的区别是什么?

2 个答案:

答案 0 :(得分:0)

这将起作用:

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

struct cir {
    int info;
    struct cir* next;
};

struct cir* create(int num) {

    struct cir* temp;

    temp = (struct cir*)malloc(sizeof(struct cir));

    temp->info = num;
    temp->next = NULL;

    return(temp);
}


struct cir* insertlast(struct cir* head0, struct cir* new1) {

    struct cir* last;

    if ( head0 == NULL ) {

        new1->next = new1;

        return new1;
    }
    else {
        last = head0;
        while (last->next != head0) {
            last = last->next;
        }

        last->next = new1;
        new1->next = head0;

        return head0;
    }
}

void vizualize(struct cir* head0) {

    struct cir* temp;

    if (head0) {
        temp = head0;

        printf("List:");

        do {
            printf("[%d]-->", temp->info);
            temp = temp->next;
        } while ( temp != head0 );
    }
}

int main() {

    struct cir* head;
    int i, n1, n2;
    struct cir* new1;

    head = 0;

    printf("Insert the number of elements you want to put in  the list:\n\n");
    scanf("%d", &n1);

    for (i = 0; i < n1; i++) {

        printf("Insert the element you want to insert in the list:\n\n");
        scanf("%d", &n2);

        new1 = create(n2);

        head = insertlast(head, new1);
    }

    vizualize(head);
}

请注意,我已经在c ++编译器(而不是c)上对其进行了测试。

  

是删除和提取元素之间的区别   从列表中?

提取意味着您可以从列表中删除元素并可以使用它。删除意味着您不仅可以从列表中删除,还可以释放内存。

答案 1 :(得分:0)

问题是insertlast函数。第一个问题是当有一个插入并且列表为空时(您还忘记了在主目录中将head初始化为NULL),因为您只是为新元素设置了“ next”指针,而没有使其成为新的head。列表。
然后,在滚动列表时,使用编写while循环的方式,循环直到找到插入点,然后退出而不进行任何操作。

这是该函数的正确工作版本:

struct cir* insertlast(struct cir** head0, struct cir* new1) {
    struct cir* temp;
    temp = (*head0);
    if(temp == NULL) {
        new1->next = new1;
        *head0 = new1;
        return(*head0);
    }
    else {
        while(temp->next != (*head0)) {
            temp = temp->next;
        }

        temp->next = new1;
        new1->next = (*head0);

    }
    return(*head0);
}

关于

的含义
(temp->next)->prev=NULL;

在双向列表中,它将“ temp”指向的节点设置为NULL,因为从“ temp”开始,您将转到下一个元素,然后再转到上一个元素,这与开始位置相同(假定“ next”和“ prev”已正确设置。

最后,要从单向列表中删除元素,您必须在要删除和重新排列指针之前停在该元素上:

while(temp->next->info != target){
      temp=temp->next
}
struct circ* node_to_delete = temp->next;
temp->next = node_to_delete->next;
free(node_to_delete);

我认为提取和删除之间没有明确定义的区别,但是通常我会在提取元素而不将其从列表中删除时考虑提取。