咕噜咕噜哈里  

1.结构体数据类型

a.定义形式:struct 结构体类型名{

   成员说明列表

};

struct date{
   int year;
   int month;
   int  day;
};

b.结构体变量的使用

①先定义结构,再说明结构体变量

struct stu{
   int num;
   char name[20];
   char sex;
   float score;
};
struct stu boy1,boy2;

②在定义结构类型的同时说明结构体变量

struct stu{
   int num;
   char name[20];
   char sex;
   float score;
}boy1,boy2;  /*变量名表列*/

③直接说明结构体变量

struct {
   int num;
   char name[20];
   char sex;
   float score;
}boy1,boy2;

调用时:boy1.sex;  boy2.sex;

c.结构体数组

①结构体数组的定义:struct employee workers[50];

②在定义结构体的同时,定义结构体数组

struct employee workers[50];

struct employee{
  long no;
  char name[10];
  char sex;
  char addr[40];
}workers[50];

②直接定义结构体数组而不定义结构体名

struct employee workers[50];

struct{
  long no;
  char name[10];
  char sex;
  char addr[40];
}workers[50];

d.结构体数组的使用

①引用某一结构体数组元素的一个成员结构体数组名 [元素下标].结构体成员名。

workers[i].no

②可以将一个结构体数组赋给同一结构体类型数组的另一元素,或赋给同一类型的变量。

struct employee workers[5],workman;
workers[3]=workers[0];
workman=workers[1];
workers[4]=workman;

③不能把结构体数组元素作为一个整体直接进行输入或输出,只能以单个成员对象进行输入或输出。

scanf("%d",&workers[0].no);
printf("%d",workers[0].no);

2.结构体指针

声明形式:struct 结构名  *结构指针变量名

struct stu *pstu

访问形式:(*结构指针变量).成员名 或 结构指针变量->成员名

(*pstu).num
pstu->num

应用实例:

#include<stdio.h>
struct stu{
  int num;
  char *name;
  char sex;
  float score;
}boy1=(102,"zhang ping",'M',78.5),*pstu;
void main(){
   pstu=&boy1;
   printf("Number=%d\n Name=%s\n ",boy1.num,boy1.name);
   printf("Sex=%c\n Score=%f\n ",boy1.sex,boy1.score);

   printf("Number=%d\n Name=%s\n ",(*pstu).num,(*pstu).name);
   printf("Sex=%c\n Score=%f\n ",(*pstu).sex,(*pstu).score);\

   printf("Number=%d\n Name=%s\n ",pstu->num,pstu->name);
   printf("Sex=%c\n Score=%f\n ",pstu->sex,pstu->score);

}

3.链表

 a.什么是链表:(1)头指针变量head----指向链表的首结点

(2)每个结点由两个域组成

①数据域---存储结点本身的信息

②指针域---指向后继结点的指针

(3)尾结点的指针域置为“NULL(空)”,作为链表结束的标志。

例:一个存放学生学号和成绩的结点:

struct stu{
  int num;
  int score;   /*数据域*/
  struct stu *next;   /*指针域,它是一个指向stu类型结构的指针变量*/
}

b.链表和数组的主要区别

二者都属于一种数据结构

1.从逻辑结构分析

    (1)数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数;

当数据减少时,造成内存浪费;数组可以根据下标直接存取。

     (2)链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便的插入、删除数据项。(数组中插入、删除数据项时,需要移动其他数据项,非常繁琐)

链表必须根据 next 指针找到下一个元素。

2.从内存存储分析

      (1)(静态)数组从栈中分配空间,对于程序员方便快速,但是自由度小。

      (2)链表从堆中分配空间自由度大但是申请管理比较麻烦。

如果需要快速访问数据,很少或不插入和删除元素,就应该用数组;相反,如果需要经常插入和删除元素就需要用连边数据结构。

c.链表的基本操作

创建链表

//声明节点结构
typedef struct Link {
    int  elem;//存储整形元素
    struct Link *next;//指向直接后继元素的指针
}link;
//创建链表的函数
link * initLink() {
    link * p = (link*)malloc(sizeof(link));//创建一个头结点
    link * temp = p;//声明一个指针指向头结点,用于遍历链表
    int i = 0;
    //生成链表
    for (i = 1; i < 5; i++) {
        //创建节点并初始化
        link *a = (link*)malloc(sizeof(link));
        a->elem = i;
        a->next = NULL;
        //建立新节点与直接前驱节点的逻辑关系
        temp->next = a;
        temp = temp->next;
    }
    return p;
}

链表插入元素

顺序表一样,向链表中增添元素,根据添加位置不同,可分为以下 3 种情况:

  • 插入到链表的头部(头节点之后),作为首元节点;
  • 插入到链表中间的某个位置;
  • 插入到链表的最末端,作为链表中最后一个数据元素;


虽然新元素的插入位置不固定,但是链表插入元素的思想是固定的,只需做以下两步操作,即可将新元素插入到指定的位置:

  1. 将新结点的 next 指针指向插入位置后的结点;
  2. 将插入位置前结点的 next 指针指向插入结点;


例如,我们在链表 {1,2,3,4} 的基础上分别实现在头部、中间部位、尾部插入新元素 5,其实现过程如 1 所示:

 

 

从图中可以看出,虽然新元素的插入位置不同,但实现插入操作的方法是一致的,都是先执行步骤 1 ,再执行步骤 2。

注意:链表插入元素的操作必须是先步骤 1,再步骤 2;反之,若先执行步骤 2,会导致插入位置后续的部分链表丢失,无法再实现步骤 1。

通过以上的讲解,我们可以尝试编写 C 语言代码来实现链表插入元素的操作:

//p为原链表,elem表示新数据元素,add表示新元素要插入的位置
link * insertElem(link * p, int elem, int add) {
link * temp = p;//创建临时结点temp
link * c = NULL;
int i = 0;
//首先找到要插入位置的上一个结点
for (i = 1; i < add; i++) {
if (temp == NULL) {
printf("插入位置无效\n");
return p;
}
temp = temp->next;
}
//创建插入结点c
c = (link*)malloc(sizeof(link));
c->elem = elem;
//向链表中插入结点
c->next = temp->next;
temp->next = c;
return p;
}

提示,insertElem 函数中加入一个 if 语句,用于判断用户输入的插入位置是否有效。例如,在已存储 {1,2,3} 的链表中,用户要求在链表中第 100 个数据元素所在的位置插入新元素,显然用户操作无效,此时就会触发 if 语句。

链表查找元素

在链表中查找指定数据元素,最常用的方法是:从表头依次遍历表中节点,用被查找元素与各节点数据域中存储的数据元素进行比对,直至比对成功或遍历至链表最末端的 NULL(比对失败的标志)。

因此,链表中查找特定数据元素的 C 语言实现代码为:

//p为原链表,elem表示被查找元素、
int selectElem(link * p, int elem) {
//新建一个指针t,初始化为头指针 p
link * t = p;
int i = 1;
//由于头节点的存在,因此while中的判断为t->next
while (t->next) {
t = t->next;
if (t->elem == elem) {
return i;
}
i++;
}
//程序执行至此处,表示查找失败
return -1;
}

注意,遍历有头节点的链表时,需避免头节点对测试数据的影响,因此在遍历链表时,建立使用上面代码中的遍历方法,直接越过头节点对链表进行有效遍历。

链表更新元素

更新链表中的元素,只需通过遍历找到存储此元素的节点,对节点中的数据域做更改操作即可。

直接给出链表中更新数据元素的 C 语言实现代码:

//更新函数,其中,add 表示更改结点在链表中的位置,newElem 为新的数据域的值
link *amendElem(link * p, int add, int newElem) {
int i = 0;
link * temp = p;
temp = temp->next;//在遍历之前,temp指向首元结点
//遍历到被删除结点
for (i = 1; i < add; i++) {
temp = temp->next;
}
temp->elem = newElem;
return p;
}

文章来源:链表的基本操作(C语言)详解 (biancheng.net)

4.枚举数据类型

什么是枚举:在实际问题中,有些变量的取值被限定在一个有限的范围内。例如,一个星期内只有7天,一年只有12个月,一个班每周有6门课程等。

如果把这些量说明为整型,字符型或其他类型显然是不妥当的。为此,C语言提供了一种为“枚举”的类型。在“枚举”类型的定义中列举出所有可能的

取值,被说明为该“枚举”类型的变量取值不能超过定义的范围。应该说明的是,枚举类型是一种基本数据类型,而不是一种构造类型,因为它不能再

分解为任何基本类型。

a.一般定义格式:enum  枚举类型名{标识符1,标识符2,....,标识符n};

enum bool {false,true};

三种定义形式:

(1)先定义枚举类型,再定义枚举变量

enum color{
   red,green,blue,yellow,white
};
enum color select,change;

(2)定义枚举类型的同时定义枚举变量

enum color{
   red,green,blue,yellow,white
} select,change;

(3)不指定枚举类型名,直接定义枚举变量

enum{
   red,green,blue,yellow,white
}select,change;

b.枚举类型变量的赋值和使用

注意:(1)枚举变量值是常量,不是变量。不能再程序中赋值语句再对它赋值。

例如对枚举weekday的元素再作以下赋值:

sun=5;
mon=2;
sun=mon;

都是错误的。

(2)枚举元素本身由系统定义了一个表示序号的数值,从0开始顺序定义为0,1,2......

如在weekday中,sun值为0,mon为1,...,sat值为6.

#include<stdio.h>
void main(){
   enum weekday
   {
       sun,mon,tue,wed,thu,fri,sat
    }a,b,c
    a=sun;
    b=mon;
    c=tue;
    printf("%d,%d,%d",a,b,c);
}

输出结果:0,1,2

枚举类型应用的几点说明:

(1)定义枚举类型必须以enum开头

(2)在定义枚举类型时花括号中的名字称为枚举元素或枚举变量。命名规则与标识符相同,

仅是为了提高程序的可读性才使用这些名字。

(3)枚举元素不是变量,不能改变其值,但枚举元素作为常量他们是有值的。从花括号的第一元素开始,值分别

是0,1,2,3,4,这是系统自动赋予的,可以输出。

例如:

printf(“%d”,blue);  结果为2;

但是枚举类型不能写成:

enum colorname{0,1,2,3,4};

可以在定义类型时对枚举常量初始化:

enum colorname{red=3,green,blue,yellow=8,white};

(4)枚举常量可以进行比较,例如

if (color==red) printf("red");
if(color==white)  printf("it is not white!");
if(color>yellow)  printf("it is white!");

(5)一个枚举变量的值只能是这几个枚举常量之一,可以将枚举常量赋给一个枚举变量,

但不能将一个整数赋给它。例如:

color=white;(正确)
color=5;(错误)

(6)枚举常量不是字符串,不能用下面的方法输出字符串“red”:

printf ("%s",red);

 

posted on 2022-02-09 21:37  咕噜咕噜哈里  阅读(70)  评论(0编辑  收藏  举报