概念:

  一堆相同类型的数据的有序集合

格式:

  元素类型  数组名称[ 元素个数 ]

定义数组: 

    // 定义了一个名称叫做scores的数组, 数组中可以存放3个int类型的数据
    int scores[3];
    // 只要定义一个C语言的数组, 系统就自动会给数组中的每一块小得存储空间一个编号
    // 这个编号从0开始, 一次递增
    // 数组中系统自动绑定的编号, 我们称之为 索引
    scores[0] = 12;
    scores[1] = 66;
    scores[2] = 59;

数组初始化:

  完全初始化:

    // 依次将{}中的每一个值赋值给数组中的每一个元素
    // 并且从0开始赋值
    int scores[5] = {99,88,77,66,100};

部分初始化:  

     // 默认从0开始初始化, 依次赋值
     // 注意: 如果"在部分初始化中"对应的内存没有被初始化, 那么默认是0
     int scores1[3] = {11, 22}; 

注意点:

  1.如果没有对数组进行初始化(完全和部门), 那么不要随便使用数组中的数据, 可能是一段垃圾数据(随机值)

  2.定义数组的时候, 数组的元素个数不能使用变量  变量作为数组的元素个数, 不初始化的情况下是随机值, 如果初始化会直接报错

  3.如果定义的同时进行初始化, 那么元素的个数可以省略, 省略之后, 初始化赋值几个数据, 数组就能存储几个数据,如果定义数组时没有进行初始化, 那么不能省略元素个数

  4.可以通过[索引] = 的方式, 给指定索引的元素赋值  

    int socres7[101] = {[99] = 1, [100] = 3}; 

  5.只能在定义的同时利用{}进行初始化, 如果是先定义那么就不能使用{}进行初始化

    int scores8[3];
    //scores8 = {1 , 4, 19};
    // 如果先定义那么就不能再进行整体赋值, 只能单个赋值
    scores8[0] = 1; 

数组遍历:

    int scores[6] = {1, 23, 44, 66, 71, 88, 99 , 2};
    // 动态计算数组的元素个数
    int length = sizeof(scores) / sizeof(scores[0]);
    //length 不要写 6 这样的魔鬼数字
    for (int i = 0; i < length; i++) {
        printf("scores[%i] = %i\n", i,scores[i]);
    } 

数组内存分配:

  存储方式:

    1)计算机会给数组分配一块连续的存储空间

    2)数组名代表数组的首地址,从首地址位置,依次存入数组的第1个、第2个....、第n个元素

    3)每个元素占用相同的字节数(取决于数组类型)

    4)并且数组中元素之间的地址是连续。        

    // 变量在内存中的存储
    // 由于变量的内存寻址是从大到小, 所以存储数据时会从高字节开始存储
    int num = 10; // 0000 0000 0000 0000 0000 0000 0000 1010
    /*
    00001010     0x7fff5fbff7cc
    00000000     0x7fff5fbff7cd
    00000000     0x7fff5fbff7ce
    00000000     0x7fff5fbff7cf
    */       
    // 注意: 数组的存储和变量有点不一样, 数组存储元素, 是从所占用的低字节开始存储
    //     数组的元素自然的从上往下排列存储,整个数组的地址为首元素的地址。
    char charValues[4] = {'l', 'u', 'c', 'k'};
    /*
     charValues[0] = 0x7fff5fbff7c8
     charValues[1] = 0x7fff5fbff7c9
     charValues[2] = 0x7fff5fbff7ca
     charValues[3] = 0x7fff5fbff7cb
     */ 

    //&charValues == charValue == &charValue[0]     

数组越界问题:    

#include <stdio.h>

int main(int argc, const char * argv[]) {
    int nums[2] = {1, 5};
    int values[3] = {7, 8, 9};
    // 注意点: 在使用数组的时候, 一定不要访问不属于字节的存储空间, 这样会导致数据混乱
    // 有时候如果访问了不属于自己的存储空间, 程序会报错
    values[3] = 44;
    printf("values[3] = %i\n", values[3]);
    printf("nums[0] = %i\n", nums[0]);    
    nums[-1] = 88;
    printf("values[2] = %i\n", values[2]);
    return 0;
}
/*
 输出结果:
     values[3] = 44
     nums[0] = 44
     values[2] = 88
 */

下图分析  values[3]访问到了nums[0]的空间    nums[-1] 访问到了 values[2] 的空间

       

数组练习:

       

    // 从键盘录入当天出售BTC的价格并计算出售的BTC的总价和平均价(比如说一天出售了4个比特币)
    // 1.1定义数组保存每个比特币的价格
    int values[4] = {-1};
    // 1.2动态计算数组的元素个数
    int length = sizeof(values) / sizeof(values[0]);
    // 1.3定义变量保存总和
    int sum = 0;
    for (int i = 0; i < length; i++) {
        printf("请输入第%i个比特币的价格\n", i + 1);
        scanf("%i", &values[i]);
        //2.0 计算总和
        sum += values[i];
    }
    /*
    // 2.计算总和
    int sum = 0;
    for (int i = 0; i < length; i++) {
        sum += values[i];
    }
     */
    // 3.计算平局值
    int average = sum / length;
    // 4.输出结果
    printf("sum = %i, average = %i\n", sum, average); 

数组与函数:

   1 数组名作为函数的参数传递, 是传递的数组的地址

     因为数组名就是数组的地址 &number = &number[0] == number

   2 如果数组作为函数的形参, 元素的个数可以省略

   3 如果形参是数组, 那么在函数中修改形参的值, 会影响到实参的值  

    void change(int values[])
    {
        values[1] = 99;
    } 

    int main(int argc, const char * argv[]) {
         int nums[2] = {1, 5};
        change(nums);
        printf("nums[1] = %i\n", nums[1]);
        return 0;
    }
    输出结果: 99 

注意点:

   如果传递的数组的名称, 其实传递的是地址 如果传递的是地址, 其实传递的是指针  指针在64位编译环境占8个字节

   如果数组作为形参, 那么在函数中就不能通过数组的名称计算出数组元素的个数  因为系统会自动将数组形参转换为指针, 指针占用8个字节  所以只能读取到8个字节的数据

  举例:

    要求定义一个函数, 实现遍历数组. (只要别人传递数组给函数, 就要求输出数组中所有元素的值)      

        #include <stdio.h>
        void printArray(int values[5]); 

        int main(int argc, const char * argv[]) {  
            int nums[3] = {1 , 3 , 5};
            printf("size = %i\n", sizeof(nums));  //  size = 12    
            printArray(nums); // 数组名称就是数组的地址
            return 0;    
        } 

        void printArray(int values[5])
        {
            printf("size = %i\n", sizeof(values));  //  size = 8    
            // 1.动态计算数组的元素个数
            int length = sizeof(values) / sizeof(values[0]);
            // 2.遍历数组
            for (int i = 0; i < length; i++) {
                printf("values[%i] = %i\n", i,values[i]);  // 输出: values[0] = 0  values[1] = 3
            }
        }                         

  改正后(能正确输出数组的所有元素):    

        #include <stdio.h>
        void printArray(int values[5], int length); 

        int main(int argc, const char * argv[]) {  
            int nums[3] = {1 , 3 , 5};
            printf("size = %lu\n", sizeof(nums));  //  size = 12   
            int length = sizeof(nums) / sizeof(nums[0]);    
            printArray(nums, length);
            return 0;
        } 

        void printArray(int values[5], int length)
        {
            printf("size = %lu\n", sizeof(values));  //  size = 8 
            // 遍历数组
            for (int i = 0; i < length; i++) {
                printf("values[%i] = %i\n", i,values[i]);  // values[0] = 0  values[1] = 3    
            }
        } 

数组练习:    

#include <stdio.h> 

int main(int argc, const char * argv[]) {
    // 要求从键盘输入6个0~9的数字,排序后输出
    // 1.定义数组保存用户输入的数据
    int nums[10] = {0};
    // 2.接收用户的数据
    int value = -1;
    for (int i = 0; i < 6; i++) {
        printf("请输入第%i个数据\n", i + 1);
        scanf("%i", &value);
        nums[value] = nums[value] + 1;
    }
    
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < nums[i]; j++) {
            printf("%i\n", i); // 1, 1, 2, 3, 3, 6
        }
    }   
    return 0;
}
/*
 1. nums[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 2. 用户输入的数组当做数组索引
 3. 输入一次  索引对应的值 + 1
 输入 1, 1, 2, 3, 3, 6之后
 数组对应值 : nums[10] = {0, 2, 1, 2, 0, 0, 1, 0, 0, 0};
 下标:                   0  1  2  3  4  5  6  7  8  9
 4. 然后对数组排序输出
 */ 

数组排序:

  冒泡排序

     

    int nums[6] = {99, 12, 88, 34, 5, 7};
    int length = sizeof(nums) / sizeof(nums[0]);
    for (int i = 0; i < length - 1; i++) {
        for (int j = 0; j < length - 1 - i; j++) {
            if (nums[j] > nums[j + 1]) {
                int temp = nums[j];
                nums[j] = nums[j + 1];
                nums[j + 1] = temp;
            }
        }
    } 

  选择排序:

     

        int nums[8] = {99, 12, 88, 34, 5, 44, 12, 100};
        int length = sizeof(nums) / sizeof(nums[0]);
        for (int i = 0; i < length - 1; i++) {
            for (int j = i+1; j < length; j++) {
                if (nums[i] > nums[j]) {
                    int temp = nums[i];
                    nums[i] = nums[j];
                    nums[j] = temp;
                }
            }
        }    

  选择--冒泡排序优化(提取函数)

    #include <stdio.h>
    void selectSort(int nums[], int length);
    void printArray(int nums[], int length);
    //void swap(int v1, int v2);
    void swap(int nums[], int i, int j);
    void bubbleSort(int nums[], int length); 

    int main(int argc, const char * argv[])
    {
        // 已知一个无序的数组, 里面有5个元素, 要求对数组进行排序
        int nums[8] = {99, 12, 88, 34, 5, 44, 12, 100};
        int length = sizeof(nums) / sizeof(nums[0]);    
        printArray(nums, length);    
        bubbleSort(nums, length);
        printf("----------------\n");    
        printArray(nums, length);
        return 0;
    }
    // 遍历数组
    void printArray(int nums[], int length)    
    {
        for (int i = 0; i < length; i++) {
            printf("nums[%i] = %i\n", i, nums[i]);
        }
    }
    void bubbleSort(int nums[], int length)
    {
        for (int i = 0; i < length - 1; i++) {
            for (int j = 0; j < length - 1 - i; j++) {
                if (nums[j] > nums[j + 1]) {
                    swap(nums, j, j+1);
                }
            }
        }
    }
     // 选择排序
    void selectSort(int nums[], int length)
    {
        for (int i = 0; i < length - 1; i++) {
            for (int j = i+1; j < length; j++) {
                if (nums[i] > nums[j]) {
                    /*
                    int temp = nums[i];
                    nums[i] = nums[j];
                    nums[j] = temp;
                     */
    //                swap(nums[i], nums[j]);
                    swap(nums, i, j);
                }    
            }
        }
    } 
    // 基本数据类型作为函数的参数, 是值传递, 在函数中修改形参不会影响实参的值
    /*
    void swap(int v1, int v2)
    {
        int temp = v1;
        v1 = v2;
        v2 = temp;
    }
     */
    // 交换两个数的值
    void swap(int nums[], int i, int j)
    {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;    
    } 

折半查找:

  思路:

    在有序表中,取中间元素作为比较对象,若给定值与中间元素的要查找的数相等,则查找成功;

    若给定值小于中间元素的要查找的数,则在中间元素的左半区继续查找;

    若给定值大于中间元素的要查找的数,则在中间元素的右半区继续查找。

    不断重复上述查找过 程,直到查找成功,或所查找的区域无数据元素,查找失败。

       

      

  #include <stdio.h>
  #include <time.h>
  int findKey(int nums[], int key, int length);
  int findKey2(int nums[], int length, int key);
  int findKey3(int nums[], int length, int key); 

  int main(int argc, const char * argv[]) {
      // 现在已知一个有序的数组, 和一个key. 要求从数组中找到key对应的索引的位置
      // 对该方法进行封装, 要求找到就返回对应的索引, 找不到就返回-1
      int nums[500000] = {1, 3, 5, 7, 9, [499999] = 99};
      int key = 99;
      int length = sizeof(nums) / sizeof(nums[0]);  

       // 消耗了1640毫秒
      clock_t startTime = clock();
      int index =  findKey(nums, key, length);
      clock_t endTime = clock();
      printf("消耗了%lu毫秒\n", endTime - startTime);
      printf("index = %i\n", index);  
      
      // 消耗了3毫秒
      clock_t startTime = clock();
      int index = findKey2(nums, length, key);
  
      // 消耗了2毫秒
      int index = findKey2(nums, length, key);
      clock_t endTime = clock();
      printf("消耗了%lu毫秒\n", endTime - startTime);
      printf("index = %i\n", index);   
      return 0;
  }  
 
  int findKey3(int nums[], int length, int key)
  {
      int min, max, mid;
      min = 0;
      max = length - 1;   
      // 只要还在我们的范围内就需要查找
      while (min <= max) {
          // 计算中间值
          mid = (min  + max) / 2;
          if (key > nums[mid]) {
              min = mid + 1;
          }else if (key < nums[mid])
          {
              max = mid - 1;
          }else
          {
              return mid;
          }        
      }
      return -1;
  }
 
  int findKey2(int nums[], int length, int key)
  {
      int min, max, mid;
      min = 0;
      max = length - 1;
      mid = (min + max) / 2;    
      while (key != nums[mid]) {
          // 判断如果要找的值, 大于取出的值, 那么min要改变
          if (key > nums[mid]) {
              min = mid + 1;
          // 判断如果要找的值, 小于取出的值, 那么max要改变
          }else if (key < nums[mid])
          {
              max = mid - 1;
          }
          // 超出范围, 数组中没有需要查找的值
          if (min > max) {
              return -1;
          }
          // 每次改变完min和max都需要重新计算mid
          mid = (min + max) / 2;
      }
      return mid; 
  }  

  //循环遍历查找
  int findKey(int nums[], int key, int length)
  {
      for (int i = 0; i < length; i++) {
          if (nums[i] == key) {
              return i;
          }
      }
      return -1;
  }   

进制转换查表法:

#include <stdio.h>
void total(int value, int base, int offset);
void ptintBinary(int num);
void printfOct(int num);
void printfHex(int num); 

int main(int argc, const char * argv[]) {
// ptintBinary(10); // printfOct(10); printfHex(10); return 0; } //转十六进制 void printfHex(int num) { total(num, 15, 4); } //转八进制 void printfOct(int num) { total(num, 7, 3); } //转二进制 void ptintBinary(int num) { total(num, 1, 1); } // 转换所有的进制 // value就是需要转换的数值 // base就是需要&上的数 // offset就是需要右移的位数 void total(int value, int base, int offset) { // 1.定义一个数组, 用于保存十六进制中所有的取值 char charValues[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; // 2.定义一个数组, 用于保存查询后的结果 char results[32] = {'0'}; // 3.定义一个变量, 用于记录当前需要存储到查询结果数组的索引 int pos = sizeof(results)/ sizeof(results[0]); while (value != 0) { // 1.取出1位的值 int res = value & base;// 1 7 15 // 2.利用取出来得值到表中查询对应的结果 char c = charValues[res]; // 3.存储查询的结果 results[--pos] = c; // 4.移除二进制被取过的1位 value = value >> offset;// 1 3 4 } // 4.打印结果 for (int i = pos; i < 32; i++) { printf("%c", results[i]); } printf("\n"); }

 

 

 

 posted on 2015-08-24 23:20  X230  阅读(222)  评论(0编辑  收藏  举报