定义
是将一组数据按照一定的规则排列起来,方便查询处理。
分类
- 1内部排序
- 2外部排序
外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。
1.1交换排序
- 1.1.1冒泡排序
基本思想:对排序记录数据从后往前(逆序)进行多次扫描,当发现相邻两个数据的次序与排序要求的规则不符实,就将这两个记录进行交换。这样,数据较小的记录将逐渐从后面向前面移动们就像气泡一样向上浮动,所以该算法称为冒泡排序法
public class BubbleSort {
/**
* @param args
* 冒泡排序
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = { 36, 12, 89, 72, 8, 68 };
ascendingBubbleSort(arr);// 升序
for (int i : arr) {
System.out.println(i); //输出
}
}
/**
* 降序
*
* @param arr
*/
static void descendingBubbleSort(int[] arr) {
int temp;
int m;
//总共循环arr.length次
for (int i = 0; i < arr.length; i++) {
m = arr.length - i - 1;
//每一次循环结束,此次循环最大数排到最后,减少一次循环
for (int j = 0; j < m; j++) {
if (arr[j] > arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
/**
* 升序
*
* @param arr
*/
static void ascendingBubbleSort(int[] arr) {
int temp;
//总共循环arr.length次
for (int i = 0; i < arr.length; i++) {
//每一次循环结束,此次循环最大数排到最前,减少一次循环
for (int j = arr.length-1; j > i; j--) {
if (arr[j] > arr[j - 1]) {
temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
}
}
}
}
}
- 1.1.2快速排序
基本思想:使用分治算法,把待排序数据序列分为两个子序列
操作步骤:
- 1.1.2.1 从数据中挑选一个元素,称该元素为“基准”;
- 1.1.2.2 扫描一遍数列,将所有比“基准”小的元素排在“基准”前面,所有比“基准”大的元素排在“基准”后面;
- 1.1.2.3 通过递归,将各子序列划分为更小的序列,直到把小于基准值元素的子序列和大于基准值元素的子序列排序。
public class QuickSort {
/**
* @param args
* 快速排序
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = { 36, 12, 89, 72, 8, 68 };
descendingQuickSort(arr, 0, arr.length - 1);
for (int i : arr) {
System.out.println(i); // 输出
}
}
/**
* 降序
*
* @param arr
* @param left
* @param right
*/
static void descendingQuickSort(int arr[], int left, int right) {
if (left < right) {
int divisionLeft = left, divisionRight = right;// 分割参数
int base = arr[left];
while (divisionLeft < divisionRight) {
// 循环从右面找到小于于基准的数字
while (divisionLeft < divisionRight
&& arr[divisionRight] >= base)
divisionRight--;
// 然后将数字赋值
if (divisionLeft < divisionRight)
arr[divisionLeft++] = arr[divisionRight];
// 循环从左面面找到第一个大于基准的数字
while (divisionLeft < divisionRight && arr[divisionLeft] < base)
divisionLeft++;
// 然后将数字赋值
if (divisionLeft < divisionRight)
arr[divisionRight--] = arr[divisionLeft];
}
arr[divisionLeft] = base;// 当divisionLeft=divisionRight时赋值
descendingQuickSort(arr, left, divisionLeft - 1);// 递归调用 基数左边
descendingQuickSort(arr, divisionLeft + 1, right);// 递归调用 基数右边
}
}
/**
* 升序
*
* @param arr
* @param left
* @param right
*/
static void ascendingQuickSort(int arr[], int left, int right) {
if (left < right) {
int divisionLeft = left, divisionRight = right;// 分割参数
int base = arr[left];
while (divisionLeft < divisionRight) {
// 循环从右面找到小于于基准的数字
while (divisionLeft < divisionRight
&& arr[divisionRight] <= base)
divisionRight--;
// 然后将数字赋值
if (divisionLeft < divisionRight)
arr[divisionLeft++] = arr[divisionRight];
// 循环从左面面找到第一个大于基准的数字
while (divisionLeft < divisionRight && arr[divisionLeft] > base)
divisionLeft++;
// 然后将数字赋值
if (divisionLeft < divisionRight)
arr[divisionRight--] = arr[divisionLeft];
}
arr[divisionLeft] = base;// 当divisionLeft=divisionRight时赋值
ascendingQuickSort(arr, left, divisionLeft - 1);// 递归调用 基数左边
ascendingQuickSort(arr, divisionLeft + 1, right);// 递归调用 基数右边
}
}
}
1.2选择排序
- 1.2.1直接选择排序
基本思想:通过对N个记录将其输出,选择最小的记录输出,再循环(N-1)次在输出最小值,直到只剩下一个记录。有点类似于冒泡
public class ChoiceSort {
/**
* @param args
* 简单选择排序
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = { 36, 12, 89, 72, 8, 68 };
choiceSort(arr);
for (int i : arr) {
System.out.println(i); // 输出
}
}
static void choiceSort(int arr[]) {
int temp;
for (int i = 0; i < arr.length; i++) {
for (int j = i; j < arr.length - 1; j++) {
if (arr[i] > arr[j + 1]) {
temp = arr[i];
arr[i] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
}
- 1.2.2堆排序
基本思想:堆就是一个完整的二叉树,树中每个结点对应于原始数据的一个记录,并且每个结点应满足以下条件,非叶结点的数据大于或者等于其左右孩子结点的数据
- 将无序的数据构成堆(即用无序数据生成满足堆定义的完全二叉树);
- 利用堆排序(即用上一步生成的堆输出有序的数据),即是对完全二叉树进行遍历。
1.3插入排序
- 1.3.1直接插入排序(Insertion Sort)
基本思想:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
public class InsertionSort {
/**
* @param args
* 插入排序
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = { 36, 12, 89, 72, 8, 68 };
insertionSort(arr);
for (int i : arr) {
System.out.println(i); // 输出
}
}
static void insertionSort(int arr[]) {
int i,j,temp;
for(i=1;i<arr.length;i++){
temp =arr[i];//取出一个未排序的数据
for(j = i-1;j>=0&& temp <arr[j];j--)//在排序序列中查找位置,<降序,>升序
arr[j+1]= arr[j];//向后移动数据
arr[j+1] = temp;//插入数据带序列
}
}
}
- 1.3.2希尔排序(Shell)
基本思想:(缩小增量排序)将需要排序的序列划分为若干个较小序列,对这些序列进行直接插入排序,通过这样的操作可使用需要排序的数列基本有序,最后再使用一次直接插入排序。
public class ShellSort {
/**
* @param args
* 希尔排序
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = { 36, 12, 89, 72, 8, 68 };
shellSort(arr);
for (int i : arr) {
System.out.println(i); // 输出
}
}
static void shellSort(int arr[]) {
int d, i, j, x;
d = arr.length / 2;
while (d >= 1) {// 循环至增量为1时结束
for (i = d; i < arr.length; i++) {
x = arr[i];// 获取序列中的下一个数据
j = i - d;// 序列中前一个数据的序列
while (j >= 0 && arr[j] > x) {// 下一个数大于前一个数
arr[j + d] = arr[j];// 将后一个将向前移动
j = j - d;// 修改序号,继续向前比较
}
arr[j + d] = x;// 保存数据
}
d /= 2;// 缩小增量
}
}
}
1.4归并排序(Merge Sort)
基本思想:就是将两个或者多个有序表合并成一个有序表。