zoukankan      html  css  js  c++  java
  • 啊哈,算法自学记——4th

    链表

    有一串已经从小到大排好序的数 2 3 5 8 9 10 18 26 32。现需要往这串数中插入 6 使其得到的新序列仍符合从小到大排列。
    先回顾下指针:(主要是我不太了解…)

    int *p;
    

    指针有什么作用呢?
    答案是:存储一个地址。确切地说是存储一个内存空间的地址。严格地说这里的指针 p 也只能存储“一个存放整数的内存空间”的地址,因为在定义的时候我们已经限制了这一点(即定义的时候*p 的前面是 int)。
    当然你也可以定义一个只能用来存储“一个存放浮点数的内存空间”的地址,如:

    double *p;
    

    整型指针 p 如何才能存储整型变量 a 的地址呢?

    p=&a;//&取地址符
    

    有什么用呢?用处就是我们可以用指针 p 来操作变量 a 了。比如我们可以通过操作指针 p 来输出变量 a 的值:

    #include <stdio.h>
    int main()
    {
    	int a=10;
    	int *p; //定义个指针p
    	p=&a; //指针p获取变量a的地址
    	printf("%d",*p); //输出指针p所指向的内存中的值
    	return 0;
    }
    

    MALLOC函数:
    malloc 函数的返回类型是 void * 类型。 void * 表示未确定类型的指针。在 C和 C++中, void * 类型可以强制转换为任何其他类型的指针。

    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {
    	int *p; //定义一个指针p
    	p=(int *)malloc(sizeof(int)); //指针p获取动态分配的内存空间地址
    	*p=10; //向指针p所指向的内存空间中存入10
    	printf("%d",*p); //输出指针p所指向的内存中的值
    	return 0;
    }
    

    链表每一个结点都由两个部分组成。
    左边的部分用来存放具体的数值,那么用一个整型变量就可以;
    右边的部分需要存储下一个结点的地址,可以用指针来实现

    #include <stdio.h>
    #include <stdlib.h>
    
    //创建一个结构体来表示链表的结点类型
    typedef struct node
    {
        int data;
        struct node *next;  
    };
    
    
    int main(int argc, char const *argv[])
    {
        struct node *head,*p,*q,*t;
        int n,a;
    
        printf("Input the num of data:
    ");
        scanf("%d",&n);
    
        head=NULL;//头指针指向空
    
        printf("Input the data:
    ");
        for (int i = 0; i < n; i++)
        {
            scanf("%d",&a);
            //动态申请一个内存,用来存放一个结点,并用临时指针指向这个结点
            p=(struct node *)malloc(sizeof(struct node));
            /*->叫做结构体指针运算符,也是用来访问结构体内部成员的。
            因为此处 p 是一个指针,所以不能使用.号访问内部成员,而要使用->*/
            p->data=a;//将数据存储到当前结点的数据域中
            p->next=NULL;//设置当前结点的后继指针为空,也就是当前结点的下一个结点为空
            if (head==NULL)//
            {
                head=p;//如果这是第一个创建的结点,则将头指针指向这个结点
            }
            else
            {
                q->next=p;//如果不是第一个创建的结点,则将上一个结点的后继指针指向当前结点
            }
            q=p;//指针q也指向当前结点    
        }
        
        /*插入新的结点*/
        printf("Input the num of insert:
    ");
        scanf("%d",&a);
    
        t=head;//
        while (t!=NULL)//遍历链表
        {
            if(t->next->data > a)//如果下一个结点的数据大于插入的数
            {
                p=(struct node *)malloc(sizeof(struct node));//动态申请
                p->data=a;//存入数据
                p->next=t->next;//新增指针的后继指针指向当前结点的后继指针所指向的结点。。。晕
                t->next=p;//当前结点的后继指针指向新增结点
                break;//插入完毕,退出
    
            }
            t=t->next;
        }
        
    
        //输出链表中的所有数
        t=head;
        while (t!=NULL)
        {
            printf("  %d",t->data);
            t=t->next;
        }
        free(p);
        return 0;
    }
    
    

    在这里插入图片描述

    **

    模拟链表:

    **
    如果你觉得上一节的代码简直是天书,或者你压根就很讨厌指针这些东西,没关系!链表还有另外一种使用数组来实现的方式,叫做模拟链表,我们一起来看看

    链表中的每一个结点只有两个部分。我们可以用一个数组 data 来存储每序列中的每一个数。那每一个数右边的数是谁,这一点该怎么解决呢?上一节中是使用指针来解决的,这里我们只需再用一个数组 right 来存放序列中每一个数右边的数是谁就可以了,具体怎么做呢?

    在这里插入图片描述
    上图的两个数组中,第一个整型数组 data 是用来存放序列中具体数字的,另外一个整型数组 right 是用来存放当前序列中每一个元素右边的元素在数组 data 中位置的。例如 right[1]的值为 2,就表示当前序列中 1 号元素右边的元素存放在 data[2]中;如果是 0,例如right[9]的值为 0,就表示当前序列中 9 号元素的右边没有元素。

    看完就晕了,说说我自己的理解:
    简单来说就是把上面链表的地址用数组下标来表示,用另一个数组来存放数据数组中的数对应的下标,也即链表中的后继指针,有理解错的地方,希望有心人能给我指正下。

    #include <stdio.h>
    
    int main(int argc, char const *argv[])
    {
        int data[101],right[101];
        int n,t,len;
        printf("Input the num of data:
    ");
        scanf("%d",&n);
    
        printf("Input the data:
    ");
        for (int i = 1; i <= n; i++)
        {
            scanf("%d",&data[i]);
        }
        len=n;
        //初始化right数组
        for (int i = 1; i <= n; i++)
        {
            if(i!=n)
                right[i]=i+1;
            else
                right[i]=0;
        }
        
        //在data末尾加上一个数据
        len++;
        printf("Input the num of insert:
    ");
        scanf("%d",&data[len]);
    
        //从链表的头部开始遍历
        t=1;
        while (t!=0)
        {
           if (data[right[t]]>data[len])//如果当前结点的下一个结点的数大于待插入的数据,将数插入到中间
           {
                right[len]=right[t];//新插入数的下一个结点标号等于当前结点的下一个编号
                right[t]=len;//当前结点的下一个节点编号就是新插入书的结点编号
                break;
           }
           t=right[t];
        }
        //打印
        t=1;
        while (t!=0)
        {
            printf(" %d",data[t]);
            t=right[t];
        }
        
        return 0;
    }
    
    

    在这里插入图片描述

  • 相关阅读:
    【视频剪辑】 Land of Dreams 航拍中国新疆篇 剪辑
    【视频剪辑】 2018年中国海空军掠影
    【视频剪辑】 成都雅安旅行vlog
    【PL/SQL】 学习笔记 (3)if 语句使用
    【PL/SQL】 学习笔记 (2)引用型变量和记录型变量
    dubbo远程方法调用的基本原理
    java8中的接口与时间操作
    接入天猫精灵auth2授权页面https发送ajax请求
    java8 流操作
    Lambda表达式和方法引用
  • 原文地址:https://www.cnblogs.com/hhsxy/p/14018431.html
Copyright © 2011-2022 走看看