数据结构与算法之排序(归纳总结一)

  排序使我们实际开发中最常使用到的几个算法之一,按照如果按照排序过程中依据的原则对内部排序进行分类,则大致上可以分为插入排序、交换排序、选择排序、归并排序等排序方法。让我们首先看看插入排序的算法有哪些,以及他们的具体实现。插入排序的基本排序思想是:逐个考察每个待排序元素,将每一个新元素插入到前面已经排好序的序列中适当的位置上,使得新序列仍然是一个有序序列。在这一类排序中主要介绍三种排序方法:直接插入排序、折半插入排序和希尔排序。

1.直接插入排序

  a.算法描述

  直接插入排序是一种最简单的插入排序方法,它的基本思想是:仅有一个元素的序列总是有序的,因此,对n个记录的序列,可从第二个元素开始直到第n个元素,逐个向有序序列中执行插入操作,从而得到n个元素按关键字有序的序列。一般来说,在含有j-1 个元素的有序序列中插入一个元素的方法是:从第j-1 个元素开始依次向前搜索应当插入的位置,并且在搜索插入位置的同时可以后移元素,这样当找到适当的插入位置时即可直接插入元素。以关键字序列{ 26 , 53 , 48 , 11 , 13 , 48, 32 , 15}为例,直接插入排序的过程如下所示。

  b:算法实现

  

	public void insertSort(int[] r, int low, int high) {
		for (int i = low + 1; i <= high; i++)
			if (compare(r[i], r[i - 1])) { // 小于时,需将r[i]插入有序表
				int temp = r[i];
				r[i] = r[i - 1];
				int j = i - 2;
				for (; j >= low && compare(temp, r[j]); j--)
					r[j + 1] = r[j]; // 记录后移
				r[j + 1] = temp; // 插入到正确位置
			}
	}

  

  

【效率分析】
空间效率:仅使用一个辅存单元。
时间效率:假设待排序的元素个数为n,则向有序表中逐个插入记录的操作进行了n-1趟,每趟操作分为比较关键码和移动记录,而比较的次数和移动记录的次数取决于待排序列按关键码的初始排列。直接插入排序的时间复杂度为O(n²)

c:实现举例

  StraightInsertionSort.java

package com.test.sort.insertion;

public class StraightInsertionSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("直接插入排序排序功能实现》》》》");
		int[] arr = { 23, 54, 6, 2, 65, 34, 2, 67, 7, 9, 43 };

		StraightInsertionSort sort = new StraightInsertionSort();
		System.out.println("排序之前序列:");
		sort.printArr(arr);
		sort.insertSort(arr, 0, arr.length - 1);
		System.out.println("排序之后序列:");
		sort.printArr(arr);
	}

	public void insertSort(int[] r, int low, int high) {
		for (int i = low + 1; i <= high; i++)
			if (compare(r[i], r[i - 1])) { // 小于时,需将r[i]插入有序表
				int temp = r[i];
				r[i] = r[i - 1];
				int j = i - 2;
				for (; j >= low && compare(temp, r[j]); j--)
					r[j + 1] = r[j]; // 记录后移
				r[j + 1] = temp; // 插入到正确位置
			}
	}

	public boolean compare(int paramA, int paramB) {
		if (paramA < paramB) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 依次打印出数组元素
	 */
	public void printArr(int[] arr) {
		if (arr != null) {
			for (int temp : arr) {
				System.out.print(temp + "   ");
			}
			System.out.println();
		}
	}
}

  d:结果输出

  

2.希尔排序

  a.算法描述

  

  希尔排序又称为“缩小增量排序”,它也是一种属于插入排序类的排序方法,是一种对直接插入排序的改进,但在时间效率上却有较大的改进。从对直接插入排序的分析中知道,虽然直接插入排序的时间复杂度为O(n²),但是在待排序元素序列有序时,其时间复杂度可提高至O(n)。由此可知在待排序元素基本有序时,直接插入排序的效率可以大大提高。从另一方面看,由于直接插入排序方法简单,则在n值较小时效率也较高。希尔排序正是从这两点出发,对直接插入排序进行改进而得到的一种排序方法。
希尔排序的基本思想是:首先将待排序的元素分为多个子序列,使得每个子序列的元素个数相对较少,对各个子序列分别进行直接插入排序,待整个待排序序列“基本有序”后,再对所有元素进行一次直接插入排序。根据上述排序思想,下面我们给出希尔排序的排序过程:
  ⑴选择一个步长序列t1,t2,…,tk,其中ti>tj(i<j),tk=1;
  ⑵按步长序列个数k,对待排序元素序列进行k趟排序;
  ⑶每趟排序,根据对应的步长ti,将待排序列分割成ti个子序列,分别对各子序列进行直接插入排序。当步长因子为1时,所有元素作为一个序列来处理,其长度为n。以关键字序列{ 26 , 53 , 67 , 48 , 57 , 13 , 48, 32 , 60 , 50}为例,假设选择的步长序列为{5 , 3 , 1},则希尔排序的过程如图9-2所示。因为步长序列长度为3,因此对待排序序列一共需要进行3趟排序。首先,第一趟排序中将关键字序列分成5个子序列{26 , 13},{53 , 48},{67 , 32},{48 , 60},{57 , 50},对它们分别进行直接插入排序,结果如图所示。然后,进行第二趟希尔排序,此时步长为3,则将关键字序列分成3个子序列{13 , 48 , 53 , 57},{48, 50 , 67},{32 , 26 , 60},对它们进行直接插入排序后的结果如图所示。最后,对整个序列进行一趟直接插入排序,此时得到一个关键字有序的序列,希尔排序结束。

  b.算法实现

    

public void shellSort(int[] r, int low, int high, int[] delta) {
        for (int k = 0; k < delta.length; k++)
            shellInsert(r, low, high, delta[k]); // 一趟步长为delta[k]的直接插入排序
    }

    private void shellInsert(int[] r, int low, int high, int deltaK) {
        for (int i = low + deltaK; i <= high; i++)
            if (compare(r[i], r[i - deltaK])) { // 小于时,需将r[i] 插入有序表
                int temp = r[i];
                int j = i - deltaK;
                for (; j >= low && compare(temp, r[j]); j = j - deltaK)
                    r[j + deltaK] = r[j]; // 记录后移 [j];
                r[j + deltaK] = temp; // 插入到正确位置
            }
    }

【效率分析】
空间效率:仅使用一个辅存单元。
时间效率:假设待排序的元素个数为n,则向有序表中逐个插入记录的操作进行了n-1趟,每趟操作分为比较关键码和移动记录,而比较的次数和移动记录的次数取决于待排序列按关键码的初始排列。直接插入排序的时间复杂度为O(n²)

  c.使用示例

  HashInsertSort.java

  

package com.test.sort.insertion;

public class HashInsertSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		System.out.println("希尔排序功能实现》》》》");

		int[] arr = { 23, 54, 6, 2, 65, 34, 2, 67, 7, 9, 43 };
		int[] delta = {5,3,1};

		HashInsertSort sort = new HashInsertSort();
		System.out.println("排序之前序列:");
		sort.printArr(arr);
		sort.shellSort(arr, 0, arr.length - 1,delta);
		System.out.println("排序之后序列:");
		sort.printArr(arr);
	}

	public void shellSort(int[] r, int low, int high, int[] delta) {
		for (int k = 0; k < delta.length; k++)
			shellInsert(r, low, high, delta[k]); // 一趟步长为delta[k]的直接插入排序
	}

	private void shellInsert(int[] r, int low, int high, int deltaK) {
		for (int i = low + deltaK; i <= high; i++)
			if (compare(r[i], r[i - deltaK])) { // 小于时,需将r[i] 插入有序表
				int temp = r[i];
				int j = i - deltaK;
				for (; j >= low && compare(temp, r[j]); j = j - deltaK)
					r[j + deltaK] = r[j]; // 记录后移 [j];
				r[j + deltaK] = temp; // 插入到正确位置
			}
	}

	public boolean compare(int paramA, int paramB) {
		if (paramA < paramB) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 依次打印出数组元素
	 */
	public void printArr(int[] arr) {
		if (arr != null) {
			for (int temp : arr) {
				System.out.print(temp + "   ");
			}
			System.out.println();
		}
	}

}

  

  d.结果输出

3.折半插入排序

  a.算法描述

  

  直接插入排序算法简便、容易实现。当待排序元素的数量n很小时,这是一种较好的排序方法,但是通常待排序元素数量n很大,则不宜采用直接插入排序方法,此时需要对直接插入排序进行改进。直接插入排序的基本操作是向有序序列中插入一个元素,插入位置的确定是通过对有序序列中元素按关键字逐个比较得到的。既然是在有序序列中确定插入位置,则可以不断二分有序序列来确定插入位置,即搜索插入位置的方法可以使用折半查找实现。

  b.算法实现

  

    public void binInsertSort(int[] r, int low, int high) {

        for (int i = low + 1; i <= high; i++) {
            int temp = r[i]; // 保存待插入元素
            int hi = i - 1;
            int lo = low; // 设置初始区间
            while (lo <= hi) { // 折半确定插入位置
                int mid = (lo + hi) / 2;
                if (compare(temp, r[mid]))
                    hi = mid - 1;
                else
                    lo = mid + 1;
            }
            for (int j = i - 1; j > hi; j--)
                r[j + 1] = r[j]; // 移动元素
            r[hi + 1] = temp; // 插入元素
        }// for
    }

【效率分析】
空间效率:仅使用一个辅存单元。
时间效率:折半插入排序仅减少了元素的比较次数,但是并没有减少元素的移动次数,折半插入排序的时间复杂度为O(n²)。

  c.应用举例

  BinaryInsertSort.java

  

package com.test.sort.insertion;

public class BinaryInsertSort {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("折半插入排序排序功能实现》》》》");
        int[] arr = { 23, 54, 6, 2, 65, 34, 2, 67, 7, 9, 43 };

        BinaryInsertSort sort = new BinaryInsertSort();
        System.out.println("排序之前序列:");
        sort.printArr(arr);
        sort.binInsertSort(arr, 0, arr.length - 1);
        System.out.println("排序之后序列:");;
        sort.printArr(arr);
    }

    public void binInsertSort(int[] r, int low, int high) {

        for (int i = low + 1; i <= high; i++) {
            int temp = r[i]; // 保存待插入元素
            int hi = i - 1;
            int lo = low; // 设置初始区间
            while (lo <= hi) { // 折半确定插入位置
                int mid = (lo + hi) / 2;
                if (compare(temp, r[mid]))
                    hi = mid - 1;
                else
                    lo = mid + 1;
            }
            for (int j = i - 1; j > hi; j--)
                r[j + 1] = r[j]; // 移动元素
            r[hi + 1] = temp; // 插入元素
        }// for
    }

    public boolean compare(int paramA, int paramB) {
        if (paramA < paramB) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 依次打印出数组元素
     */
    public void printArr(int[] arr) {
        if (arr != null) {
            for (int temp : arr) {
                System.out.print(temp + "   ");
            }
            System.out.println();
        }
    }

}

  d.结果输出

  

时间: 2024-08-28 11:36:18

数据结构与算法之排序(归纳总结一)的相关文章

数据结构与算法之排序(归纳总结三)

选择排序的基本思想是:每一趟从n-i+1 (i=1,2,…,n)个元素中选取一个关键字最小的元素作为有序序列中第i个元素.本节在介绍简单选择排序的基础上,给出了对其进行改进的算法堆排序. 1.简单选择排序 a:算法描述 简单选择排序的基本思想非常简单,即:第一趟,从n个元素中找出关键字最小的元素与第一个元素交换:第二趟,在从第二个元素开始的n-1个元素中再选出关键字最小的元素与第二个元素交换:如此,第k趟,则从第k个元素开始的n-k+1个元素中选出关键字最小的元素与第k个元素交换,直到整个序列按

数据结构与算法之排序(归纳总结四)

1.算法描述 归并排序的基本思想是基于合并操作,即合并两个已经有序的序列是容易的,不论这两个序列是顺序存储还是链式存储,合并操作都可以在Ο(m+n)时间内完成(假设两个有序表的长度分别为m和n).为此,由分治法的一般设计步骤得到归并排序的过程为: 1. 划分:将待排序的序列划分为大小相等(或大致相等)的两个子序列: 2. 治理:当子序列的规模大于1时,递归排序子序列,如果子序列规模为1则成为有序序列: 3. 组合:将两个有序的子序列合并为一个有序序列. 2.算法实现 归并的核心在于除了每个子列的

数据结构与算法之排序(归纳总结二)

交换类排序主要是通过两两比较待排元素的关键字,若发现与排序要求相逆,则“交换”之.在这类排序方法中最常见的是起泡排序和快速排序,其中快速排序是一种在实际应用中具有很好表现的算法. 1.冒泡排序 a.算法描述 起泡排序的思想非常简单.首先,将n个元素中的第一个和第二个进行比较,如果两个元素的位置为逆序,则交换两个元素的位置:进而比较第二个和第三个元素关键字,如此类推,直到比较第n-1个元素和第n个元素为止:上述过程描述了起泡排序的第一趟排序过程,在第一趟排序过程中,我们将关键字最大的元素通过交换操

Java数据结构与算法之排序

排序从大体上来讲,做了两件事情: 1.比较两个数据项: 2.交换两个数据项,或复制其中一项 一.冒泡排序 大O表示法:交换次数和比较次数都为O(N*N). 算法原理: 1.比较相邻的元素.如果第一个比第二个大,就交换他们两个. 2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 3.针对所有的元素重复以上的步骤,除了最后一个. 4.持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较. /** * 冒泡排序 demo * */

在Object-C中学习数据结构与算法之排序算法

笔者在学习数据结构与算法时,尝试着将排序算法以动画的形式呈现出来更加方便理解记忆,本文配合Demo 在Object-C中学习数据结构与算法之排序算法阅读更佳. 目录 选择排序 冒泡排序 插入排序 快速排序 双路快速排序 三路快速排序 堆排序 总结与收获 参考与阅读 选择排序 选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n2) 的时间复杂度.所以用到它的时候,数据规模越小越好.唯一的好处可能就是不占用额外的内存空间了吧. 1.算法步骤 首先在未排序序列中找到最小(大)元素,存放到排

python 数据结构与算法之排序(冒泡,选择,插入)

目录 数据结构与算法之排序(冒泡,选择,插入) 为什么学习数据结构与算法: 数据结构与算法: 算法: 数据结构 冒泡排序法 选择排序法 插入排序法 数据结构与算法之排序(冒泡,选择,插入) 为什么学习数据结构与算法: 计算机重要的几门课: 1.数据结构和算法 2.网络 3.操作系统 4.计算组成原理 数据结构与算法: 算法: 衡量算法的标准: 时间复杂度:就是程序代码执行的大概次数 小结: 时间复杂度是用来估计算法运行时间的一个式子(单位) 一般来说,时间复杂度高的算法比复杂度低的算法慢 常见的

数据结构和算法之排序一:归并排序

我们不得不承认一个事实,java学习过程中如果我们掌握了各种编程手段和工具,确实可以做一些开发,这就是一些培训机构敢告诉你几个月就能掌握一门语言的原因.但是随着时间的发展,我们总会感觉,这一类人如果不提升自己,最后也只会是一个码农.技术会日新月异,随时在发展更新换代,但是这几十年,有谁说过算法会过时,如果我们说java语言的发动机是各种开发手段和技术,那么我们可以毫不客气的说算法会是他的灵魂.一个程序员的提升和拔高一定是万丈高楼平地起,那么我希望这个地基一定是数据结构和算法,掌握这些原理以后其实

数据结构和算法之排序六:希尔排序

经过前面五篇排序方法的介绍,我们了解到了递归思想以及分而治之的归并和快速排序,当然也涉及到了比较简单易懂的数据值传递冒泡,选择,以及插入排序.可以说每一种排序方式都各有千秋,都适合在不同的环境下进行使用,但是我们有时会不会思考一个问题,那就是我们在学习插入排序的时候的主题思想是将每一个数据取出来,然后和后边的前边的数据逐一进行比较,那么,我们是不是要进行N-1次的循环,或者说我们是不是要进行大约N的平方次比较,我们知道,在进行值的交换和比较是非常消耗时间的,那么是不是违背了我们算法的发展.有没有

javascript数据结构与算法--高级排序算法

高级排序算法是处理大型数据集的最高效排序算法,它是处理的数据集可以达到上百万个元素,而不仅仅是几百个或者几千个.现在我们来学习下2种高级排序算法---- 希尔排序和快速排序. 一:希尔排序: 希尔排序的核心理念是:首先比较距离较远的元素,而非相邻的元素. 基本原理:通过定义一个间隔序列来表示在排序过程中进行比较的元素之间有多远的间隔. 下面我们来看看数组[0,9,1,8,7,6,2,3,5,4] 来使用希尔排序的原理:如下图: 代码分析如下: 1. 执行 "间隔序列=3的步骤" A.