3.结构体与链表

转载请标明出处:http://blog.csdn.net/u012637501

一、结构体

struct Student *p:p是一个struct
Student *类型的指针变量,

用于存放struct Student类型变量的地址

1.结构体:把一些基本类型数据组合在一起形参的一个新的复合数据类型,用来表示一些复杂的事物,即称为结构体。

2.定义结构体方法

(1)第一种方法:指定结构体名,不定义结构体变量

struct Student

{

int age;

float score;

char sex;

};

(2)第二种方法:指定结构体名,并同时定义一个结构体变量

struct Student2

{

.....

}st2;

(3)第三种方法:不指定结构体名,但定义一个结构体变量

struct

{

.....

}st3;

3.初始化(赋值)与成员变量引用

(1)定义的同时可以整体赋初值;

(2)如果定义完之后,则只能单个的赋初值;

(3)结构体成员引用

方法一:结构体变量名.成员名

方法二:指针变量名->成员名

注:"指针变量名->成员名"比较常用,其在计算机内部会被转化成(*指针变量名).成员名的方式来执行,这两种方式是等价的。如pst->age 会在计算机内部转化成 (*pst).age的方式来执行,没有为什么,这就是->的含义,这也是一种硬性规定。

§举例1:

/*结构体定义与引用*/

#include<stdio.h>

struct Student

{

char name;

int age;

char sex;

};

void main()

{

struct Student stu1={‘L‘,18,‘g‘},stu2;    //声明结构体类型变量并初始化

printf("结构体成员所占字节数sizeof(结构体变量/结构体类型) = %d\n\n",sizeof(struct Student));

struct Student *p=&stu1;

//&stu1不能写成stu1,因为struct Student *p表示:p是一个struct Student *类型的指针变量,用于存放struct
Student类型变量的地址

p->age=25;

printf("stu1.age=%d\n",stu1.age);

stu2=stu1;

printf("stu2.name=%c\nstu2.age=%d\nstu2.sex=%c\n",stu2.name,stu2.age,stu2.sex);

}

运行结果:

  

分析说明:

◇p->age的含义是:p指向结构体变量stu1中的age这个成员。p->age在计算机内部会被转换成

(*p).age=stu1.age,而p=&stu1,故p->age=(*p).age=stu1.age( *p=*&stu1=stu1 );

◇ struct Student *p=&stu1,等价于{ struct Student *p; p=&stu1},即将struct Student类型变量的地址

赋值给只能存放(struct Student * )类型的指针变量。

◇结构体变量不能相加,不能相减,也不能互相乘除,但结构体变量可以相互赋值。

◇pst->的含义:pst 所指向的那个结构体变量中的age这个成员。

◇结构体变量的大小略大于其内部成员类型所占字节数之和。

sizeof(struct Student)或sizeof(stud1),需要注意的是,这里计算得到结构体占12字节数据,是因为系统以占字节最大类型对齐(int占4字节最大),故4+4+4=12.

§举例2:通过函数完成对结构体变量的输入和输出

若想通过函数对主函数结构体变量进行修改,则①主函数必须发送地址,②外函数定义指针结构体变量,③通过外函数内部语句完成对变量的修改。 而仅想输出、读取操作,则不用传地址。

即:(1)对结构体变量输入(修改结构体成员),必须发送结构体变量的地址;

(2)对结构体变量输出,可以发送结构体变量,也可以发送结构体变量的地址;

/*举例二:通过函数完成对结构体变量的输入和输出*/

#include<stdio.h>

# include <string.h>

/*1.结构体*/

struct Student

{

char name[20];

int age;

int score;

};

/*2.修改主函数结构体变量成员值

伪算法:

(1)主函数传入结构体变量地址,作为实参;

(2)被调函数定义结构体指针变量,作为形参;

(3)在被调函数中,通过 (指针变量->成员) 或者 (*指针变量).成员 修改数据*/

void InputFunction(struct Student *stu)

{

stu->age = 20; //等价于(*stu).age

strcpy(stu->name,"小龙女"); //stu->name="钟显",会出现

stu->score=99;

}

/*3.输出传入变量的成员数据*/

void OutputFunction(struct Student stu)

{

printf("stud1修改前:name=%s,age=%d,score=%d\n\n",stu.name,stu.age,stu.score);

}

void main()

{

struct Student stud1={"林俊杰",33,100}; //声明一个结构体变量并初始化

OutputFunction(stud1); //输出:变量的成员数据

InputFunction(&stud1); //输入:修改变量的成员数据

printf("stud1修改后:name=%s,age=%d,score=%d\n\n",stud1.name,stud1.age,stud1.score);

}

运行结果:

说明分析:

☆对于字符数组成员,如pstu->name = "张三丰"; 或(*pstu).name = "张三丰";  都是error,

提示错误信息: cannot convert from ‘char [5]‘ to ‘char [100]‘ 。 strcpy(pstu->name,"张三丰"); // 用字符串拷贝命令解决问题

☆倘若希望传递的是结构体变量,而不是结构体变量的地址来修改变量的成员值

如:

void InputFunction(struct Student stu)

{

stu.age = 20; //等价于(*stu).age

strcpy(stu.name,"小龙女"); //stu->name="钟显",会出现

stu.score=99;

}

主函数调用:InputFunction(stud1)。

 

这种方法是不能够修改主函数结构体变量成员值的,因为被调函数中struct
Student stu是一个局部变量,当被调函数结束后,stu会被系统回收,所以,最终主函数结构体变量成员值根本没有变化。

内存分析如下:

(2)传递变量

(2)传递地址

§举例3:通过函数完成对结构体变量的输入和输出

  1. /*举例三:动态构造存放学生信息的结构体数组,并排升序(高>低,反序)*/
  2. #include<stdio.h>
  3. #include<malloc.h>
  4. # include <string.h>
  5. //1.结构体
  6. struct Student
  7. {
  8. char name[20];
  9. int age;
  10. int score;
  11. };
  12. /*动态一位数组
  13. *  (1)声明一个struct Student *类型指针变量,用于接收malloc的返回值;
  14. (2)动态开辟一段空间,用于存储len个结构体类型变量;
  15. (3)结构体数组变量的所有元素赋值*/
  16. void main(void)
  17. {
  18. //a.确定变量个数
  19. int number,i,j;
  20. struct Student *pArray,temp;
  21. printf("请输入学生的个数:number= ");
  22. scanf("%d",&number);
  23. //b.动态开辟一段空间
  24. pArray=(struct Student *)malloc(number*sizeof(struct Student)); //开辟一段空间
  25. //c.给结构体数组变量赋值
  26. for(i=0;i<number;i++)
  27. {
  28. printf("请输入第%d个学生的信息:\n",i+1);
  29. printf("name=");
  30. scanf("%s",pArray[i].name);
  31. printf("age=");
  32. scanf("%d",&pArray[i].age);
  33. printf("score=");
  34. scanf("%d",&pArray[i].score);
  35. }
  36. //d.按学生成绩升序排序(冒泡算法)
  37. for(i=0;i<number-1;i++)          //number-1表示数组第number个元素下标
  38. {
  39. for(j=number-2;j>=i;j--) //number-2表示倒数第二个元素位置(下标)
  40. {
  41. if(pArray[j].score>pArray[j+1].score)
  42. {
  43. temp=pArray[j];     //注意:temp为struct Student类型
  44. pArray[j]=pArray[j+1];
  45. pArray[j+1]=temp;
  46. }
  47. }
  48. }
  49. //e.输出
  50. printf("\n\n学生的信息是:\n");
  51. for (i=0;i<number;++i)
  52. {
  53. printf("第%d个学生的信息是:\n", i+1);
  54. printf("name = %s\n", pArray[i].name);
  55. printf("age = %d\n", pArray[i].age);
  56. printf("score = %d\n", pArray[i].score);
  57. }
  58. }

二、链表

1.基本概念

(1)头结点:头结点是首结点前面的那个结点,其数据类型和首结点一样,但并不存放有效数

据,设置头结点的目的是为了方便对链表的操作(如头插法建单链表)。

(2)头指针:存放头结点地址的指针变量,确定一个链表必须要有头指针。

(3)首结点:存放第一个有效数据的结点。

(4)尾结点:存放最后一个有效数据的结点。

2.链表优缺点

(1) 数组

优点:存取速度快

缺点:需要一整块连续的空间

(对于庞大数据,往往没有一个适合的较大的连续的空间如a[30000000000000])

插入和删除元素效率很低 (插入和删除中间某个元素,其后的所有都要前后移动)

(2)链表

优点:插入删除元素效率高 ,无需一整块连续的空间

缺点:查找某个位置的元素效率低

(由于不是连续的,不同由下标直接找,必须由头至尾逐一比对查找)

两者各有所长,至今没有出现一个更优的存储方式,可集数组、链表优点于一身。

确定一个链表需要一个参数,头指针

对于每个链表元素,分为左右两部分,左边为数据单元,右边为下一元素地址。

例:

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

struct Node
{
 int data; //数据域
 struct Node * pNext; //指针域
};

//函数声明
struct Node * create_list(void);
void traverse_list(struct Node *);

int main(void)
{
 struct Node * pHead = NULL;

 pHead = create_list();
//create_list():创建一个非循环单链表,并将该链表的头结点的地址付给pHead
 traverse_list(pHead);

 return 0;
}

struct Node * create_list(void)
{
 int len;  //用来存放有效节点的个数
 int i;
 int val; //用来临时存放用户输入的结点的值

 //分配了一个不存放有效数据的头结点
 struct Node * pHead = (struct Node *)malloc(sizeof(struct Node));
 if (NULL == pHead)
 {
  printf("分配失败, 程序终止!\n");
  exit(-1);
 }
 struct Node * pTail = pHead;
 pTail->pNext = NULL;

 printf("请输入您需要生成的链表节点的个数: len = ");
 scanf("%d", &len);

 for (i=0; i<len; ++i)
 {
  printf("请输入第%d个节点的值: ", i+1);
  scanf("%d", &val);

  struct Node * pNew = (struct Node *)malloc(sizeof(struct Node));
  if (NULL == pNew)
  {
   printf("分配失败, 程序终止!\n");
   exit(-1);  //终止程序
  }
  pNew->data = val;
  pTail->pNext = pNew;
  pNew->pNext = NULL;
  pTail = pNew;
 }

 return pHead;
}

void traverse_list(struct Node * pHead)
{
 struct Node * p = pHead->pNext;

 while (NULL != p)
 {
  printf("%d  ", p->data);
  p = p->pNext;
 }
 printf("\n");

 return;
}
时间: 2024-07-30 10:55:04

3.结构体与链表的相关文章

C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com

原文:C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 | IT宅.com C语言语法笔记 – 高级用法 指针数组 指针的指针 二维数组指针 结构体指针 链表 本文由 arthinking 发表于315 天前 ⁄ itzhai.com原创文章 ⁄ C语言 ⁄ 评论数 3 ⁄ 被围观 1,775 views+ 指针数组: 在一个数组中,如果它的元素全部都是指针类

学习C/C++语言:结构体,动态链表

//*************************************************************** //结构体:简单的静态链表 #include<stdio.h> #include<string.h> #define NULL 0 #define SIZE 10 struct student { char num[SIZE]; float score; struct student *next; }; void main() { struct stu

关于结构体和链表结构

程序如下 #include <stdio.h>typedef struct list{ int data; struct list *next;} LIST;int fun(LIST *h){ LIST *p; int t = 0;//初始值不给的话会出现很离奇的错误! p=h; while( p )//*p为结构体,不能转换为bool(布尔)型,只能用p或者*p!=NULL { t=t+p->data;//p为指针,需要用->,不能用 .  p=(*p).next; } retu

解决一个题目。关于结构体与链表的操作

有初学者给我发了一个题目,求助我解决. 题目如下: 其实哥也不会C,但就是有一颗热心肠.于是果断研究起. 最后解决如下: 先上效果图 附上代码 : // LinkListDemo.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <STDLIB.H> # define LEN sizeof(struct examinee) //结构体长度 //

结构体和链表

PTA 实验作业 7-1查找书籍 1.本题 pta 提交列表 2.设计思路 本题要求我们给定n本书的名称和定价并编写程序,查找并输出其中定价最高和最低的书的名称和定价. 尤其注意到的是要保证输出的为保留两位小数 这种题目我们要使用结构体,首先先定义好书名和价格为结构体,再定义 max 和 min并初始化为0用来标记最小价格和最高价格的书 再输入书本的个数n 之后,要判断循环变量 i 是否小于 n,不是的话直接输出答案 是的话再输入书本信息,并比较 s[i] 和 max 或 min 的大小,如果大

结构体与链表

1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<malloc.h> 5 #define N 3 6 #define LEN sizeof(struct grade) 7 struct grade 8 { 9 char no[7]; 10 int score; 11 struct grade *next; 12 }; 13 struct grade *create

C语言结构体

一.结构体的定义 1.定义形式 struct 结构名 {成员列表:};       //定义为语句,分号不能丢 2.结构类型变量的声明 (1)声明形式1 struct student { int number; char name[10]; float score; }; struct student st1,st2,st3; (2)声明形式2 struct student { int number; char name[10]; float score; }st1,st2,st3; (3)结构

Python中对复杂数据结构排序(类似C中结构体数据结构)

Python中排序主要有两个函数:sorted和列表成员函数sort,两者除了调用方式有些区别外,最显著的区别是sorted会新建一个排序好的列表并返回,而sort是修改原列表并排好序.sorted的原型是: sorted(iterable, cmp=None, key=None, reverse=False) sort的原型是: list.sort(cmp=None, key=None, reverse=False) 其中cmp和key都是函数引用,即可以传入函数名.这两个函数都是对list里

linux块设备驱动---相关结构体(转)

上回最后面介绍了相关数据结构,下面再详细介绍 块设备对象结构 block_device 内核用结构block_device实例代表一个块设备对象,如:整个硬盘或特定分区.如果该结构代表一个分区,则其成员bd_part指向设备的分区结构.如果该结构代表设备,则其成员bd_disk指向设备的通用硬盘结构gendisk 当用户打开块设备文件时,内核创建结构block_device实例,设备驱动程序还将创建结构gendisk实例,分配请求队列并注册结构block_device实例. 块设备对象结构blo