C 给定单链表的交替拆分

C 给定单链表的交替拆分,c,linked-list,C,Linked List,编写一个函数AlternatingSplit(),该函数接受一个列表并将其节点划分为两个较小的列表“a”和“b”。子列表应由原始列表中的交替元素组成。因此,如果原始列表是0->1->0->1->0->1,那么一个子列表应该是0->0->0,另一个子列表应该是1->1->1 有关问题的更多详情- 现在我编写了这段代码,它正在成功运行 #include<stdio.h> #include<stdlib.h> struct node { int num; nod

编写一个函数AlternatingSplit(),该函数接受一个列表并将其节点划分为两个较小的列表“a”和“b”。子列表应由原始列表中的交替元素组成。因此,如果原始列表是0->1->0->1->0->1,那么一个子列表应该是0->0->0,另一个子列表应该是1->1->1

有关问题的更多详情-

现在我编写了这段代码,它正在成功运行

#include<stdio.h>
#include<stdlib.h>
struct node
{
    int num;
    node *next;
};

node *start1 = NULL, *start2 = NULL, *start3 = NULL;

void push()
{
    node *temp = (node *)malloc(sizeof(node));
    printf("Enter number = ");
    scanf("%d", &temp->num);
    temp -> next = start1;
    start1 = temp;
}

void split()
{
    while(start1 != NULL)
    {
        node *temp1 = (node *)malloc(sizeof(node));
        temp1 ->num = start1 ->num;
        temp1->next = start2;
        start2 = temp1;
        start1 = start1 -> next;

        if(start1 != NULL)
        {
            node *temp2 = (node *)malloc(sizeof(node));
            temp2 ->num = start1 ->num;
            temp2->next = start3;
            start3 = temp2;
            start1 = start1 -> next;
        }
    }
}

int main()
{
    int n;
    scanf("%d", &n);

    while(n--)
        push();

    split();

    node *temp = start2;

    while(temp != NULL)
    {
        printf("%d  ", temp ->num);
        temp = temp ->next;
    }

    printf("\n");
    temp = start3;

    while(temp != NULL)
    {
        printf("%d  ", temp ->num);
        temp = temp ->next;
    }

    return 0;
}
#包括
#包括
结构节点
{
int-num;
节点*下一步;
};
节点*start1=NULL,*start2=NULL,*start3=NULL;
无效推送()
{
node*temp=(node*)malloc(sizeof(node));
printf(“输入number=”);
scanf(“%d”,&temp->num);
临时->下一步=开始1;
start1=温度;
}
无效拆分()
{
while(start1!=NULL)
{
node*temp1=(node*)malloc(sizeof(node));
temp1->num=start1->num;
temp1->next=start2;
start2=temp1;
start1=start1->next;
if(start1!=NULL)
{
node*temp2=(node*)malloc(sizeof(node));
temp2->num=start1->num;
temp2->next=start3;
start3=temp2;
start1=start1->next;
}
}
}
int main()
{
int n;
scanf(“%d”和“&n”);
而(n--)
推();
split();
节点*temp=start2;
while(temp!=NULL)
{
printf(“%d”,temp->num);
温度=温度->下一步;
}
printf(“\n”);
温度=start3;
while(temp!=NULL)
{
printf(“%d”,temp->num);
温度=温度->下一步;
}
返回0;
}
而随问题一并提交的守则是—

/*Program to alternatively split a linked list into two halves */
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>

/* Link list node */
struct node
{
    int data;
    struct node* next;
};

/* pull off the front node of the source and put it in dest */
void MoveNode(struct node** destRef, struct node** sourceRef) ;

/* Given the source list, split its nodes into two shorter lists.
If we number the elements 0, 1, 2, ... then all the even elements
should go in the first list, and all the odd elements in the second.
The elements in the new lists may be in any order. */

void AlternatingSplit(struct node* source, struct node** aRef, struct node** bRef) 
{
    /* split the nodes of source to these 'a' and 'b' lists */
    struct node* a = NULL; 
    struct node* b = NULL;

    struct node* current = source;

    while (current != NULL) 
    {
        MoveNode(&a, &current); /* Move a node to list 'a' */

        if (current != NULL) 
        {
            MoveNode(&b, &current); /* Move a node to list 'b' */
        }
    }

    *aRef = a;
    *bRef = b;

}

/* Take the node from the front of the source, and move it to the front of the dest.
It is an error to call this with the source list empty. 

Before calling MoveNode():
source == {1, 2, 3}   
dest == {1, 2, 3}

Affter calling MoveNode():
source == {2, 3}      
dest == {1, 1, 2, 3}      
*/

void MoveNode(struct node** destRef, struct node** sourceRef) 
{
    /* the front source node  */
    struct node* newNode = *sourceRef; 
    assert(newNode != NULL);

    /* Advance the source pointer */
    *sourceRef = newNode->next;

    /* Link the old dest off the new node */
    newNode->next = *destRef; 

    /* Move dest to point to the new node */
    *destRef = newNode; 
}

/* UTILITY FUNCTIONS */
/* Function to insert a node at the beginging of the linked list */

void push(struct node** head_ref, int new_data)
{
    /* allocate node */
    struct node* new_node = (struct node*) malloc(sizeof(struct node));

    /* put in the data  */
    new_node->data  = new_data;

    /* link the old list off the new node */
    new_node->next = (*head_ref);     

    /* move the head to point to the new node */
    (*head_ref)    = new_node;
}

/* Function to print nodes in a given linked list */

void printList(struct node *node)
{
    while(node!=NULL)
    {
        printf("%d ", node->data);
        node = node->next;
    }
} 

/* Drier program to test above functions*/
int main()
{
    /* Start with the empty list */
    struct node* head = NULL;
    struct node* a = NULL;
    struct node* b = NULL;  

    /* Let us create a sorted linked list to test the functions
    Created linked list will be 0->1->2->3->4->5 */
    push(&head, 5);
    push(&head, 4);
    push(&head, 3);
    push(&head, 2);
    push(&head, 1);                                    
    push(&head, 0);  

    printf("\n Original linked List:  ");
    printList(head); 

    /* Remove duplicates from linked list */
    AlternatingSplit(head, &a, &b); 

    printf("\n Resultant Linked List 'a' ");
    printList(a);            

    printf("\n Resultant Linked List 'b' ");
    printList(b);            

    getchar();

    return 0;

}
/*将链接列表拆分为两半的程序*/
#包括
#包括
#包括
/*链接列表节点*/
结构节点
{
int数据;
结构节点*下一步;
};
/*拔下源的前节点并将其放入dest*/
void MoveNode(结构节点**destRef,结构节点**sourceRef);
/*给定源列表,将其节点拆分为两个较短的列表。
如果我们对元素0,1,2。。。然后是所有偶数元素
应该放在第一个列表中,所有奇数元素放在第二个列表中。
新列表中的元素可以是任意顺序*/
void AlternatingSplit(结构节点*源,结构节点**aRef,结构节点**bRef)
{
/*将源节点拆分为这些“a”和“b”列表*/
结构节点*a=NULL;
结构节点*b=NULL;
结构节点*当前=源;
while(当前!=NULL)
{
MoveNode(&a,¤t);/*将节点移动到列表“a”*/
如果(当前!=NULL)
{
MoveNode(&b,¤t);/*将节点移动到列表“b”*/
}
}
*aRef=a;
*bRef=b;
}
/*从源的前面获取节点,并将其移动到dest的前面。
在源列表为空的情况下调用此函数是错误的。
在调用MoveNode()之前:
source=={1,2,3}
dest=={1,2,3}
在调用MoveNode()之后:
source=={2,3}
dest=={1,1,2,3}
*/
void MoveNode(结构节点**destRef,结构节点**sourceRef)
{
/*前端源节点*/
结构节点*newNode=*sourceRef;
断言(newNode!=NULL);
/*前进源指针*/
*sourceRef=newNode->next;
/*将旧dest链接到新节点*/
新建节点->下一步=*destRef;
/*移动dest以指向新节点*/
*desref=newNode;
}
/*效用函数*/
/*函数在链表的开头插入一个节点*/
无效推送(结构节点**head\u ref,int new\u数据)
{
/*分配节点*/
结构节点*新节点=(结构节点*)malloc(sizeof(结构节点));
/*输入数据*/
新建_节点->数据=新建_数据;
/*将旧列表链接到新节点*/
新建节点->下一步=(*head\u ref);
/*移动头部以指向新节点*/
(*head_ref)=新节点;
}
/*函数打印给定链表中的节点*/
无效打印列表(结构节点*节点)
{
while(节点!=NULL)
{
printf(“%d”,节点->数据);
节点=节点->下一步;
}
} 
/*用于测试上述功能的干燥器程序*/
int main()
{
/*从空列表开始*/
结构节点*head=NULL;
结构节点*a=NULL;
结构节点*b=NULL;
/*让我们创建一个排序的链表来测试函数
创建的链表将是0->1->2->3->4->5*/
推压(和头部,5);
推压(和头部,4);
推压(和头部,3);
推压(和头部,2);
推送(和头部,1);
推送(&头,0);
printf(“\n原始链接列表:”);
印刷品清单(标题);
/*从链接列表中删除重复项*/
交替裂缝(顶部、a和b);
printf(“\n结果链表‘a’”);
印刷品清单(a);
printf(“\n结果链表'b'”);
印刷品清单(b);
getchar();
返回0;
}
我的问题是,考虑到时间复杂度、空间复杂度和其他因素,这两个代码中哪一个更有效、更正确? 为什么?
详细的解释会更有帮助。

当您拆分一个链表时,您不需要任何内存分配,只需在指针周围随意移动就足够了

您的代码在拆分时进行内存分配,因此这样效率很低,模型应答代码要好得多

但更糟糕的是,你的代码会泄漏内存。它会丢失指向原始列表元素的指针,而不会释放它们。所以你的代码实际上是错误的,在一个坏的方面


要修复内存泄漏,这是一个实际的bug,您需要更改两个
start1=start1->next指向此的行:

node *tmp_next =  start1->next;
free(start1);
start1 = tmp_next;
对于其他更改,模型答案是一个很好的例子,但最重要的事情是:去掉额外的
malloc
调用,通过移动节点进行拆分,而不是分配新节点和复制数据(以及在上述错误修复后释放旧节点)。然后去掉全局变量,改为向函数中添加参数,如模型答案中所示
void split_in_evenodd(node *orig)
{
    if(!orig)
        return;

    node *e, *cur, *e_hd;

    e = orig->next; // point first even member
    e_hd = e; // keep a head pointer to even list

    if(!e) // covers the case of list with single element
        return;

    orig->next = e->next; // make orig skip the even node
    cur = orig->next; // cur moves to next odd node

    while(cur && cur->next) {
        e->next = cur->next; // even pointing to next even node
        e = e->next; // move even list forward

        cur->next = e->next; // update odds next
        cur = e->next;// move current forward (to next odd)
    }
}
#include <stdio.h>
#include <stdlib.h>
struct node *add_at_end(struct node *ptr,int item);
struct node{
int data;
struct node *next;
};

void main(){

struct node *head=malloc(sizeof(struct node));
head->data=1;
head->next=NULL;
// first node gets created
struct node *ptr=head;
//now we will add other nodes at the end

ptr=add_at_end(ptr,2);
ptr=add_at_end(ptr,3);
ptr=add_at_end(ptr,4);
ptr=add_at_end(ptr,5);
//the nodes get added to the linked list.Now let's print the data of all these nodes
ptr=head;
while(ptr!=NULL){
    printf("%d ",ptr->data);
    ptr=ptr->next;
}
printf("\n");
int count;
struct node *splitNode=malloc(sizeof(struct node));
struct node *forward=malloc(sizeof(struct node));
forward=head;

//now we will create the 1st split linked list
struct node *headll1=malloc(sizeof(struct node));
splitNode=forward;
forward=forward->next;
    headll1->data=splitNode->data;
    headll1->next=NULL;
    struct node *ptr1=headll1;
    count=1;
     
//now we will create the 2nd split linked list
struct node *headll2=malloc(sizeof(struct node));
splitNode=forward;
forward=forward->next;
    headll2->data=splitNode->data;
    headll2->next=NULL;  
    struct node *ptr2=headll2;
    count++;
    
//head nodes of both the split linked lists is ready    
while(forward!=NULL){
    splitNode=forward;
    forward=forward->next;
    count+=1;
    if(count%2==1){
      ptr1->next=splitNode;
      splitNode->next=NULL;
      ptr1=ptr1->next;
    }else{
      ptr2->next=splitNode;
      splitNode->next=NULL;
      ptr2=ptr2->next;
    }
}
//we have finished adding the nodes to linked list 1 and 2 alternatively based on count.

//now let's print both the linked lists.
ptr1=headll1;
while(ptr1!=NULL){
    printf("%d ",ptr1->data);
    ptr1=ptr1->next;
}
printf("\n");
ptr2=headll2;
while(ptr2!=NULL){
    printf("%d ",ptr2->data);
    ptr2=ptr2->next;
}


}
struct node *add_at_end(struct node *ptr,int item){
struct node *temp=malloc(sizeof(struct node));
temp->data=item;
ptr->next=temp;
temp->next=NULL;

return temp;
}