链表

讨论链表之前先看一个数组模拟的链表

struct s

{

 Int v;

 Int next;

}a[1000];

其中v就是值,而next是下一个值所存储的位置的下标

如果存在一条链是a[0]->a[4]->a[2]

那么a[0].next=4,a[4].next=2

 

而真正的链表与上面的区别就是可以动态开空间,因为数组的大小是直接开好的,所以容易出现浪费

struct s

{

    int v;

    s *next;

};

其中v存这个点的值,next是下一个值所存储的位置的地址

 

然后就是如何定义了,由于每个点都是用的时候才开辟,所以就用指针来存储地址即可

Struct s *p;

动态开辟地址可以用mallocnew(据说区别是占用空间不一样,我只会malloc

p=(struct s *)malloc(sizeof(s));

这样p就指向了一个新定义的结构体

 

接下来就是如何创建链表了

首先链表开始分为头结点和头指针

头指针存储的就是第一个点的地址

头结点是在第一个点之前定义了一个结构体,这个结构体的next才是第一个节点的地址

而他的值域v通常存储有多少个节点

 

插入一般分为两种方式

头插法,尾插法(我比较喜欢头插法)

头插法

每次把新的点放在开头,只需要把本个节点的next指向第一个节点,然后本个节点就可以当做第一个节点了

尾插法

需要一直记录最后一个点在哪里,插入的时候,把最后一个节点的next指向本个节点即可

 

一般来说最后一个节点的next都要存NULL

所以遍历的时候只需要while(p!=NULL)一直循环即可

 

 

 

有个比较有锻炼的题,可以试试

有一个链表,其中奇数位置取出来单调递增,偶数位置取出来单调递减(可以自己建立,奇数是i,偶数是n-i),让你把整个链表变成单调递增的

 

#include<stdio.h>
#include<malloc.h>
#include<algorithm>
using namespace std;
struct s
{
    int v;
    s *next;
};
void create(s *p,int n)
{
    for(int i=1; i<=n; i++)
    {
        p->next=(struct s*)malloc(sizeof(s));
        p=p->next;
        p->next=NULL;
        if(i%2)
            p->v=i;
        else
            p->v=n-i;
    }
}
void print(s *p)
{
    while(p!=NULL)
    {
        printf("%d\n",p->v);
        p=p->next;
    }
    printf("---------------------------------------\n");
}
int main()
{
    int n;
    scanf("%d",&n);
    s *head,*p;
    head=(struct s*)malloc(sizeof(s));
    head->v=n;
    head->next=NULL;
    create(head,n);
    printf("输出原始链表\n");
    print(head->next);
    s *head1=NULL,*head2=NULL,*p1,*p2;
    p=head->next;
    int z=1;
    while(p!=NULL)
    {
        if(z)
        {
            if(head1==NULL)
                head1=p;
            else
                p1->next=p;
            p1=p;
            p=p->next;
            p1->next=NULL;
        }
        else
        {
            if(head2==NULL)
                head2=p;
            else
                p2->next=p;
            p2=p;
            p=p->next;
            p2->next=NULL;
        }
        z^=1;
    }
    printf("分别输出两个链表\n");
    print(head1);
    print(head2);
    p2=head2->next;
    head2->next=NULL;
    while(p2!=NULL)
    {
        p=p2;
        p2=p2->next;
        p->next=head2;
        head2=p;
    }
    printf("输出翻转后的2链表\n");
    print(head2);
    s *head3=NULL;
    while(head1!=NULL||head2!=NULL)
    {
        if(head2==NULL||(head1!=NULL&&head1->v<head2->v))
        {
            if(head3==NULL)
                head3=head1;
            else
                p->next=head1;
            p=head1;
            head1=head1->next;
        }
        else
        {
            if(head3==NULL)
                head3=head2;
            else
                p->next=head2;
            p=head2;
            head2=head2->next;
        }
    }
    printf("输出合并以后的链表\n");
    print(head3);
}

 

做法就是

先根据奇数偶数位置,把链表拆成两个

然后把偶数位置反转过来(把这个链表一直头插到一个空的链表就反转成功了)

然后每次都取两个链表当前没取过,且最小的尾插到答案的链表中即可

posted @ 2018-12-25 18:03  注册以后还能改吧  阅读(175)  评论(0编辑  收藏  举报