C language: essay 8-structure

When learning, we need to know why we use structures?

Because sometimes it is necessary to combine (encapsulate) different types of data into an organic whole for easy reference. (For example, a class is to encapsulate methods and properties, and the structure here is to encapsulate different variables)

For example, a student has attributes such as student ID/name/age/address

int num;
char name[20];
char sex;
int age;
char addr[30];

1. Structure

The general form of defining a structure is:

struct 结构名
{
   成员列表
};
//成员列表由若干个成员组成,每个成员都是该结构的一个组成部分。对每个成员也必须作类型说明,其形式为:
类型说明符 成员名;//int num;


//比如:定义的student学生类他有6个属性
struct stucent
{
   int num;
   char name[20];
   char sex;
   int age;
   float score;
   char addr[30];

};

The following three methods can be used to define structure type variables:

(1) Declare the structure type first and then define the variable name:

//比如:定义的student学生类他有6个属性
struct stucent//struct 结构体名
{
   int num;
   char name[20];
   char sex;
   int age;
   float score;
   char addr[30];//成员表列

};
struct student  student1,student2;//类型名 结构体  变量名,变量名
//定义了student1和student2为struct student类型的变量,即他们具有struct student类型的结构。

(2) Define variables while declaring the type

/比如:定义的student学生类他有6个属性
struct stucent
{
   int num;
   char name[20];
   char sex;
   int age;
   float score;
   char addr[30];

}student1,student2//变量名列表
//在定义结构体变量后,系统会为之分配内存单元。例如studet1和student2在内存中各占?子节
(4+20+1+4+4+30=67)

(3) Directly define structure type variables

//即不出现结构体名
struct
{
   成员表列
}变量名表列;

Nested definition of structure (structure inside structure)

on one name sex age birthday addr
Month day year

First, the structure data should be defined, consisting of Month (month), day (day), year (year), and three members.

When the variables boy1 and boy2 are defined and explained, the birthday of the member is explained as a data structure type. The member name can have the same name as other variables in the program without interfering with each other. (Because their scope is different)

//结构的嵌套
struct data
{
   int month;
   int day;
   int year;
};

struct
{
int num;
char name[20];
char sex;
struct data birthday;
float score;
}boy1,boy2={102,“jane”,'M',98.5};//结构体变量初始化,对变量赋值(有点像数组)
boy1=boy2;//将boy2的值给了boy1,全体成员copy

//如果对boy1使用点"."运算符进行了赋值操作的话,那么boy2=boy1;(将boy1的全体成员赋值给了boy2)这个语句就可以把boy1里边成员变量的值直接都赋值给boy2的成员变量,因此Boy2不用再一个个的进行赋值。

After defining the structure variable, you can of course refer to this variable. Should comply with:

(1) A structure variable cannot be input and output as a whole.

The dot "." member operator should be used.

//比如打印student1中的各个变量的值时,我们不可以直接
printf("%d,%s,%c,%d,%f,%\n",student1);

//正确引用结构体变量中成员的方式为:
//结构体变量名.成员名//点操作符来进行引用
//student1.num//表示student1变量中的num成员。
//student1.num=100;//可以对变量的成员赋值

"." is a member (component) operator, which has the highest priority among all operators, so you can treat student1.num as a whole. The above assignment statement is to pay the integer 100 to the member num in the student1 variable.

It is also not possible to use the following statement to read the structure variable as a whole: (to be accurate to each level at the bottom of it)

scanf("%d,%s,%c,%d,%f,%s",&student1);

(2) If the member itself belongs to a structure type, several member operators are used to find the lowest and member level by level. Only the lowest-level members can be assigned or accessed and operated on.

For the structure variable student1 defined above, each member can be accessed like this:

student1.num
student1.birthday.month//因为birthday也是一个结构的变量名,他不能代表全体成员,我要再点进去,访问到最下级,最下级才有操作的权力。

(3) The members of structure variables can perform various operations like ordinary variables (the operations that can be performed are determined according to the type).

(4) You can refer to the address of the structure variable member (&boy1.num) or the address of the structure variable (&boy1) . (&Boy1 and &boy1.num their two addresses are the same, similar to an array)

The address of the structure variable is mainly used as a function parameter to pass the address of the structure variable. (Actually, the address of the first element is fine, but the address of the structure variable is generally used. The name is more representative)

Two, structure array

A structure variable can store a set of data (such as a student's student ID, name, grades, etc.). If there are 10 students' data to be calculated, obviously an array should be used, which is a structure array.

The structure array is different from the numerical arrays introduced before. It points out that each array element is a structure type data, and they all include each member (component) item.

The following is an example of an address book to illustrate:

#include<stdio.h>
#include<stdlib.h>
#define NUM 3

struct person//定义person结构
{
   char name[20];
   char phone[10];
};
void main()
{
   struct person man[NUM];//定义man数组,结构体数组,有三个元素
   int I;
   for(I=0;i<NUM;i++)//一个元素包含了两个项分别是name和phone。
   {
      printf("input name:\n");
      gets(man[i].name);
      printf("input phone:\n");
      gets(man[i].phone);
   }
   printf("\tname\t\t\t\t\tphone\n\n");
   for(i=0;i<NUM;i++)
   {
      printf("%20s\t\t\t%20s\n",man[i],name,man[i].phone);
   }
   system("pause")
}

Definition of structure array:

//第一种定义方法
struct stucent
{
   int num;
   char name[20];
   char sex;
   int age;
   float score;
   char addr[30];

};
struct student student[3];//定义了一个数组有三个元素,这个数组名称叫student,有三个元素,每一个元素都有上述6个项

//第2种定义方法
struct stucent
{
   int num;
   char name[20];
   char sex;
   int age;
   float score;
   char addr[30];

}studet[3];

Initialization of structure array:

struct stucent
{
   int num;
   char name[20];
   char sex;
   int age;
   float score;
   char addr[30];

}stu[2]={
            {101,“Li”,'M',18,87.5,"Beijing"},
            {102,“zhang",'F',19,99,"Shanghai"}
        
        };

//或者也可以用以下形式初始化:
struct student
{
   int num;
   ...
};
student student str[]{
   
   {...},{...},{...}};
//即先声明结构体类型,然后定义数组为该结构体类型,再定一数组是初始化。

Example question: the statistical procedure for the candidates' votes. There are 3 candidates. Each time you enter the name of the candidate who has received the votes, you are required to output the results of each vote. And output the highest voter.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define NUM 5
struct person
{
      char name[20];
      int count;
}candidate[NUM] = {
                  {"A", 0},
                  {"B", 0}, 
                  {"C", 0},
                  {"D", 0}, 
                };//定义结构体数组

char *winner();

int main()
{
      int i, j;
      char candidate_name[20];

      printf("欢迎进入2020年火爆网站评选系统:\n\n");
      printf("选择项目:A,B,C,D \n\n");
      
      for( i=1; i <= 6; i++ )
      {
            printf("第 %2d 位投票, 请选择支持的候选人: ", i);
            scanf("%s", candidate_name);
            for( j=0; j < NUM; j++ )//j小于5,所以j只能到4,因为有4个A,B,C,D
            {
                  if( 0 == strcmp(candidate_name, candidate[j].name) )
                  {
                        candidate[j].count++;
                  }
            }
      }
      printf("\n");

      for( i=0; i < 5; i++ )//打印ABCD分别的得票数
      {
            printf("%s 得票数为: %d\n", candidate[i].name, candidate[i].count );
      }
      printf("\n");
      printf("本次评选活动的胜利者的: %s\n", winner() );//调用winner()函数,比较得票最高的是谁

      printf("\n");
      system("pause");
}

char *winner()
{
      int i =0 , winner = i;//相当于winner=0
      
      for( i=1; i < NUM; i++ )
      {
            if( candidate[winner].count < candidate[i].count )//结构体数组的第一个元素的count项依次与后边的元素的count项比较比较
            {
                  winner = i;
            }
      }
      
      return candidate[winner].name;
}

----Pointer to structure type data---

The pointer of a structure variable is the actual address of the memory segment occupied by the structure variable. (A pointer is a variable that stores an address)

You can set a pointer variable to point to a structure variable. At this time, the value of the pointer variable (that is, an address) is the starting address of the structure variable. (The pointer is really great, whatever it means)

Pointer variables can also be used to point to elements in structure arrays.

The general form of structure pointer variables:

struct  结构名  *结构指针变量名//*表示他是指针
//例如前面定义的stu这个结构,说明一个指向stu的指针变量名pstu,可以写为:
struct  stu  *pstu;//*表示它是一个指针,stu表示他是哪一个结构的指针。
//当然也可以在定义stu结构时同时说明pstu。与前面讨论的各类指针变量相同,结构指针变量也必须要先赋值后才能使用。(不然就是个无头案)

//Assignment is to assign the first address of the structure variable to the pointer variable, and the structure name cannot be assigned to the pointer variable.

The structure name and the structure variable name are not the same thing (one is student and the other is boy1). E.g

//如果boy是被说明为stu类型的结构变量,则:
struct stu//结构为stu
{
   ...
}boy={...,...,...,};//结构变量为boy,并同时赋初值
//(还可以结构变量名再有一个girl,不止一个boy了这次,所以再声明一个指针指向girl就好了,访问方式跟下边雷同)
struct  stu  *pstu;//*表示它是一个指针,stu表示他是哪一个结构的指针。//定义结构变量指针
pstu=&boy;//是正确的//将boy的初始值地址给了它
(*pstu).name//正确;
(*pstu)->name//正确;
boy.name//正确//通过三种形式可以输出
pstu=&stu;//是错误的
//为什么呢???
//因为结构名stu和结构变量boy是两个不同的概念,不能混淆,结构名只能表示一个结构形式,编译系统并不对它分配内存空间。
//只有当某变量被说明定义为这种类型的结构时,才对该变量分配存储空间。在定义时操作系统才会为它分配空间。只是说明没定义不分配空间。
//因此上面&stu这种写法是错误的,不可能去取一个结构名的首地址。(因为结构名本来是有地址的,他只是让编译器知道,编译器在编译时会申请空间)有了结构指针变量,就能更方便的访问结构变量的各个成员。

//其访问的一般形式为:
(*结构指针变量).成员名
//或者:
结构指针变量->成员名
//例如:
(*pstu).num
//或者:
pstu->num

Example: Application of pointer variable pointing to structure variable (output in the above three forms).

Three, structure pointer variables as function parameters

There are three ways to pass the value of a structure variable to another function:

(1) Use members of structure variables as parameters.

(2) Use structure variables as actual parameters. (Use the name of the structure variable as the actual parameter)

(3) Use the pointer to the structure variable (or array) as the actual parameter, and pass the address of the structure variable (or array) to the formal parameter.

Example: There is a structure variable stu, which contains student ID, name and grades of three courses. They are output by calling the function print.

(The requirement is to use structure variables as function parameters (pass to it as actual parameters) (2))

This example is to copy the entire structure, because void print (struct student); the parameter here is the entire structure variable. (Pass by value)

#include<stdio.h>
#include<string.h>
struct student//定义结构
{
   int num;
   char name[20];//字符串,(name[20]出现在栈里面,实实在在的空间,而下面的“zhangsan字符串出现在数据常量区”//改变为char *name;的话下边的语句stu.name="zhangsan";是将数据区常量的地址传递给name这个指针而已。
   float score[3];//浮点型数组
};
void print(struct student);//函数的参数是这个结构体,一个结构体作为他的形参
void main()
{
   struct student stu;//定义这个结构体变量的名称为stu
   stu.num=8;
   strcpy(syu.name,"zhangsan");//如果用stu.name="zhangsan";这个语句会错误(复制号的左边必须是一个左值l-value(可以简单的理解l-value就是一个地址,必选是一个指针所以上边就必须改一下定义为char *name;这样的话这句话就没有错误了)),
   stu.score[0]=98.2;
   stu.score[1]=93.2;
   stu.score[2]=98.7;//分别赋值
   print(stu);//把结构体变量作为实参传递给他
}
void print(struct student stu)//print这个函数知道了结构体变量的位置就能够索引到他的名称学号成绩并分别打印
{
    printf("\tnum      :%d\n",stu.num);
    printf("\tname      :%s\n",stu.name);
    printf("\tscore_1      :%5.2f\n",stu.score[0]);
    printf("\tscore_2      :%5.2f\n",stu.score[1]);
    printf("\tscore_3      :%5.2f\n",stu.score[2]);
    printf("\n")
}

(Requires pointers to structure variables as actual parameters (3))

In the second method, only an address is copied, so in terms of efficiency, it is the second method that transmits less. (Passage)

#include<stdio.h>
#include<string.h>
struct student//定义结构
{
   int num;
   char name[20];//字符串,(name[20]出现在栈里面,实实在在的空间,而下面的“zhangsan字符串出现在数据常量区”//改变为char *name;的话下边的语句stu.name="zhangsan";是将数据区常量的地址传递给name这个指针而已。
   float score[3];//浮点型数组
};
void print(struct student *);//函数的参数是指针
void main()
{
   struct student stu;//定义这个结构体变量的名称为stu
   stu.num=8;
   strcpy(syu.name,"zhangsan");
   stu.score[0]=98.2;
   stu.score[1]=93.2;
   stu.score[2]=98.7;//分别赋值
   print(&stu);//因为上边是指针,指针必须接收一个地址嘛,所以这里传递给他的那就是这个结构体的地址了
}
void print(struct student *p)//用指针来接收,p指向的还是这个结构,用p来打印
{
    printf("\tnum      :%d\n",p->num);
    printf("\tname      :%s\n",p->name);
    printf("\tscore_1      :%5.2f\n",p->score[0]);
    printf("\tscore_2      :%5.2f\n",p->score[1]);
    printf("\tscore_3      :%5.2f\n",p->score[2]);
    printf("\n")
}

---Dynamic storage allocation----

In the chapter on arrays, it was introduced that the length of an array is pre-defined (not directly explained, but it is also necessary to indirectly tell the compiler how long the array is), which is fixed throughout the program. Dynamic array types are not allowed in C language.

int a[10]={0,1,2,3,4,5,6,7,8,9};//Tell him the length

char a[ ];//The compiler will automatically calculate the length of the string, and then automatically fill in []. (So ​​the array must be pre-defined and specify how long it is)

int a[n];//This is not possible. Because dynamic array types are not allowed in C language. (It is wrong to use a variable to indicate the length and want to dynamically explain the size of the array. This is wrong. Because the compiler doesn't know how big your array is, then it doesn't know how to allocate space when it is defined, but in actual programming , It often happens that the required memory space depends on the actual input data and cannot be determined in advance; therefore, it is difficult to solve this problem with arrays (because the array must specify how many Long data))

In order to solve the above problems, C language provides some memory management functions. These memory management functions can dynamically allocate memory space as needed, and can also reclaim the no longer used space for use, providing a means for effective use of memory resources.

There are three commonly used memory management functions:

(1) Functions malloc and calloc that allocate memory space

(2) Free memory space function

----malloc function

//函数原型为
void *malloc(unsigned int size)//返回一个空指针,参数是要申请的一个尺寸,尺寸是无符号整型
//其作用是在内存的动态存储区中分配一个长度为size的连续空间(size是一个无符号数)。
//此函数的返回值是一个指向分配域的(要分配的这个空间的)起始地址的指针(类型为void)。
//如果此函数未能成功的执行(例如存储空间不足),则返回空指针(NULL)表示0。

----calloc function

//函数原型为:
void *calloc(unsigned n,unsigned size);
//其作用是在内存的动态存储区中分配n个长度为size的连续空间。
//函数返回一个指向分配域起始地址的指针。
//如果分配不成功,返回NULL。
//用calloc函数可以为一维数组开辟动态存储空间,n为数组元素个数,每个元素长度为size。
(,这种用法用的少,上个用法用的多,因为这种用法是结合数组来使用的)

----free function

//函数原型为void free(void *p);
//无返回值,将一个指针(void *p),这个指针就是你将要释放的,刚才申请的那个内存的地址
//起作用是释放由p指向的内存区,使这部分内存区能被其他变量使用
//p是最近一次调用calloc或malloc函数时返回的值
//free函数无返回值

----Linked list (this is a data structure)

What is a linked list?

Answer: Linked list is a common and important data structure, which is a structure for dynamic storage allocation. (So ​​to talk about the three functions just now)

The composition of the linked list:

Head pointer: Store an address that points to the first element.

Node: The actual data needed by the user (element) and the pointer of the link node.

Convex

ABCD above is four nodes, the first pointer of the head pointer, then we find a feature, the first pointer stores an address, the address refers to the first data, the first data has two parts, the first part It is the content of the data, the other part is the address that points to the next data; then the next data has two parts, one is the content, the other is the address that points to the next data; in turn, if there is no at the end, it points to Null, which means this The linked list ends. Then we will find that this linked list is bluntly similar to an array. The data of the array is also composed one by one, and the linked list is also next to each other, but there is a difference between the linked list and the array. One element of the linked list contains two things. , One is the content of the element, and the other is the address of the next element. One of the simplest benefits in this case is that the linked list can be dynamically allocated. How to allocate it dynamically? 1. Add an extra E temporarily, change this Null to the address of E, and then point E to the next one, if not, it will be Null, if there are some, point to the next; 2. It is also possible to temporarily remove B and store A The address points to C (directly evaporates B from the world); 3. Can I add B between A and C? Yes. I pointed the address of B to C, pointed the address of A to B, and assigned elements to B, which realized the insertion of B between A and C; so the linked list data structure makes our entire allocation space more flexible . The advantage over the array is reflected in these aspects.

Try to build a linked list according to the following figure

The linked list has three data and three nodes. The source code is as follows:

//由上图可以看到他有三个结点,每个结点都有元素(一个是number学号、还有score分数、还有地址(存放下一个的地址))
#include<stdio.h>
struct student
{
    long num;//长型存放学号
    float score;//分数
    struct student *next;//(相当于结构体里边有个结构体指针)//因为我们下一个指向的是跟他相同结构的也是student这个结构的一个数据,那我们这里就指向了一个指向结构的指针,指向student这个结构//这是一个指针,存放的地址就是下一个这样的结构,大家结构都是一样的只是位置不同//next这个指针变量,是一个结构体类型的所以它需要指向的是一个结构体(类比于 int *p;相当于int型的这个指针变量,需要指向的是int型的数据)
};
void main()
{
   struct student a,b,c,*head;//定义abc三个结点和一个head是一个结构体指针。
   a.num=10101;
   a.score=89.5;
   b.num=10103;
   b.score=90;
   c.num=10107;
   c.score=85;//赋值
 
   head=&a;//head是链表的头指针它必指向链表的第一元素,我们只需要知道这个链表的第一个元素在哪里,我们接着的第几个元素都可以索引到,因为我们接着的元素都会存放下一个元素的地址。//head里边存放的地址是指向第一个元素
   a.next=&b;//a指向b//因为是指针指向下一个地址
   b.next=&c;//b指向c
   c.next=null//c最后的地址就存放Null,表示链表结束
   do//使用do while依次打印出来,只要head不等于0
   {
       printf("%ld %5.1f\n",head->num,head->score);
       head=head->next;//第一次循环相当于head=a.next;而a.next=&b;//为什么每次执行的都是head,不是就一个head吗?head->a->b->c->Null。(因为我们这里并没有规定head必须指向头结点,所以head的指向是可以变化的)(它这里是把 head 当普通指针使用了,每次改变 head 的值,这样 head 就不指向头结点了,而是每次指向下一个节点)
   }while(head);//这个的意思就是while(head!=0);//while(head!=Null);//NUll就是0//他的地址的下一个值是有指向一个结构的,那么他就可以继续把他打印出来,直到最后一个,因为最后一个他是指向Null,所以这里head=head->next;这个head 是空的,那么整个程序结束。

}//通过链表索引分别将a元素,b元素,c元素打印出来。

---Establish a dynamic linked list

The so-called establishment of a dynamic linked list refers to the establishment of a linked list from scratch during the execution of the program, that is, to open up nodes one by one and enter the data of each node (that is, dynamically open and eliminate nodes according to needs, which is called dynamic establishment Linked list, which embodies the superiority and timeliness of linked list over arrays), and establishes the relationship between back and forth (linked lists are connected one by one).

Write a program based on the following analysis to create a one-way dynamic linked list containing student (student number, grade) data.

(Convention: if the student ID is not 0, then enter it; if the student ID is 0, (it means the establishment of the linked list is completed), it means that the process of establishing the linked list is completed, and the node should not be connected to the linked list)

analyse as below:

We write him as the simplest box flow chart. How to analyze this diagram? To draw, draw circles and triangles to analyze. Do it in order (triangles indicate nodes)

head=Null, n=0 means initializing to 0, just copy it.

Implementation of the algorithm:

(1) If the input p1->num is not equal to 0, the input is the first node (n=1), let head=p1, that is, assign the value of p1 to head, that is, make head also point to the new For the opened node, the newly opened node pointed to by p1 becomes the first node in the linked list. (Then we must point all three nodes to the first data, because only this one data can point us to.)

(2) Open up another node and make P1 point to it, and then input the data of that node.

(3) If the input p1->num is not equal to 0, the second node should be connected (n=2), and the address of the new node should be assigned to the next member of the first node.

(4) Then make p2=p1, that is, make p2 point to the node just created.

Figure (Figure description)

When the first node was created just now, head, p1, and p2 were all pointed to the first node. (Picture a) When the second node appears, p1 rushes up at the brunt, and then pulls p2 over (Picture b). At this time, only the head of the first node points to it and guides the first one. The next pointer of the node points to the second node, and when this step is completed, all three pointers point to the second node (Figure c). In this case, the third and the fourth are the same. There is a process.

(5) Open up another node and make p1 point to it, and input the data of the node.

(6) In the third cycle, since n=3 (n is not equal to 1), the value of p1 is assigned to p2->next, that is, after connecting the third node to the second node, And make p2=p1, make p2 point to the last node (that is, the third node).

In the third cycle, we will end it, as shown in the following figure: (How to end it, make its last next point to Null) (The third step and the second step are repeated, first make p1 point to it, and then make p2 Point to it, his next point to it)

(7) Open up a new node and make p1 point to it, and input the data of the node. Since the value of p1->num is 0, the loop is no longer executed, and this new node should not be connected to the linked list.

(8) Assign Null to p2->next.

(9) The process of establishing the linked list ends here. The last node pointed to by p1 is not linked to the linked list. The value of the next member of the third node is Null, which does not point to any node.

The following program also realizes the output of the linked list, how to realize it?

First of all, we must know the address of the first node of the linked list, that is, we must know the head value. (As long as we know the address, we are equivalent to grasping the entire linked list)

Set a pointer variable p, first point to the first node (that is, the head node), output the node pointed to by p, and then move p back by one node (p moves to the head->next pointer at this time, Move to the next node), and then output until the unconnected point of the linked list. So you can get the following flow chart

The following program is dynamic input and dynamic stop

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>

#define LENsizeof(struct student)//结构的大小
struct student *creat();//创建链表
void print(struct student *head)//打印链表(的函数)
struct student
{
    int num;
    float score;//分数
    struct student *next;
};
int n;//全局变量,用来记录存放了多少数据

void main()
{
   struct student *stu;
   stu=create();//12这个stu就是他的头结点,指针指向他的头结点
   print(stu);//然后我把这个头当成参数来print(是自定义的函数,实现的是打印这个链表)接收他的头
   printf("\n\n");
   system("pause");
}

struct student *creat()//creat创建函数
{
   struct student *head;
   struct student *p1,*p2;//在这里只是开辟了四个字节,说明这些指针是指向这个结构的,在内存并没有真正的创建整个结构那么大小的空出来。只是创建了一个指针,说它指向这么一个结构所以在2处就必须动态的给他初始化,给他获取相应的空间。LEN在上边通过宏定义,定义为这个student这个结构的大小
   p1=p2=(struct student *)malloc(LEN);//先定义要给他赋值,我们是动态创建链表,我们在上边声明的都是指针结构,都是指针,指针结构的话他只是开辟了一个四个字节,放一个指针地址//LEN是student结构的大小。3//让p1,p2同时指向我们刚申请的这个大小

   printf("Please enter the num:");
   scanf("%d",&p1->num);
   printf("Please enter the score:");
   scanf("%f",&p1->score);//4接着我们输入,输入都是指向的p1,p1首当其冲
   head=NULL;//head指向NULL
   n=0;//0个节点,还没有任何结点//5开始初始化
   while(p1->num)//6实现循环,当p1的num不等于0的时候,就是没有退出(while(0!=p1->num))
   {
      n++;//7不等于0就n++,表示出现了第一个结点(因为当p1的num成员为0时,就标志着我们整个程序结束,链表创建完成)
      if(1==n)//
      {
         head=p1;//8当n=1时head必须指向它p1,我们整个数据链的头结点指向它
      }
      else
     {
         p2->next=p1;
     }
     p2=p1//p2是跟在p1后边的
     p1=(struct student *)malloc(LEN);//9然后接着p1再次创建一个新的结点
   
     printf("\nPlease enter the num:");
     scanf("%d",&p1->num);
     printf("\nPlease enter the score:");
     scanf("%f",&p1->score);  //10这里要求输入第二个结点//只要输入的值不为0他就在while循环里边慢慢的循环,依次循环,当他在while处判断输入的值为0,到11
   }
   p2->next=NULL;//p2->next就指向NULL,我们刚申请的9到11之间的这个地方就废掉了,他就停留在内存的某个地方
   return head;//然后我们返回的值是head,head是我们整个链表的一个头结点的一个指针(也就是整个链表的领头羊,相当于我们数组的首地址,我们知道了这个数组的首地址,我们知道了数组依次索引,链表是同样的。)(我们之所以发明链表这个数据结构主要就是弥补数组的不足)//return返回的是指向我们创建完的链表的头
}
void print(struct student *head)//11定义接收头
{
   struct student *p;//12我们又定义了p指针,
   printf("\nThere are %d records!\n\n",n);
   p=head;//将头先指向了p
   if(head)//13如果head不等于0的话(if(NULL!=head))(什么都没有也就是一个空指针因为head是一个指针嘛)
   {
       do//14然后用while的形式把p输出出来
       { 
           printf("学号为%d的成绩是:%f\n",p->num,p->score);
           p=p->next;
       }while(p);//这里也是P不等于NULL的时候(while(NULL!=p))他就实现循环
   }

}

Result display:

-----Delete operation on linked list:

For example, the following linked list wants to delete B.

(A->B->C->D->E->H)

In fact, it is very simple to remove it directly, and point A to C.

If you want to add B back after deleting B, just break the link between A and C and add B (point A to B and B to C again).

(If it is an array ABCDE, what should I do if I want to delete B? Delete B directly, then C walks to the position of B, D walks to the position of C, and E walks to the position of D; then if you want to insert B again If you come in, you have to run E back to the original position, D walk back, C walk back, and then put B in. So this is the inconvenient place where the array is equivalent to the linked list)

Deleting a node from a dynamic linked list is not actually erasing it from the memory. (We want to link the next one in the linked list just to link with the address, because the next pointer of the linked list points to the pointer of a node. We only need to change the pointer, then we feel that he has disappeared (where did the disappearing node go like an astronaut abandoned in space, sooner or later will be hit by a meteorite, then he is the same, Somewhere in the memory will be overwritten by the data sooner or later. Don’t worry about it. It’s not really erased from the memory, but)) but to separate it from the linked list, just undo the original link relationship OK.

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/m0_37957160/article/details/108685364