深入认识数组

数组:
大家来想一想
1.什么数组?
2.为什么需要数组?


问题:
   int score1; 
   int score2; 
   int score3;
   int score4;
   
可以一次性创建多个变量 -- 数组 


什么数组:
  相同类型的 数据的集合 
  相同类型的 变量的集合  
为什么?
  提供了批量处理的方式 -提高了效率 
  
C语言针对数组提供形式
一维数组
二维数组
多维数组 


一维数组:
定义的语法:
  类型说明符 数组名[常量表达式];
    (1)        (2)     (3)
    
(1).类型说明符 
    用来说明 要处理的数据的 类型

(2).数组名
    名字 --- 代表这个数组
    //更本质的后面说 
    标识符 
    起名字规则 变量名命名规则相同     
(3).[常量表达式]
    []               //表示是个数组 
    常量表达式      10 10+1
    
    整型常量表达式    //不能是浮点型 
    表示的是,该数组中有多少个同类型的变量 //数组中的每个变量 --数组的元素
    
eg:
  int score[10]; //表示定义了一个数组,这个数组中有10个元素,每个元素类型是 int型 
                 //表示定义了一个包含了10个int型变量的数组
                 //数组定义好之后,表示10个int型变量的空间被开辟出来了 


  int a = 10; //

 printf("a = %d\n",a);  
 
一维数组的初始化 和 赋值问题 
  //初始化方式
  //方式1 -- 初始化列表  
  int score[10] = {1,2,3,4,5,6,7,8,9,10}; //初始化列表 --全部初始化 
  //方式2 -- 部分初始化 
  int score[10] = {1,2,3,4,5}; //部分初始化,已初始化部分,挨个给值 未初始化的部分,默认给成0
  
  //全部初始化成 0 
  int a[10] = {0};
  int a[10] = {}; //{} --- 初始化器 
  
  //未初始化的数组 
   随机值(垃圾值)
   
  //数组长度 可以省略,但是前提是,必须要有初始化的值
  int a[];//  错误 ---编译器也不知道有多大 
  int a[] = {1,2,3,4,5}; //编译器会根据给到的元素值的个数来推算出元素的个数(数组长度)
  
  //定义好之后如何给值 
  //赋值 方式

   int a;
   a = 10;
   
   int a[10];
   
   
  
  //键盘 输入 
  
  
一维数组元素引用:
需要说明引用的是哪个元素
语法:
数组名[下标]; //[]下标运算
         //下标 就是对应元素在数组中的编号 
         //下标 从0开始 
 
  printf("%d\n",score[2]);
  

int a[10]; //10个int型变量的空间 


数组越界:
int a[] = {1,2,3,4,5}; //5个int型变量 

注意:
    1. 编译器并不检查这种问题 
      作为程序员 自己小心 
      
    2. 数组下标的合法范围
       [0~len-1] 
       
    3. 下标的本质
    
数组名:
   1.数据类型 
     数组名 --可以代表数组这种数据类型
    sizeof(a) // 整个数组的大小 
   2.代表值 
     代表的是数组对应空间的其实地址 
     数组名所代表的地址为 数组首元素对应的地址
   3.数组下标 
     本质上是相对于首元素的偏移量(偏移了几个元素)   
数组特点:
 1.连续性   //一片连续的内存空间 
 2.有序性 
 3.单一性  //同种类型 内存空间大小都相同
 
练习1:
    定义一个数组, 从键盘输入10个整数,找出数组中能被3整除的数
  

补充:
  注意: 
  1. c99标准开始,数组长度可以是一个整型变量。
   int n ; //变量 
   int a[n]; //不能初始化 
   
  2. 数组 不能 整体操作 
     只能操作具体的元素 
练习:
   准备10个整型数,
   
   找出最大值 
   
   
   思路:
       打擂台 
     
    int max = a[0];
    
练习:
   数组逆序
   
   int a[10] = {1,2,3,4,5,6,7,8,10};

   int i = 0;
   
   for (i = 9; i >= 0; --i)
   {
        printf("%d\n",a[i]);
   }
   //

   
  int a[10] = { 1,2,3,4,5,6,7,8,9,10};
              {10,9,8,7,6,5,4,3,2,1};
     
     
     
  0 1 2 3 4 5 6 7 8 9  //下标      
{ 1,2,3,4,5,6,7,8,9,10};
{10,9,8,7,6,5,4,3,2,1};

a[i] <=> a[len-1-i]  

//对 对应的位置上值交换 

循环结束 
     换到一般 
     i < len/2 

交换两个数:
a[i] a[len-i-1]

int temp = a[i];
a[i] = a[len-i-1];
a[len-i-1] = temp;


  i                 j
  0 1 2 3 4 5 6 7 8 9  //下标      
{ 1,2,3,4,5,6,7,8,9,10};
{10,9,8,7,6,5,4,3,2,1};

  0 9 
  i j
  i++ j--
  
  i < j
-----------------------------------------------
排序:
   选择排序 
   冒泡排序 
   
   排序  
       把数据,从大到小或者从小到大 排列 
       
       从大到小 降序 
       从小到大 升序 
   
   
   选择排序 
     思想:
         给合适位置,选择合适的数 
         
         
         
         
          
   冒泡排序 
   
   
  
算法:
   理解 抽象 
   理解 过程 
   能够 实现代码
   
   算法优化? ---算法的实现 
   
   
    
   
   冒泡排序:
   
   思想:
       相邻两个元素两两比较 ,小的放前,大的放后 
    
   
   
   冒泡 和 选择 ,本质上差别不大 
   
   
   判断依据 --- 时间复杂度 
   
for (i = 0; i < len-1; ++i)//控制位置
{
    for(j = i+1; j < len; ++j)//找数
    {
        if (a[j] > a[i])
        {
                int t = a[i];
                a[i] = a[j];
                a[j] = t;
        }
    }
}
   
   
 
i = 0     j = 1    j < n;  //n-1
i = 1     j = 2    j < n;  //n-2
...
...                        //2
i = n-2   j = n-1  j < n;  //1 
   
   

 1+2+3+...+n-1   // (1+n-1)(n-1)/2
                 // n(n-1)/2
                 // (n^2 - n)/2 
                 
                 O(n^2)  //大o记法  
                 

//冒泡排序
for (i = len-1; i > 0; --i ) //趟数
{
        for (j = 0;j < i; ++j)  //一趟过程
        {
                if (a[j] > a[j+1])
                {
                        int t = a[j];
                        a[j] = a[j+1];
                        a[j+1] = t;
                }
        }
}

i = n - 1  //n-1
i = n - 2  //n-2 
...
i = 1      //1 

---------------------------------------------------------------------- 
总结:
1.数组 
  概念 
2.一维数组 
  数据类型 数组名[数组长度]
  //给值的方式 
    //初始化
    //赋值   
    //输入 
  //配合循环   
3.引用数组元素
  数组名[下标];

  1.不要越界 
  2.浮点类型
  
  int a[10];
  
  a[10] 
  

4.数组特点 
  连续性 
  有序性 
  单一性
  
  //线程 

5.练习 
  1.找最大值 
  2.逆序 
  3.选择排序 
  4.冒泡排序 
  
作业:
1. 从终端输入一个n将数组int a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9}
    完成如下变化,并打印,操作方式如下:
 //n:1     9 1 2 3 4 5 6 7 8
   n:2     8 9 1 2 3 4 5 6 7 
   n:3     7 8 9 1 2 3 4 5 6
   
 
   n:1     9 1 2 3 4 5 6 7 8
   n:-1    2 3 4 5 6 7 8 9 1
   
   数据 的 结构 
   
2. 已知数组a[10]和b[10]中元素的值递增有序,
   将两个数组合并为一个数组(有序)并完成打印。
   
   int a[] = {1,3,5,7,9};
   int b[] = {2,4,6,8,10};
   
   int c[10+10] 
--------------------------------------------------
排序的目的 
   查找 
  
二分查找   //非常高效的查找方式 
思想:
   每次找到中间的一个值 进行判断
   (二分法)

前提:
   数据必须是有序的 
-----------------------------------------------
整型二维数组:

背景,
  int score[30];
  
问题:
  学习小组 
  5组 
  6个同学 
  
  int score[6];
  
  
二维数组定义:

数据类型 数组名[整型常量表达式][整型常量表达式];

eg:

int score[5][6]; //两维 


//理解角度 
//表格 
//坐标 

int score[5][6];  //表示定义了一个5行 6列的一个二维数组
                  //30个元素


5 个组 
6 表示每组 6 个同学

5 行 
6 列          
int score[30]; //一维 


二维数组的初始化:
//全部初始化 
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

//按行初始化 
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};

二维数组元素的引用:
数组名[行下标][列下标];


二维数组的理解:
  行列 
  坐标 
  
二维数组的本质:
  满足数组特点
  单一性
  有序性
  连续性 
  
  C语言中,并不存在真正的二维数组 
  
  int score[4];
  
  int score[3][4]; //
  
  
  注意:
    数组是一种数据类型 
    
    int a[4]; // int ---数据类型
              // 描述数组中要存放的元素的数据类型 
              
    //数组 --的数据类型 
    //标识符对应的数据类型 --- 标识符去掉,剩下就是其对应的数据类型 
    
    int[4] //数组类型 --- 表示是一种包含了4个int型数据的一维数组类型  
  
  
  
   int[4] a; //int a[4]; //数组 
   
   int[4] a[3]; //定义了一个一维数组
                //一维数组中的每个元素 又是一个 一维数组类型 
   
   
   //int a[3][4]; //二维数组 
  

   int[4] a[3]; //a[0] 就相当于是内部的一维数组(int[4])的数组名
   
   a[0]  --->a[0][0] a[0][1] a[0][2] a[0][3]
   a[1]  --->
   a[2]  --->
   
  总结:
    1.c语言中,并不存在真正的二维数组 
    2.一维数组的一维数组
    3.二维数组 在内存上,数据的存放和一维数组没啥区别 
    4.二维数组 是按行优先存储 
     
   二维数组 --- 一维数组类型的一维数组 
            --- 数组的数组 
  
  
  
  


二维数组的应用:
  矩阵 
  图片数据 
 
练习:
    定义一个二维数组 定义一个 3*3 
    输入9个数
    找出最大值 
---------------------------------------------------
字符型数组 

字符型一维数组 

char ch[10] = {'h','e','l','l','o','w','o','r','l','d'}; 

多个字符数据 --- 字符串  
字符串 --- 一串字符 ---更在乎整体一个意思 

字符串:
    用来表示 一串字符 
    
    
"hello"  //字符串常量 
         //字符串在c语言中,都是按字符型一维数组来处理的 
         //在字符串末尾会默认添加一个结束标志 '\0'
         
char ch[5] = {'h','e','l','l','o'}; 
=>'h''e''l''l''o'

"hello" //
=>内存中的形式
'h''e''l''l''o''\0'


字符数组 与 字符串 
1.字符数组 可以 用来 存放字符串数据 
2.字符串 关心是字符串这个整体 
  此时结束标志('\0')重要,而数组长度 不那么重要了 
  
  编写代码时,数组长度 可能不再需要,而是以结束标志作为判断依据 
  
3.字符数组 和 字符串 写的时候 
  char str[10] = "hello";
 
eg:
  char str[10] = "hello";
  
  printf("sizeof(str) = %ld\n",sizeof(str));
  
  
输出字符串:
  puts(); // string 
  
   int puts(const char *s); 
   功能:
       输出字符串 
   参数:
       @s 表示存在字符串的空间的首地址
   返回值:
       非负数  成功
       EOF     出错 
       
  
  char *gets(char *s);
  功能:
      输入字符串 
  参数:
    @s  表示存放字符串的一块空间的首地址 
  返回值 
     成功 返回就是s 
     
总结:
  字符串的输入输出 
  gets
     //本质 --实际上时字符数组的操作 
     //最终加了 '\0'
  puts 
     //本质 --实际上就是输出数组中的元素,结束判断条件是'\0'
  
  
//gets内部实现 
//方式1 
        do
        {
                str[i] = getchar();
        }while (str[i++] != '\n');//hello\n'\0'
        str[i-1] = '\0';

//方式2 
        while ( (str[i] = getchar()) != '\n')
                ++i;
        str[i] = '\0';

  
//puts内部实现  --默认自带\n  
    int i = 0;

    while (ch2[i] != '\0')
    {
        printf("%c",ch2[i]);
        ++i;
    }
    putchar('\n');

字符串的输入
gets ()   
scanf() //如果输入的字符串中间 有空格 只能接收空格前面的 
注意:
   空间尽可能足够 
   否则可能导致越界


字符串函数:
//字符串的长度 
"hello" //指的是 '\0'前面字符的个数  --- 字符串长度 
strlen();
size_t strlen(const char *s);
功能: 计算字符串长度
参数:
    s  //存在字符串的一块内存空间的首地址 
返回值:
   成功 返回 长度
   size_t //long int 
   
char str[10] = "hello";

printf("sizeof(str) = %ld\n",sizeof(str)); //数组大小 --- 数组长度 
printf("strlen(str) = %ld\n",strlen(str)); //字符串的长度

数组大小 ---数组所占内存空间的字节数 
数组长度 ---数组元素个数 
字符串长度--- '\0'前字符的个数 

#include <string.h> //加头文件 


//字符串拷贝 

char str1[10] = "hello";
char str2[10];

//str2 = str1; 

strcp

char * strcpy(char *dest, const char *src);
功能:
   将src中的字符串 拷贝到 dest 
参数:
   src  存放这源字符串的 一块空间的首地址 
   dest 存放字符串的目的空间的地址   
返回值:
   成功 返回dest空间的地址
   失败 返回NULL
   
//字符串拼接 
 

char str1[20] = "hello";
char str2[20] = "world"; 


strcat
 char *strcat(char *dest, const char *src);
 功能:
     拼接字符串
 参数:
    dest 拼接的目的字符串对应空间的首地址  
    src  源字符串对应空间的首地址
 返回值
   成功 返回dest空间的地址
   失败 返回NULL 

思路:
   1.定位到 目标字符串 '\0'所在位置 
   2.从 '\0'位置开始,将 源字符串 字符挨个拷贝过来 
   
 
字符型二维数组     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值