zoukankan      html  css  js  c++  java
  • C/C++指针学习记录(二)

    上一篇: C/C++指针学习记录(一)

    1、指定定义的基本原则。

    我们在使用指针的时候,记住下面的准则可以很好的帮助我们节约修改程序的时间。

    • (1):永远清楚每一个指针指向了哪里,指针必须指向一块有意义的内存。
    • (2):永远清楚指针指向的对象的内容是什么。
    • (3):永远不要使用未初始化的指针变量。

    2、链表

    建立链表是我们学习数据结构的最基础的能力。链表这一块真的就是听懂容易,上手难。但是解决方法非常朴实,多敲就好!

    • (1):概念。
      官方定义:单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。


      可能看文字比较费力,那我们继续看一下概述图。




    其实就是,我们建立了一个结构体。这个结构体里面有两个部分,其一是 数据区 ,其二就是我们的 指针区 (里面存放的就是下一个结构体的地址)。
    假如我要定义一下关于学生成绩信息的结构体:

    typedef struct Student
    {
    	//数据区
    	char id[12];//学生学号
    	float Match;//数学成绩
    	float Chinese;//语文成绩
    
    	//地址区
        struct Student *next;//指向下一个学生信息结构体
    }
    

    上面的结构体就是我们链表里面最小的单位。接下来我们就要开始建立单链表。这里呢我们需要介绍一下头指针,对于整一张链表我们只需要知道指向第一个节点的地址,那么我们就可以通过遍历来获取整张表的信息。所以建立链表的时候不要忘记定义一个头指针。

    • 不用malloc()函数建立链表的可行性实验


      写链表的时候我们都会用到 <stdlib.h> 里面的 malloc() 动态分配内存的函数。但是突然有一天,我想到反正指针都是指向的地址,我可以直接定义一个变量并且初始化它。在把地址赋值给指针变量就可以了。
      插入函数代码如下:
    int insert(Stu *b)//指向链表的最后一个节点。
    {
    	Stu stu;
    	Stu *f;
    	scanf("%s %f %f",stu.id,&stu.Chinese,&stu.Match);//初始化
            if(stu.id!="EOF")
    	{
    		f=&stu;
    		f->next=NULL;
    		b->next=f;
                    //b=f;这一句没有办法修改参数b的值。就像传参里面的字节传值。
    		return 0;
    	}
    	else
    	{
    		return 1;
    	}
    }
    

    其实在先前一小会儿,我都觉得我的代码没有问题。可是,现在我知道我错了。虽然思想没有问题。但是代码是真的有问题。因为每次我插入新节点的时候,新建的节点对象。他在内存中的地址都被CPU分到了同一个地方,所以我的链表根本没有办法延长。并且非常尴尬的是,最后一个节点的地址变量指了自己。唯一的解决办法只有在每插入一个节点的时候都要重新声明一个节点变量,这样可能才能达到目的。但是这样做的话,我为什么不用数组呢?因为这样建立链表我也必须事先知道我需要定义多少个变量。

    • 使用malloc()函数建立链表
      主要代码:
    int insert(Stu *b)//指向链表的最后一个节点。
    {
    	Stu stu;
    	Stu *f;
    	char ch[]={"EOF"};
    	f=(Stu *)malloc(sizeof(Stu));//申请空间
    
    	scanf("%s %f %f",stu.id,&stu.Chinese,&stu.Match);//初始化
           if(stu.id[0]!=ch[0])
    	{
    		*f=stu;
    		f->next=NULL;
    		b->next=f;	
                    //b=f;这一句没有办法修改参数b的值。就像传参里面的字节传值。
    		return 0;
    	}
    	else
    	{
    		return 1;
    	}
    }
    

    现在讨论一下为什么我要注释掉: b=f 。原因就是传参数直接传值的原因。被传入参数仅仅只是把自己的内容传了进去,所有的操作都仅仅实在拥有相同内容的另一个变量下进行的。
    所以进行值传递就OK了。
    修改代码:

    int insert(Stu* &b)//
    {
    	Stu stu;
    	Stu *f;
    	char ch[]={"EOF"};
    	f=(Stu *)malloc(sizeof(Stu));//申请空间
    
    	scanf("%s %f %f",stu.id,&stu.Chinese,&stu.Match);//初始化
        if(stu.id[0]!=ch[0])
    	{
    		*f=stu;
    		f->next=NULL;
    		b->next=f; 
    		b=f;
    		return 0;
    	}
    	else
    	{
    		return 1;
    	}
    }
    

    当然传地址也是一样的,可以修改指针变量的内容。

    int insert(Stu* *b)//
    {
    	Stu stu;
    	Stu *f;
    	char ch[]={"EOF"};
    	f=(Stu *)malloc(sizeof(Stu));//申请空间
    
    	scanf("%s %f %f",stu.id,&stu.Chinese,&stu.Match);//初始化
        if(stu.id[0]!=ch[0])
    	{
    		//Stu *t=*b;
    		*f=stu;
    		f->next=NULL;
    		(*b)->next=f; 
    		*b=f;
    		return 0;
    	}
    	else
    	{
    		return 1;
    	}
    }
    

    好了指针的部分就到此结束!
    完整代码:

  • 相关阅读:
    括号序列的dp问题模型
    粉刷匠
    木棍加工
    物流运输
    最短路图
    DP基础(线性DP)总结
    离散化
    树链剖分
    NOIP2016 “西湖边超萌小松鼠” 模拟赛
    NOI导刊 2009 提高二
  • 原文地址:https://www.cnblogs.com/kadcyh/p/13793019.html
Copyright © 2011-2022 走看看