排序

一.数组:

1. 基本含义

  • 变量:
  1. 内存中的一块空间
  2. 数组内存中的一串连续的空间
  • 数组:是一个变量,由数据类型相同的一组元素组成

2. 数组的结构和基本要素

  • 标识符:数组的名称,用于区分不同的数组
  • 数组元素:向数组中存放的数据
  • 元素下标:对数组元素进行编写
  • 元素类型:数组元素的数据类型

3.语法

  • 声明:

     datetype  arrayNames[size];
     int nums[5] = {1, 2, 3, 4, 5};
    

4.程序示例

  • demon1
#include <stdio.h>
#define N 5		//宏定义
int main()
{
    double score[5];
    int i;      //循环变量
    //使用循环操作数组时,要注意:一个循环尽量只做一件事
    for(i = 0; i < N; i++)
    {
        printf("请输入第%d位同学的成绩:", i + 1);
        scanf("%lf", &score[i]);
    }
    //下面的循环用来打印数组元素
    for(i = 0; i < N; i++)
    {
        printf("第%d位同学的成绩是:%.2lf\n", i + 1, score[i]);
    }

    return 0;
}
  • demon2
#include <stdio.h>
int main()
{
    int i;
    int sum = 0;
    double avg; 			//求平均
    int searchNum;  		//要查找的数字
    //1.定义数组并初始化
    int nums[] = {8, 4, 2, 1, 23, 344, 12};
    //2.循环输出
    printf("输出数组元素:\n");
    for(i = 0; i < 7; i++)
    {
        printf("%d\t", nums[i]);
    }
    printf("\n******************************\n");
    //3.求和、求平均值
    for(i = 0; i < 7; i++)
    {
        sum += nums[i];  //经典累加
    }
    avg = sum / 7.0;
    printf("平均值是:%.2lf\n", avg);
    //4.查找数字
    printf("请输入要查找的数字:");
    scanf("%d", &searchNum);
    for(i= 0; i < 7; i++)
    {
        if(searchNum == nums[i])	//一个一个元素对比
        {
            printf("找到了!\n");
            break;
        }
    }
    if(i == 7)
        printf("茫茫人海,你在哪里!\n");
    return 0;
}

二.冒泡排序:

1. 降序排列

  • 冒泡排序的基础原理:遍历和交换
  • 排序
  1. 每轮轮循环:当前数字小于后面的数字,则进行交换
  2. 第一轮比较次数 = 数组长度 - 1
  3. 需要多轮循环,每一轮循环比较次数比上一轮减1次

demon

 #include <stdio.h>
#define N 5 //宏定义
int main()
{
    //冒泡排序
    int i, j;   //循环变量
    int nums[N] = {16, 25, 9, 90, 23};
    int temp;   //用来交换的临时变量
    //外层循环控制轮数
    for(i = 0; i < N - 1;i++ )
    {
        //内层循环控制每轮的比较次数
        for(j = 0; j < N - i - 1;j++)
        {
            //如果当前值小于后面就交换
            if(nums[j] < nums[j + 1])
            {
                temp = nums[j];
                nums[j] = nums[j + 1];
                nums[j + 1] = temp;
            }
        }
    }
    printf("排序后的结果是:\n");
    for(i = 0; i < N; i++)
    {
        printf("%d\t", nums[i]);
    }
    return 0;
}

2. 逆序排列

  • 数组有序:

     逆序采用冒泡排序的方式
    
  • 数组无序:

      1.第一个元素与最后一个交换
      2.第二个元素与倒数第二个交换	
      3.归纳可知第 i 个元素与第(N - i - 1)个元素交换
      4.数组元素偶数个逆序进行N/2次交换,奇数个进行(N - 1)/2次交换
    

demon

#include <stdio.h>
#define N 5
int main()
{
    //逆序排列
    int i;   //循环变量
    int temp;   //临时变量
    int nums[N] = {12, 34, 23, 67, 9};

    for(i = 0; i < N / 2 ; i++)     //进行N/2次即逆序排列,若是N次互换将会还原
    {
            temp = nums[i];
            nums[i] = nums[N - i -1];
            nums[N - i - 1] = temp;
    }
    printf("输出排序后的数组元素:\n");
    for(i = 0; i < N; i++)
    {
        printf("%d\t", nums[i]);
    }
    return 0;
}

3. 数组元素的删除和插入

  • 删除的逻辑

      1.查找删除数字的下标
      2.从下标开始,后面一个覆盖前面一个数字	
      3.数组总长度 - 1
    
  • 添加元素:

      在数组预留空间足够的情况下,添加数值即可
    

demon

#include <stdio.h>
int main()
{
    //根据要求操作排行榜战力值
    int i, j;   //定义循环变量
    double temp;    //定义临时变量
    int count = 5;
    double powers[] = {41000, 42000, 43000, 44000,45000};
    double deletePower;   //用户要删除的战力值
    int deleteIndex = -1;    //要删除战力值的下标,给一个不可能的值
    double insertPowers;
    //排序
    for(i = 0; i < count -1; i++)
    {
        for(j = 0; j < count - i - 1; j++)
        {
            if(powers[j] < powers[j + 1])
            {
               temp = powers[j];
               powers[j] = powers[j + 1];
               powers[j + 1] = temp;
            }
        }
    }
    printf("战力值从大到小排列为:");
    for(i = 0; i < count; i++)
    {
        printf("%lf\t", powers[i]);
    }
    //删除某个战力值
    printf("\n请输入要删除的战力值:");
    scanf("%lf", &deletePower);
    for(i = 0; i < count; i++)
    {
        if(deletePower == powers[i])
        {
            //记录下当前的下标
            deleteIndex = i;
            break;
        }
    }
        if(-1 == deleteIndex)   //判断是否找到
    {
        printf("很遗憾,没有找到要删除的战力值,删除失败!\n");
    }
    else
    {
        //从下标开始,后面一个覆盖前面一个数字
        for(i = deleteIndex; i < count - 1; i++)
        {
            powers[i] = powers[i + 1];
        }
        count--;     //删除完毕后,一定记得数组的总长度-1 障眼法要做到底
    }
    printf("删除后的结果为:");
    for(i = 0; i < count; i++)
    {
        printf("%lf\t", powers[i]);
    }
    //插入一个战力值,并按降序排列
    printf("\n输入想要插入的战力值:");
    scanf("%lf", &insertPowers);
    powers[count] = insertPowers;   //插入元素
    count++;
    printf("插入后的元素:");
    for(i = 0; i < count; i++)
    {
        printf("%lf\t", powers[i]);
    }
    for(i = 0; i < count; i++)   //升序排列
    {
        for(j = 0; j < count -i -1; j++)
        {
            if(powers[j] > powers[j + 1])
            {
                temp = powers[j];
                powers[j] = powers[j + 1];
                powers[j + 1] = temp;
            }
        }
    }
    printf("\n升序排列为:");
    for(i = 0; i < count; i++)
    {
        printf("%lf\t", powers[i]);
    }
    return 0;
}

4. 二维数组

  • 二维数组

     声明:datatype  names[size_row][size_column];
    

demon1

#include <stdio.h>
#define ROW 3
#define COL 3

int main()
{
    //使用二维数组表示4个学生3门成绩表
    double scores[ROW][COL];
    int i, j;   //定义循环变量
    for(i = 0; i < ROW; i++)
    {
        for(j = 0; j < COL; j++)
        {
            printf("第%d位同学的第%d门课成绩:", i + 1, j + 1);
            scanf("%lf", &scores[i][j]);
        }
    }
    //打印成绩
    for(i = 0; i < ROW; i++)
    {
        for(j = 0; j < COL; j++)
        {
            printf("%.2lf\t", scores[i][j]);
        }
        printf("\n");
    }
    return 0;
}

demon2

#include <stdio.h>
#define R 4
#define C 3
int main()
{
    int i, j;   //定义循环变量
    double  scores[R][C];   //定义一个4行3列的数组
    //= {{80, 85, 90}, {81, 86, 92}, {82,91,90}, {79, 88, 80}}
    //录入成绩
    printf("科目\t语文\t英语\t数学\n");
    for(i = 0; i < R; i++)
    {
        printf("学生%d\t", i + 1);
        for(j = 0; j < C; j++)
        {
            scanf("%8lf", &scores[i][j]);
            printf("\t");
        }
        printf("\n");
    }
    //打印成绩
    printf("科目\t语文\t英语\t数学\n");
    for(i = 0; i < R; i++)
    {
        printf("学生%d\t", i + 1);
        for(j = 0; j < C; j++)
        {
            printf("%-4.2lf\t", scores[i][j]);  //负号左对齐
        }
        printf("\n");
    }
    return 0;
}

快速排序的基本思路:

 1.从需要排序的数据中,找到一个适当的基准值(pivot)
 2.将需要排序的数据按照小于pivot和大于pivot进行分类
 3.对分类后的两类数据各自进行上述的1和2的处理

第二部分类:

 1. 从左向右,检索比pivot大的数据
 2. 从右向左,检索比pivot小的数据
 3. 如果两个方向都能搜索到数据,将找到的数据交换
 4. 重复进行1-3的操作,直到从左开始检索的下标和从右开始检索的下标冲突为止

快速排序代码:

#define SWAP(a, b) {int temp; temp = a; a= b; b = temp;};

void quick_sort_sub(int *data, int left, int right)
{
    int left_index = left;
    int right_index = right;
    int pivot = data[(left + right)/2];
    
    while(left_index <= right_index)
    {
        for(; data[left_index] < pivot; left_index++)
            ;
        for(; data[right_index] < pivot; right_index--)
            ;
        if(left_index <= right_index)
        {
            SWAP(data[left_index], data[right_index]);
            left_index++;
            right_index--;
        }
    }
    if(right_index > left)
    {
        quick_sort_sub(data,left, right_index);
    }
    if(left_index < right)
    {
        quick_sort_sub(data, left_index, right);
    }
}

void quick_sort(int *data, int data_size)
{
    quick_sort_sub(data,0, data_size - 1);
}

注解:

1.这个程序将数组分成两部分之后,再进行递归调用。
2.此时,**在栈中分配了新的用于当前部分数组的内存区域**。
3.另外,当某部分数组的数据处理完毕,函数调用返回的时候,栈会收缩,调用前的状态恰好处于栈的最初位置。
4.正因为如此,处理才这样不断地向右移动。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值