链表后半部分反转(2016亚信实习生笔试题)

题目(2016亚信实习生笔试题):
将链表后半部分反转,编写功能函数。函数头类似于本代码中reList()。
只记得一个大概了,具体规则在代码注释中提到了。

#define NULL 0
#include <stdio.h>
typedef struct LNode
{
    char value;
    struct LNode *next;
}LNode;

int initLi(LNode **head)//头插法
{
    LNode *th=*head;
    char c=getchar();
    while(c!='$')
    {
        if(c!=' ')
        {
             LNode *temp=malloc(sizeof(LNode));
            if(temp)
            {
                temp->value=c;
                temp->next=th;
                th=temp;
            }
            else
            {
                free(temp);
                return -1;
            }
        }
        c=getchar();
    }
    *head=th;
    return 0;
}

void visit(LNode **head)
{
    LNode *th=*head;
    for(LNode *p=th;p!=NULL;p=p->next)
    {
        printf("%c->",p->value);
    }
    printf("NULL\n");
}

/*
*regular
*1 2 3 4 5--1 2 5 4 3
*1 2 3 4-- 1 2 4 3
*/
LNode* reList(LNode *List)
{
    int n=0;
    for(LNode *p=List;p!=NULL;p=p->next)
    {
        ++n;
    }
    if(n%2)
    {
        n=(n+1)/2;//奇数个情况,如果有5个,则从第3个开始。
    }
    else
    {
        n/=2+1;//偶数个情况,如果有4个,则从第3个开始。
    }
    LNode *reHead,*flag;
    int i=0;
    for(LNode *p=List;p!=NULL;p=p->next)
    {
        ++i;
        if(i==n-1)
        {
            flag=p;
        }
        else if(i==n)
        {
            reHead=(LNode *)malloc(sizeof(LNode));
            reHead->next=NULL;
            reHead->value=p->value;
        }
        else if(i>n)
        {
            LNode *temp=(LNode *)malloc(sizeof(LNode));
            temp->value=p->value;
            temp->next=reHead;
            reHead=temp;
        }
    }
    delLi(&(flag->next));
    flag->next=reHead;
    return List;
}

void delLi(LNode **head)
{

    LNode *th=*head;
    for(LNode *temp=th;temp!=NULL;)
    {
        LNode *p=temp;
        temp=temp->next;
        free(p);
    }
    *head=NULL;
}
int main()
{
    LNode *head=NULL;
    if(initLi(&head))
    {
        printf("error\n");
        return 0;
    }
    printf("LinkedList\n");
    visit(&head);
    head=reList(head);
    printf("LinkedList which has dealt\n");
    visit(&head);
    delLi(&head);
    printf("hello world\n");
    return 0;
}

结果图:
链表后半部分反转(2016亚信实习生笔试题)_第1张图片
由于初始化用的头插法,所以创建时候倒序,并且加入了结束标志’$’。
下面是1 2 3 4

注:由于在笔试的时候这个题目半天没有调出来,很是气愤,所以就好好的折腾了一下,主要是实现功能函数,对于其余部分,随便加强了学习。水平有限,如果有更好的方法,可以随时交流。

2016.7.14更新

reList函数更改说明:之前的方法使用了额外的空间,现在进行修改,简洁化代码,减少空间复杂度。利用pre(初始化为空),cur指针进行链表指针修改。增加了空链表检查,结果测试正确。

/*
*regular
*1 2 3 4 5--1 2 5 4 3
*1 2 3 4-- 1 2 4 3
*/
LNode* reList(LNode *List)
{
    int n=0;
    for(LNode *p=List;p!=NULL;p=p->next)
    {
        ++n;
    }
    if(n==0)
    {
        return List;
    }
    else if(n%2)
    {
        n=(n+1)/2;//奇数个情况,如果有5个,则从第3个开始。
    }
    else
    {
        n=n/2+1;//偶数个情况,如果有4个,则从第3个开始。
    }
    LNode *flag,*pre=NULL,*cur=List,*nextNode;
    int i=0;
    while(cur!=NULL)
    {
        ++i;
        nextNode=cur->next;
        if(i==n-1)
        {
            flag=cur;
        }
        else if(i>=n)
        {
           cur->next=pre;
           pre=cur;
        }
        cur=nextNode;
    }
    flag->next=pre;
    return List;
}

你可能感兴趣的:(链表)