zoukankan      html  css  js  c++  java
  • 链表

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

    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
    ",p->v);
            p=p->next;
        }
        printf("---------------------------------------
    ");
    }
    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("输出原始链表
    ");
        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("分别输出两个链表
    ");
        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链表
    ");
        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("输出合并以后的链表
    ");
        print(head3);
    }

    做法就是

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

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

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

  • 相关阅读:
    大数据内存模型(二级指针)
    多线程函数指针
    返回函数指针的函数
    动态分配二维数组指针
    俄罗斯方块学习笔记
    tailf
    tail
    cut
    split
    paste
  • 原文地址:https://www.cnblogs.com/lmhyhblog/p/10175573.html
Copyright © 2011-2022 走看看