数据结构笔记(排序)

本文详细介绍了内排序的四种主要方法:插入排序(直接插入、折半插入、希尔排序)、交换排序(冒泡排序、快速排序)、选择排序(简单选择、堆排序)和归并排序(自底向上、自顶向下)。讨论了排序的基本概念,包括排序的稳定性、有序区与无序区。每种排序算法的实现细节和工作原理均进行了阐述。
摘要由CSDN通过智能技术生成

目录

前言

一、排序的基本概念

1.排序的定义

2.内排序的分类

3.排序的稳定性

4.有序区与无序区

5.排序数据的组织

二、插入排序

1.直接插入排序

2.折半插入排序

3.希尔排序

三、交换排序

1.冒泡排序

2.快速排序

四、选择排序

1.简单选择排序

2.堆排序

1)堆的定义

2)筛选算法

3)建立初始堆

4)堆排序算法

五、归并排序

1.自底向上的二路归并排序

1)排序思路

2)二路归并算法

3)每一趟的二路归并排序

4)二路归并排序算法

2.自顶向下的二路归并排序

总结


前言

排序分为内排序和外排序,内排序是指排序时不涉及数据的内、外存交换。本章讨论的是内排序。内排序主要有8种方式,它们各有优劣。


一、排序的基本概念

1.排序的定义

所谓排序,就是整理表中的元素,使之按照关键字递增或递减有序排列。在默认情况下所有的排序均指的是递增排序。

2.内排序的分类

根据内排序算法是否基于关键字的比较,将内排序算法分为基于比较的排序算法和不基于比较的排序算法。插入排序、交换排序、选择排序和归并排序都是基于比较的排序算法,而基数排序则是不基于比较的排序算法。

3.排序的稳定性

当待排序的表中存在多个关键字相同的元素,经过排序后这些具有相同关键字的元素之间的相对次序保持不变,则称这种排序方法是稳定的。反之,如果这些元素的相对次序改变了,则称这种排序方法是不稳定的

4.有序区与无序区

在排序过程中的某一时刻R被划分为两个区间,前面的子区间是已经排好序的,称作有序区,后面的是待排序的部分,称为无序区

5.排序数据的组织

在讨论排序算法时,以顺序表作为排序数据的存储结构,假设关键字为int类型,其元素类型定义如下:

public class SortType {
    int key;                     //存放关键字
    String data;                 //存放其他数据
    public SortType(int key){
        this.key = key;
    }
}

设计用于内排序的SortClass如下:

public class SortClass {
    final int MAXSIZE = 100;         //最多元素的个数
    SortType[] R;                    //存放排序的元素
    int num;                         //表中实际元素的个数

    /**
     * 交换i和j
     * @param i
     * @param j
     */
    public void swap(int i,int j){   
        SortType tmp;
        tmp = R[i];
        R[i] = R[j];
        R[j] = tmp;
    }

    /**
     * 由关键字序列a构造顺序表R
     * @param a
     */
    public void creatR(int[]a){
        R = new SortType[MAXSIZE];
        for (int i = 0; i < a.length; i++) {
            R[i] = new SortType(a[i]);
        }
        num = a.length;
    }

    /**
     * 构造用于堆排序的R
     * @param a
     */
    public void creatR_1(int[]a){
        R = new SortType[MAXSIZE];
        for (int i = 0; i < a.length; i++) {
            R[i+1] = new SortType(a[i]);
        }
        num = a.length;
    }

    /**
     * 输出顺序表R
     */
    public void display(){
        for (int i = 0; i < num; i++) {
            System.out.print(R[i].key+" ");
        }
        System.out.println();
    }

    /**
     * 输出用于堆排序的R
     */
    public void display_1(){
        for (int i = 1; i <= num; i++) {
            System.out.print(R[i].key+" ");
        }
        System.out.println();
    }
}

二、插入排序

插入排序的基本思想是每次将一个待排序的元素按其关键字大小插入前面已经排好序的子表中的适当位置

1.直接插入排序

直接插入排序的每趟操作是将当前无序区的开头元素插入有序区中适当位置,从而扩大有序区减少无序区。这种方法通常称为增量法,因为它每次使有序区增加一个元素。经过n-1趟后无序区变空。

其过程为:先将无序区头元素R[i]暂时放入tmp中,用j在有序区从后往前找,凡是大于tmp的元素均后移一个位置,指到找到某个小于或等于tmp的元素为止,再将tmp放在它的后面

    public void insertSort(){
        SortType tmp;
        int j;
        for (int i = 1; i < num; i++) {                   //从R[1]开始
            if (R[i].key < R[i - 1].key) {                //当反序时才执行,可以减少运行次数
                tmp = R[i];                               //取出无序区第一个元素
                j = i - 1;                                //有序区的末尾
                while (j >= 0 && tmp.key < R[j].key) {    
                    R[j + 1] = R[j];                      //将所有比tmp大的元素后移
                    j--;
                }
                R[j + 1] = tmp;                           //在j+1处插入tmp
            }
        }
    }

2.折半插入排序

折半查找是先在有序区中用折半查找方法找到插入位置,再通过移动元素经行插入。折半插入排序又称为二分插入排序

    public void halfSort(){
        SortType tmp;
        int left;
        int right;
        int mid;
        for (in
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值