调用move函数(让小于0 的排在大于0的之前)后,printf和DispList不输出

题目:某非空单链表L中所有元素为整数,设计一个算法将所有小于零的节点移到所有大于等于零的节点的前面
问题:为什么调用move函数后,第二个DispList函数不输出,第二个printf也不输出。
提示:L1是不带头节点的,这样可以直接连到L最后一个结点的后面

#include<stdio.h>
#include<malloc.h>
typedef int ElemType;
typedef struct Lnode
{
    int data;
    struct Lnode *next; 
}LinkNode;
void InitList(LinkNode *&L)
{
    L=(LinkNode *)malloc(sizeof(LinkNode));
    L->next=NULL;
}
void CreatList(LinkNode *&L,int a[],int n)
{
    LinkNode *s;
    L=(LinkNode *)malloc(sizeof(LinkNode));
    L->next=NULL;
    for(int i=0;i<n;i++)
    {
        s=(LinkNode *)malloc(sizeof(LinkNode));
        s->data=a[i];
        s->next=L->next;
        L->next=s;
    }
}
void DispList(LinkNode *L)
{
    LinkNode *p=L->next;
    while(p!=NULL)
    {
        printf("%d ",p->data);
        p=p->next;
    }
}
void move(LinkNode *&L)
{
    LinkNode *L1,*r=L,*r1,*p=L->next;
    L1=NULL;
    L->next=NULL;
    while(p!=NULL)
    {
        if(p->data>0)
        {
            if(L1->next==NULL)
             {L1=p;r1=p;}
            else
             {r1->next=p;
              r1=p;}
        }
        else
        {
            r->next=p;
            r=p;
        }
        p=p->next;
    }
    r->next=r1->next=NULL;
    r->next=L1;
} 
int main()
{
    LinkNode *L;
    int a[5];
    InitList(L);
    printf("请输入:");
    for(int i=0;i<5;i++)
    {
        scanf("%d",&a[i]);
    }
    CreatList(L,a,5);
    printf("请输出:");
    DispList(L);
    move(L);
    printf("移动后请输出:");
    DispList(L);
}

img

修改如下,改动处见注释,供参考:

#include<stdio.h>
#include<malloc.h>
typedef int ElemType;
typedef struct Lnode
{
    int data;
    struct Lnode *next;
}LinkNode;
void InitList(LinkNode *&L)
{
    L=(LinkNode *)malloc(sizeof(LinkNode));
    L->next=NULL;
}
void CreatList(LinkNode *&L,int a[],int n)
{
    LinkNode *s;
    //L=(LinkNode *)malloc(sizeof(LinkNode)); 修改
    //L->next=NULL;                           修改
    for(int i=0;i<n;i++)
    {
        s=(LinkNode *)malloc(sizeof(LinkNode));
        s->data=a[i];
        s->next=L->next;
        L->next=s;
    }
}
void DispList(LinkNode *L)
{
    LinkNode *p=L->next;
    while(p!=NULL)
    {
        printf("%d ",p->data);
        p=p->next;
    }
    printf("\n");
}
void move(LinkNode *&L)
{
    LinkNode *L1=NULL,*r=NULL,*r1=L,*p=L->next;  //L1=NULL;修改
    L->next=NULL;
    while(p!=NULL)
    {
        r = p;          //修改
        p = p->next;    //修改
        r->next = NULL; //修改
        if(r->data >= 0)//修改
        {
            r->next = L1;//修改
            L1 = r;      //修改
        }
        else
        {
            r1->next = r;//修改
            r1 = r;      //修改
            //r->next = p;
            //r = p;
        }
            //p = p->next;
    }
            //r->next=r1->next=NULL;
    r1->next = L1;  //修改  r->next=L1;
}
int main()
{
    LinkNode *L;
    int a[5];
    InitList(L);
    printf("请输入:");
    for(int i=0;i<5;i++)
    {
        scanf("%d",&a[i]);
    }
    CreatList(L,a,5);
    printf("请输出:");
    DispList(L);
    
    move(L);
    printf("移动后请输出:");
    DispList(L);

    return 0;
}

问题出在这行代码: L1=NULL;,L1在这里被初始化为空指针,所以第一次使用它时会访问空指针,导致程序崩溃。

为了解决这个问题,应该在初始化L1之前为它分配内存,例如:

LinkNode *L1 = (LinkNode *)malloc(sizeof(LinkNode));
L1->next = NULL;

这样就能保证L1是一个有效的指针。

另外,在函数move中,需要在移动元素之后,将最后一个小于零的节点的next指针设置为NULL,防止链表循环,代码如下:


void move(LinkNode *&L)
{
    LinkNode *L1,*r=L,*r1,*p=L->next;
    L1= (LinkNode *)malloc(sizeof(LinkNode));
    L1->next=NULL;
    L->next=NULL;
    while(p!=NULL)
    {
        if(p->data>0)
        {
            if(L1->next==NULL)
             {L1=p;r1=p;}
            else
             {r1->next=p;
              r1=p;}
        }
        else
        {
            r->next=p;
            r=p;
        }
        p=p->next;
    }
    r->next=L1;
    r1->next=NULL;
}