嵌入式学习-排序算法

目录

选择排序:

冒泡排序:

非原地插入法

原地插入排序

二分查找

总结

字符型数组

数组初始化:

字符串终止符:

注意

gets、puts语句

int puts(const char *s);

  char *gets(char *s);


选择排序:

选择排序的操作步骤

  1. 初始化

    • 设定一个待排序数组 arr,数组长度为 n
  2. 排序过程

    • 外层循环:从 0 到 n-2,控制当前的排序位置 i
      • 内层循环:从 i+1 到 n-1,用于寻找最小元素的位置。
        • 在内层循环中,比较当前位置 i 的元素与从 i+1 到 n-1 的每个元素。
        • 将比较后比 i 位置值大的数与当前位置 i 的元素交换。
      • 重复:继续执行外层循环,直到排序完成

作用:将一组数据从小到大排列。

思想:先从前面第一个数开始往后面比较(利用for循环),如果后面的数比这个数还小,则交换数据,再用这个小的数去和后面剩下的数比较,第一个数比较完后,第一个位置就存放了最小的数,在第一个for循环里面再添加一个for循环,开始比较第二个数,注意此时只需要从第三个数开始比较,直到比完,依次类推,越往后需要比较的次数越少,最后一个数就在前一次的比较中已经将最大值放在了最后一位,所以外部for循环主要换到 第 len-2个位置就行了  (len- 2 < len -1) 。

  1 #include <stdio.h>
  2 int main()
  3 {
  4     int a[] = {1,2,3,4,5,6,7,8,9,0};
  5     int len = sizeof(a) / sizeof(a[0]);
  6     int i,j;
  7     for(i = 0;i < len -1;i++)//1-10个位置,i代表在数组中的对应位置
  8     {
  9         for(j = i + 1;j < len;j++)//j=i+1从a[i]后面一个开始比较,直至最后一个
 10         {
 11             int num;
 12             if(a[i] > a[j])//如果后面的数有比a[i]还小的数,则将大数放在后面,这样小数又到前面了,依次类推比较,最后小数在前,大数在后                         
 13             {
 14                 num = a[i];
 15                 a[i] = a[j];
 16                 a[j] = num;
 17             }
 18         }
 19     }
 20     for(i = 0;i < len; i++)
 21     {
 22         printf("%d\n",a[i]);
 23     }
 24 
 25 }
 26 

冒泡排序:

操作步骤

  1. 开始排序

    • 从数组的第一个元素开始,比较相邻的两个元素。
    • 如果前一个元素大于后一个元素,则交换它们的位置。
  2. 重复比较与交换

    • 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。
    • 在这一轮比较结束时,最大的元素会被“冒泡”到数组的末尾。
  3. 持续进行

    • 针对所有的元素重复以上的步骤,但每次循环都忽略已经排序好的末尾部分。
    • 持续对越来越少的元素重复上述步骤,直到没有任何一对数字需要比较。
  4. 排序完成

    • 当整个数组都按照升序(或降序)排列时,排序过程结束。

作用:将一组数据从小到大排列。

思想:冒泡法一次冒泡只将一个数送给到合适位置,将大数往后送,外层循环控制冒几次泡(也就是从当前位置往后对比几趟),每次冒泡随着次数越多,后面大数确定位置越多,从头开始比较 次数也越少。冒泡法只跟自己的后面一个比较,如果后面的数小,则互换,将大数往后面运输。

总结 :一次冒一个数,相邻两个元素两两比较,小的放前,大的换后。

 1 #include <stdio.h>
  2 int main()
  3 {
  4     int i,j,temp;
  5     int a[] = {9,8,7,6,5,4,3,2,1,0};
  6     int len = sizeof(a) / sizeof(a[0]);
  7 
  8     for(i = len - 1;i > 0;--i)//冒泡法一次只将一个数送到合适的位置,即将大数往后面位置送,确保最后的数最大
  9     {
 10         for(j = 0;j < i;j++)//控制每次比较多少次,越往后比的次数越少,后面的大数就已经确定了                                                                  
 11         {
 12             if(a[j] > a[j + 1])//只跟自己身后的数比较,后面的数如果比他自身小,则互换数值(即将大数忘后面传递)(注意是只跟自己身后的数比较,因此a[j]与a[j+1]>
 13             

                {
 14                 temp = a[j];
 15                 a[j] = a[j + 1];
 16                 a[j + 1] = temp;
 17             }
 18         }
 19     }
 20 
 21     for(i = 0; i < len;i++ )
 22     {
 23         printf("%4d",a[ui]);
 24     }
 25 
 26     return 0;
 27 
 28 }

插入排序

操作步骤

  1. 初始化

    • 从第二个元素(索引为1,第一个无对比,直接放入)开始,将其与前面的元素进行比较并插入到正确的位置。
  2. 遍历数组

    • 从数组的第二个元素(索引为1)开始,依次对每个元素进行插入操作。设当前元素为 key。
    • 内层循环:利用while(j > 0&&t<b[j-1])循环在已排序的部分中,从后向前遍历,找到插入 key 的正确位置。具体步骤:
      • 比较 key 与当前元素。如果 key 比当前元素小,则将当前元素向后移动一位。
      • 继续比较,直到找到合适的插入位置或已遍历完已排序部分。
  3. 插入

    • 将 key 插入到找到的位置。
  4. 重复

    • 对数组中的所有元素重复以上步骤,直到所有元素都被插入到正确的位置,数组完全有序。

非原地插入法

思想:首先创建两个一样的数组,一个存放原始数据,一个存放排序过后的数据,从原始数组a中一个一个取出数据,暂放到b对应的位置去,在对应位置后,要与b数组在此之前的数据全部比较一遍,如果前面的值比自身大,则数值互换,同时while判断条件中确保 j>=0,比完就结束,即找到该数值在b数组中的准确位置,插入排序也有两个循环,一个for循环一个while(上面两种排序方式都是两个for循环)外层for循环控制从a中一个一个数依次取出,直至取完,while循环确定插入的位置。

  1 #include <stdio.h>
  2 int main()
  3 {
  4     int t,i,j;
  5     int a[] = {9,8,7,6,5,4,3,2,1,0};
  6     int b[10];//创建一个新的一模一样的数组,用于后续存放
  7     int len = sizeof(a) / sizeof(a[0]);
  8     for(i = 0;i < len;i++)//从a数组中循环取出第i个数
  9     {
 10         t = a[i];//用t来存放取得的值
 11         j = i;//同时在b数组中找到对应的位置,然后依次往前面比较,看看自己合适在哪
 12         while(j > 0&&t<b[j-1])//跟自己前面的每一个数比较,如果前面的数比自己大则互换数值,同时while循环判断条件检查是否j=0了(即此时已经和自身前面所有的数比较过了,找到确定位置
 13         {
 14             b[j] = b[j-1];
 15             j--;
 16         }
 17         b[j] = t;//此时j--了已经在最合适的位置,将数值放进去
 18     }                                                                                                                                                         
 19     for(i = 0;i < len;i++)
 20     {
 21         printf("%3d",b[i]);
 22     }
 23     putchar('\n');
 24     return 0;
 25 }

原地插入排序

原地插入排序只有一个数组,在本数组中进行数据排列替换,空间复杂度比非原地插入法更低。

 #include <stdio.h>
  2 int main()
  3 {
  4     int t,i,j;
  5     int a[] = {9,8,7,6,5,4,3,2,1,0};
  6     int len = sizeof(a)/sizeof(a[0]);
  7 
  8     for(i = 0;i < len;i++)
  9     {
 10         t = a[i];
 11         j = i;
 12         while(j>0&&t<a[j-1])
 13         {
 14             a[j] = a[j-1];
 15             j--;
 16         }
 17         a[j] = t;
 18     }
 19     for(i = 0;i < len;++i)
 20     {
 21         printf("%d",a[i]);
 22     }
 23 
 24     putchar('\n');                                                                                                                                            
 25     return 0;
 26 }
~                        

二分查找

算法步骤

  • 初始化左右位置 begin 和 end,分别表示数组的开始和结束位置。
  • 计算中间位置 mid
  • 比较目标值与 a[mid]
    • 如果相等,break退出循环。
    • 如果目标值小于 a[mid],end = mid -1,在左半部分继续查找。
    • 如果目标值大于 a[mid],begin = mid + 1在右半部分继续查找。
    • 最后通过if检查begin和end大小,判断是否查找到数据,并输出。
 1 #include <stdio.h>
  2 int main()
  3 {
  4     int begin,end,mid,n;
  5     int a[] = {1,2,3,4,5,6,7,8,9};
  6     begin = 0;
  7     end = 8;
  8     n = 8;                                                                                                                                                           
  9 
 10     while(begin<=end)
 11     {
 12         mid = (begin + end)/2;
 13         if(a[mid]>n)
 14         {
 15             end = mid - 1;
 16         }
 17         else if(a[mid]<n)
 18         {
 19             begin = mid + 1;
 20         }else
 21             break;
 22     }
 23         if(begin<=end)
 24         {
 25             printf("found the num a[%d]\n",mid);
 26         }else
 27         {
 28             printf("not found");
 29         }
 30 
 31 
 32     return 0;
 33 }
~         

总结

  • 定义和用途:二分查找用于在有序数组中快速查找元素,具有 O(\log n)O(logn) 的时间复杂度。
  • 算法实现:可以使用迭代或递归方式实现二分查找。
  • 注意事项:确保数组有序,避免整数溢出,正确处理边界条件,考虑处理重复元素的需求,并选择适合的实现方式。

掌握这些细节可以帮助我们更有效地在 C 语言中使用二分查找算法,提升程序的性能和稳定性。

字符型数组

数组初始化:

char str[10];                           // 定义一个长度为 10 的字符数组
char str[20] = {'a','b','c','d'};       //定义一个数组部分初始化,其余位置补'\0'
char str[] = {'a','b','c','d'}          //这个数组中则没有'\0'这个结束标志
char str1[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // 显式初始化
char str2[] = "Hello";                           // 隐式初始化

字符串终止符:

     在 C 语言中,字符串以 '\0'(空字符)作为结束符。这意味着实际存储的字符数比数组的大小小 1,因为最后一个字符是用来标识字符串的结束。 

注意

  1.字符串 是 当做字符数组来处理的。
  2.字符串 有一个专门的结束标志 '\0'
  3.处理的是字符串,操作的时候,往往以 结束标志 为 操作依据 
  4.处理的是数组,操作的时候,往往以 数组长度 作为操作依据 
  5.字符数组可以用来存储字符串 
    而
    字符串在内存中存储的方式 也是以 字符数组形式存储的     
   
  "hello" --- 'h''e''l''l''o''\0'
               实际占用的内存空间,是包含了'\0'   

""  //字符串 --- 空字符串 '\0'

gets、puts语句

int puts(const char *s);

功能:
           输出一个字符串 
     参数:
         s   //表示字符串 -- 指针类型 
             //字符数组名 s
             //字符串常量 "hello"

  返回值:
          成功 非负数 
          失败 -1 
    注意:
       puts输出时 自动会加 换行


  char *gets(char *s);

功能:
         从键盘获得一个字符串 
     参数:
         s  //代表就是一块存储空间 --- 需要的是一个一维字符型数组的数组名
     返回值:
        成功 s 
        失败 NULL

1 #include <stdio.h>
  2 int main()
  3 {                                                                                                                                        
  4     char s[] = "hello";
  5     char s1[] = {'w','o','r','l','d'};//注意这里单个字符存储,没有存入‘\n’结束标志,如果你要使用s1字符数组用puts输出,当作字符串使用,它需要检测到‘\0’才会结束,但是是
中没有,所以它会往空间后面一直输出 知道遇到'\0'结束标志
  6 
  7     puts(s);
  8     puts(s1);
  9     return 0;
 10 
 11 }

排序总结:

选择排序:

                从确定位置依次比较,选择小数往前面确定的位置填进去。关键词:定位置

冒泡排序:

                从第一个数开始往自身后一个比较,大数往后放,直至填满。 关键词:大往后

插入排序:

                从第二个数开始往前比,找到自身合适位置,大往后 关键词:往前比,找位置

  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值