嵌入式学习第七天——C语言——数组排序与查看和字符数组

C语言数组排序、查找与字符数组学习

排序

排序:
   排序 --- 将数据按照 从大到小(降序) 或者 从小到大(升序) 排列

在C语言中,规定排序的顺序是升序。

选择排序

   思想与算法:

给一个位置选择合适的值。

例如:

想要在位置0处存放最小的值,将位置0的值先与位置1的值比较,如果位置1的值小于位置0的值,则两值互换。再将现在位置0的值与位置2的值比较,存放小值,以此类推,最后位置0会存放这个数组中的最小值。

代码实现:

for(int j=1;j<n;j++)
{
   if(a[0]>a[j])
   {
      交换a[0]和a[j];
    }
}

接下来想要在位置1存放第二小的值,就不断将每次的位置1的值与之后位置的值进行比较,存放小值,最后位置1就会存放位置1到位置7中最小的值了。

可以看出,在每个位置存放合适的值是在不断重复的操作,这就可以看成是一个循环中的循环体,这个循环做的就是决定放值的位置,而且只需要决定n-1个位置,当其他位置都确定后,最后的位置自然就存放着最后存放的值,至于寻找合适的数则是循环体在做。

所以,选择排序,就是在合适的位置选择合适的值来存放,最终实现升序排序的功能。

代码主体如下:

for(i=0;i<n-1;i++)
{
    for(j=i+1;j<n;j++)
{
       if(a[i]>a[j])
       {
           交换;
        }
}
}

冒泡排序

   思想与算法

给一个值合适的位置。

例如:

想要把数组中最大的数存放到位置7处。先将位置0和1的两值比较,把大值存放到位置1,再把1和2进行比较,大值存放到2,再2和3,3和4。。。最后,一定是把最大的值存放到了最后一位。

代码实现

for(j=0;j<n-1;j++)
{
   if(a[j]>a[j+1])
     交换;
}

然后再从位置0开始,就可以把第二大的值存放到倒数第二位,以此类推,将这个代码运行n-1次,最后可以实现升序排序的功能。但是需要注意,在每次确定一个数后,需要确定的数就减少一个,这个比较的次数就减少一次。例如上图,第一趟有八个数,需要比较7次,但第二趟只有7个数,只需要比较6次了。

所以可以在外面再套一个循环,来说明这是在第几趟了,从而控制比较次数,需要注意的是,外层循环与初始化和结束条件无关,只需要它能循环n-1趟即可。例如:for(i=0;i<n-1;i++) for(i=1;i<n;i++) for(i=n-1;i>0;i--)

所以我们可以据此写出冒泡排序的代码主体:

for(i=1;i<n;i++)
{
    for(j=0;j<n-i;j++)
{
       if(a[j]>a[j+1])
            交换;
}
}

插入排序

    思想与算法

找到一个合适的位置,进行插入。

例如:

给a[0]在b数组中找一个位置,由于a[0]是第一个数,此时,b数组中没有数,所以a[0]存放到b[0]。

再拿出a【1】,此时想要给a【1】找位置则需要与b【0】作比较,如果a【1】小于b【0】,则a【1】需要存到b【0】处,那么b【0】的值就需要往后挪,即b【1】存放原b【0】的值,b【1】=b【0】,b【0】=a【1】。(注意,这并不是交换。)我们再拿出a【2】,想要给它找一个位置,那么就让它与应该在b中存放的位置b【2】的前一个位置b【1】进行比较,小于就b【2】=b【1】,再与b【0】比较,大于就b【1】=a【2】。以此类推,我们不断的从a中拿出一个数然后在b中找一个合适的位置插入,最后实现升序的排序。

这种不断重复的操作完成就是一个循环,我们可以把拿数据写成外层的循环,找位置写成内层的循环,用双层循环实现插入排序。

代码主体如下:

for(i=0;i<n;i++)
{
     //a[i]
    j=i;
     while(j>0 && a[i] < b[j-1])
      {
            b[j]=b[j-1];
             j--;
      }
        b[j]=a[i]; //当不进入这个循环时,意味着j=0或者a[i]>b[j-1],
                   //此时意味着a[i]找到了自己的位置:
                   //数组最前面或是b[j]
}

以上,是对a数组中的数据在b数组中进行了插入排序,但这种方法需要额外创建一个数组空间,会额外占用内存空间,所以在下面还会说明一个在a数组内部完成插入排序的方法。

由于思路与算法和上述大同小异,所以仅贴出代码,附有注释

代码主体:

for(i=0;i<n;i++) //从a中拿数据
{
      int t=a[i]; //准备插入的数据
       j=i;       //准备插入的位置
      while(j>0&&t<a[j-1]) //找一个能插入的位置
  {
         a[j]=a[j-1];
            j--;
  }
     //得到了一个能插入的位置
       a[j]=t;  //插入数据
}

*快速排序

(暂未学习)

算法的性能

大O算法

透视一维数组

数据类型 
 int a[10];//整型的一维数组 
 数组也是一种数据类型 


 
 数组的类型 


 //方法:
 //去掉标识符 剩下就是对应的数据类型 
 int[10] //数组类型 --- 表示这是一个数组 ---是一个能够存放10个int型数据的数组 
 int[20] 


 int[10]  a; //理解的角度 把a理解成变量名 这样没问题 ---但是c语法不支持写成这样 
  
 //数组名
 数组名 
  printf("sizeof(a) = %ld\n",sizeof(a)); //
  1.数组名 --代表数组                                //从数据类型的角度看 --数组名 --代表数组这种类型  
  2.数组名 --代表数组首元素的地址          //从值的角度看 -- 数组名 代表数组首元素的地址 
  3.数组名代表数组首元素的地址 参与到运算中 ,用的其实是这个值 
   数组名 是个常量 
 
 //可变长数组 
   int a[n]; //c99 标准后,数组长度可以是个变量
   注意:
    int a[n]; //要求: 不能初始化,且n需要先有值

查找

二分查找

前提:有序数组

思想与算法

通过把需要查找的值不断与数组中间值进行比较来查找的方法。

1.需要先找到中间位置,2.再与中间值进行比较。

我们可以定义数组序号的开头,结尾,和中间分别为begin,end,mid。

令begin=0(数组的第一个值的序号),end=len(数组长度),mid=(begin+end)/2

输入需要查找的数n,当n<a[mid]时,意味着在数组的左边,这时令end=mid-1,就可以再得到新的中间位置,n>a[mid]时,令begin=mid+1即可。我们就可以继续判断n与中间值的关系来不断的缩小需要查找的范围。在最后,begin与end重合,得到的mid也会重合,这时我们可能得到两种结果,找到或者没找到。例如n=-1,最后mid位于0,这时a[mid]>n,又会begin=mid+1,这时begin>end,显然这是不行的,所以我们应该限制,begin<=end。如果找到了,n=a[mid]。

代码主体如下:

while(begin<=end)
{
     mid=(begin+end)/2;
    if(a[mid]>n)
     {
         end=mid-1;
     }else if(a[mid]<n)
     {
         begin=mid+1;
     }else
     {
        break;
     }
}
     if(begin<=end)
{
       printf("找到了"); 
}else
{
       printf("not");
}

字符数组

处理 字符串 数据的

主要用途---用来存放字符串数据 
"hello" //字符串常量  
 
"hello" //整体的含义    --- 字符串 --- 一串字符 

字符串 是一种特殊的字符型一维数组 

 char s[10] = {'h','e','l','l','o'};  
 char s[10] = {'h','e','l','l','o','\0'};  
   
 数组特点:
 1.连续性 
 2.单一性 
 3.有序性 
 
 字符串 特殊在 ---它始终有一个 结束标志 '\0'
 "hello"  ---内存中示意--> 'h','e','l','l','o','\0'
 char s[10] = "hello";

puts()

int puts(const char *s);
 功能:
   输出一个字符串 
 参数:
  @s   --- 需要的是一个字符串的首地址 
         //传 字符型数组的数组名 即可 
         // "hello" 
返回值:
  成功  非负数 
  失败  -1 
  
  输出效果默认 带有 换行 

gets()

char *gets(char *s);
   功能:
       从键盘标准输入获得字符串 
   参数:
     @s  表示存放字符串数据的一块空间的起始地址 
   返回值:
     成功 s
     失败 NULL 
     
  注意:
     gets 很容易导致数组越界 带来 栈奔溃 
     scanf 也可以输入字符串 ,但是不能输入带 空格字符串 
     scanf 也会导致数组越界 带来 栈奔溃

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值