首页 > 其他分享 >内部排序

内部排序

时间:2022-09-19 14:46:55浏览次数:57  
标签:内部 记录 int 基准值 关键字 key 排序

排序分为内部排序和外部排序,区别在于存储数据的位置。

内部排序分别有五类:插入、选择、交换、归并和分配排序。

排序过程有两个操作:一是比较关键字大小,二是记录的移动或改变。

(1)插入排序

基本思想:每次将待排序的记录按关键字的大小插入到前面已经排序好的适当位置,直到全部记录插入完成。

主要方法:直接插入排序和希尔插入排序。

   //直接插入排序
    int i, j;
    //因为比较防止数组越界
    for(i = 2; i <= n; i++) {
        //判断是否小于有序区最小值
        if(R[i].key < R[i-1].key) {
            R[0] = R[i];//保留当前位置值
            //从有序区最大值依次比较以确定插入合适位置
            for(j = i - 1; R[0].key < R[j].key; j--)
                R[j+1] = R[j];
            //插入当前比较的值    
            R[j+1] = R[0];
        }
    }
View Code

希尔排序基本思想:通过一个整数作为增量进行分组内进行直接插入排序,直到增量等于1时把所有元素在一组内排序。

void ShellInsert(SeqList R, int dk, int n) {
    int i, j;
    //从增量加一开始,等于多少个增量分组
    for(i = dk+1; i <= n; i++) {
        //判断每个分组内是否需要交换位置
        if (R[i].key < R[i-dk].key) {
            R[0] = R[i];//临时存储最小值
            j = i - dk;
            while(j > 0 && R[0].key < R[j].key) {
                //交换同一个组内值
                R[j+dk] = R[j];
                j = j - dk;
            }
            R[j+dk] = R[0];
        }
    }
}

void ShellSort(SeqList R, int d[], int t, int n) {
    int k;
    //d增量数组[5,3,1]
    for(k = 0; k < t; k++)
        ShellInsert(R, d[k], n);
}
View Code

(2)选择排序

基本思想:每次将待排序记录关键词最小记录,依次放在排序好的记录最后,直到全部记录排序完成。

主要方法:直接选择排序和堆排序两种。

//直接选择排序
    int i, j, k;
    for (i = 0; i < n; i++) {
        k = i;//插入初始值
        for (j = i + 1; j <= n; j++) {
            if (R[j].key < R[k].key)//更新最小值位置
                k = j;
        }
        //如果位置有变化表示更新值
        if (k != i) {
            R[0] = R[i];
            R[i] = R[k];
            R[k] = R[0];
        }
    }
View Code

堆排序是一种树型选择排序,基本思想是把数组当成一棵完全二叉树的顺序存储结构,堆的定义是n个记录的序列k1, k2, ..., kn称为堆,满足每个子树的根大于叶子结点为大根堆,小于为小根堆。

每一次建堆把堆中最顶端根的值排序到已经记录中,直到排序完成。

void Sift(SeqList R, int i, int h) {
    int j;
    RecType x = R[i];//从树的结点开始
    j = 2 * i;//当前结点的子树
    //只要满足树的高度
    while (j <= h) {
        //判断是否有右结点
        if (j < h && R[j].key < R[j+1].key)
            j++;
        //如果当前结点大于子树结点跳过
        if (x.key >= R[j].key)
            break;
        //移动结点到   
        R[i] = R[j];
        //继续找子树的子树
        i = j;
        j = i * 2;
    }
    //保存初始结点的内容
    R[i] = x;
}

void HeapSort(SeqList R, int n) {
    int i;
    //初始堆
    for (i = n / 2; i > 0; i--)
        Sift(R, i, n);

    for (i = n; i > 1; i--) {
        //交换最后结点和根结点
        R[0] = R[1];
        R[1] = R[i];
        R[i] = R[0];
        Sift(R, i, i-1);//从剩余结点中获取最大值
    }
}
View Code

(3)交换排序

基本思想:两两比较待排序记录的关键字,发现两个记录的次序相反是进行交换,直到所有记录都没有反序为止。

主要方法:冒泡排序和快速排序。

冒泡排序基本思想:通过相邻元素之间的比较和交换,使关键字较小的元素逐渐从底部移向顶部。

int i, j , flag;
    for (i = 1; i < n; i++) {
        flag = 0;//判断是否有交换
        //从最后元素开始直到第二个元素
        for (j = n; j >= i+1; j--) {
            //判断当前元素小于前一个元素的值进行交换
            if (R[j].key < R[j-1].key) {
                R[0] = R[j-1];
                R[j-1] = R[j];
                R[j] = R[0];
                flag = 1;
            }
        }
        if(flag == 0) return;
    }
View Code

快速排序的基本思想:从所有元素中任选一个值作为基准,以它为分界拆成两个集合,然后分界左边位置的值小于基准值,右边的位置值大于基准值,这样称为一趟快速排序。具体操作设两个指针i和j,它们初始值为low和high,其基准值为x=R[i],首先从j所指向的位置向前搜索直到找到小于基准值得关键字存入当前i所指向的位置,i自增1,然后从i开始位置向后搜索大于基准值的关键字存入当前j的位置,j自减1,重复这个过程直到i等于j为止,完成一趟快速排序过程。

int Partition(SeqList R, int i, int j)
{
    RecType x = R[i];//基准值
    //满足i等于j一趟排序完成
    while (i < j) {
        //从后往前寻找小于基准值的关键字
        while (i < j && R[j].key >= x.key)
            j--;
        //如果不是同一个位置
        if (i < j) {
            //交换当前位置关键字
            R[i] = R[j]; 
            i++;
        }
        //从前往后寻找大于基准值的关键字
        while (i < j && R[i].key <= x.key)
            i++;
        if (i < j) {
            R[j] = R[i];
            j--;
        }
    }
    //最后为基准值
    R[i] = x;
    //以基准值下标作为后面排序关键点
    return i;
}
/**
 * @brief 
 * 快速排序
 * @param R 
 * @param low 
 * @param high 
 */
void QuickSort(SeqList R, int low, int high) {
    int p;
    if (low < high) {
        p = Partition(R, low, high);//划分中间
        QuickSort(R, low, p-1);//左分区
        QuickSort(R, p+1, high);//右分区
    }
}
View Code

 (4)归并排序

 基本思想:把待排序的文件n个长度的为1的有序子文件,这些文件两两归并,获得【n/2】个长度2的有序子文件,然后再重复进行,直到一个长度n的有序文件。

   (5) 分配排序

  箱排序基本思想:设置若干箱子,依次扫描待排序记录,把关键字等于k的记录全部装入第k个箱子里,然后按序号依次将各非空的箱子首尾连接起来。

标签:内部,记录,int,基准值,关键字,key,排序
From: https://www.cnblogs.com/Python-233/p/16390931.html

相关文章

  • java-stream-内部类
    一、概述按网上的说法,内部类分为4种:1,成员内部类,类似于对象的成员变量;需要通过外部类对象创建;2,静态内部类,类似于类的static变量;直接通过类创建;3,局部内部类,类似于方法(作......
  • 0-4 测试面试题_16合并两个排序数组_17tcp和udp_18单元集成系统验收回归_19测试和开发
    面试题(除个别外)及部分解析答案来自牛客网https://www.nowcoder.com/exam/interview/以下所述内容并不是百分之百正确,仅供参考。16手写代码:合并两个排序数组Merge1......
  • js数组sort()方法按指定顺序排序
    一、sort介绍数组的sort()方法可以把数组排序,不传参数的默认按字典排序sort()方法还接受一个回调函数,按回调函数内代码逻辑排序该函数要比较两个值,然后返回一个用于说明这......
  • DataTable中数据记录的排序,检索,合并,分页,统计(整理)(转)
    一、排序1获取DataTable的默认视图2对视图设置排序表达式3用排序后的视图导出的新DataTable替换就DataTable(Asc升序可省略,多列排序用","隔开)DataViewdv=dt.Default......
  • 1636. 按照频率将数组升序排序【模拟】
    题目给你一个整数数组nums,请你将数组按照每个值的频率升序排序。如果有多个值的频率相同,请你按照数值本身将它们降序排序。请你返回排序后的数组。难度:简单提示:......
  • 034每个进程占用内存排序
    一、  #ps-aux|head-n2  USERPID%CPU%MEMVSZRSSTTYSTATSTARTTIMECOMMAND  root10.00.019633213704?......
  • [算法]循环排序
    这类题的特点是给定的数值和下表rank是类似的,其中可能会有一些差异.在设计算法的时候,可以将value值映射到rank上去.其中,选择大于的值最好比rank的最大值+1,这样会避......
  • 1636. 按照频率将数组升序排序
    1636.按照频率将数组升序排序给你一个整数数组 nums ,请你将数组按照每个值的频率升序排序。如果有多个值的频率相同,请你按照数值本身将它们降序排序。 请你返......
  • 内部类
    内部类在方法体或代码块局部内部类1、可以访问外部类的所用成员,包括私有的2、不能添加访问修饰符,因为局部内部类跟局部变量一样,可以加final关键字。3、作用域:仅仅在定......
  • cmd 'node' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
    报错:cmd提示:‘node‘不是内部或外部命令,也不是可运行的程序原因:没安装node.js或者没配置好环境变量情况1:安装node.js下载地址:https://nodejs.org/en/安装步骤:默......