冒泡排序法
原理是从第一个元素开始,比较相邻元素的大小,若大小顺序有误,则对调后再进行下一个元素的比较。
1. n个元素的冒泡排序必须执行n-1次扫描。
2.适用于数量小或者有部分数据已经过排序的情况。
/**
* 冒牌排序,改进版
*/
public class Sentry{
int[] data = new int[]{4,6,2,7,8,9};
//打印输出数据
public void showData(){
int i;
for (i = 0; i < data.length ; i++) {
System.out.print(data[i] + " ");
}
System.out.print("\n");
}
//排序后并且打印输出
public void bubble(){
int i, j, tmp, flag;
for (i = data.length-1; i>= 0 ; i--) { //扫描次数
flag = 0;
for (j = 0; j < i; j++) { //比较、交换次数
//比较相邻两个元素,进行交换操作
if (data[j+1] > data[j]){
tmp = data[j];
data[j] = data[j+1];
data[j + 1] = tmp;
flag++; //如果执行过交换,则flag不为0
}
}
//执行过一次扫描就判断是否执行过交换操作。如果没有交换过数据
//则表示此时数组已经完成-排序,因此可以指甲跳出循环
if (flag == 0){
break;
}
System.out.print("第"+(data.length - i)+"次排序:");
for (j = 0; j < data.length; j++) {
System.out.print(data[j]+" ");
}
System.out.print("\n");
}
System.out.print("排序后的数据:");
showData();
}
}
选择排序法
属于枚举法的应用,就是反复从未排序过的数列中取出最大或最小的元素,加入到另一个数列中,最后的结果即位已排序的数列。
1.适用于数量小或者有部分数据已经过排序的情况。
package sort;
/**
* 选择排序法
*/
public class Selection {
int[] data = new int[]{9,7,5,3,4,6};
//打印输出数据
public void showData(){
int i;
for (i = 0; i < data.length ; i++) {
System.out.print(data[i] + " ");
}
System.out.print("\n");
}
//具体排序算法
public void select(){
int j, k, smallest, temp, index;
for (int i = 0; i < data.length -1; i++) { //扫描次数为数列长度-1次
smallest = data[i];
index = i;
for (j = i+1; j < data.length; j++) { //由i+1 比较起,比较次数为:数列长度 - (i+1) 次
if (smallest > data[j]) { //比较第i个和第j个元素
smallest = data[j];
index = j;
}
}
temp = data[index];
data[index] = data[i];
data[i] = temp;
System.out.print("第"+(i+1)+"次排序的结果:");
for (k = 0; k< data.length; k++) {
System.out.print(data[k]+ " "); //打印最后排序结果
}
System.out.print("\n");
}
System.out.print("\n");
}
}
插入排序法
将数组中的元素逐一与排序好的数据进行比较,先将前两个元素排好,再将第三个元素插入适当的位置,接着是第四个,重复此步骤。
1.由于插入排序法会造成数据大量搬迁,因此建议在链表上使用。
package sort;
/**
* 插入排序
*/
public class Insertion {
int[] data = new int[]{8,4,6,7,3,5};
int size = data.length;
public void showData(){
for (int i = 0; i < size; i++) {
System.out.print(data[i] + " ");
}
System.out.print("\n");
}
//具体排序算法
public void insert(){
int i; //i为扫描次数
int j; //用j来定位比较的元素
int tmp ; // tmp用来暂存数据
for (i = 1; i< size ; i++) {
tmp = data[i];
j = i - 1;
while (j >= 0 && tmp < data[j]){ // 如果第二个元素小于第一个元素
data[j + 1] = data[j]; // 就把所有元素往后推一个位置
j--;
}
data[j+1] = tmp;
System.out.print("第"+i+"次扫描:");
showData();
}
}
}
希尔排序法
排序原则是将数据区分成特定间隔的几个小区块,以插入排序法排完区块内的数据后在渐渐减少间隔的距离。可以减少插入排序法中的数据搬迁次数,以加速排序速度。
1.适用于大部分数据都已经排序第情况。
package sort;
/**
* 希尔排序法
*/
public class Shell {
int[] data = new int[]{63,92,27,36,45,71,58,7,109};
public void showData(){
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + " ");
}
System.out.print("\n");
}
public void shell(){
int i; //i为扫描次数
int j; //以j来定位比较的元素
int k = 1; //k打印计算
int tmp; //tmp用来暂存数据
int jmp; //设置间距位移量
jmp = data.length / 2;
while (jmp != 0){
for (i = jmp; i < data.length; i++) {
tmp = data[i];
j = i - jmp;
while (j >= 0 && tmp < data[j]){ //插入排序法
data[j + jmp] = data[j];
j = j - jmp;
}
data[jmp + j] = tmp;
}
System.out.print("第"+(k++)+"次排序:");
showData();
jmp = jmp / 2;
}
}
}
快速排序法
会先在数据中找到一个虚拟的中间值,并按此中间值将所有打算排序的数据分为两部分,小于中间值放于左边,大于中间值放于右边,再以同样的方法分别处理左、右两边的数据,直到排序完为止。
package sort;
import java.util.Random;
/**
* 快速排序法
*/
public class Quick {
int process = 0;
public int[] data = new int[13];
//随机生成数据
public void inputarr(){
Random random = new Random();
for (int i = 0; i < data.length; i++) {
data[i] = (Math.abs(random.nextInt(99)))+1;
}
}
public void showData(){
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + " ");
}
System.out.print("\n");
}
// 具体算法
public void quick(int[] d, int s,int lf, int rg){
int i,j,tmp;
int lf_idx;
int rg_idx;
int t;
//第一个键值为data[lf]
if (lf < rg){
lf_idx = lf + 1;
rg_idx = rg;
//排序
while (true){
System.out.print("处理过程:"+(process ++));
for (t = 0; t < s ; t++) {
System.out.print("["+d[t]+"] ");
}
System.out.print("\n");
for (i = lf+1; i <= rg ; i++) { //从左到右找出一个键值大于data[lf]者
if (d[i] >= d[lf]){
lf_idx = i;
break;
}
lf_idx++;
}
for (j = rg; j >= lf+1 ; j--) { //从右到左找出一个键值小于data[lf]者
if (d[j] <= d[lf]){
rg_idx = j;
break;
}
rg_idx--;
}
if (lf_idx < rg_idx){ //若 lf_idx 小于 rg_idx
tmp = d[lf_idx];
d[lf_idx] = d[rg_idx]; //则将d[lf_idx] 和 d[rg_idx] 互换
d[rg_idx] = tmp;
}else {
break; //否则跳出排序过程
}
}
if (lf_idx >= rg_idx){ //若lf_idx大于等于 rg_idx,
tmp = d[lf];
d[lf] = d[rg_idx]; //将的d[lf] 和d[rg_idx]互换
d[rg_idx] = tmp;
//以rg_idx为基准点分成左右两半
quick(d, data.length, lf, rg_idx - 1); //以递归方式分别为左右两部分进行排序
quick(d, data.length, rg_idx + 1, rg); //直至完成排序
}
}
}
}
合并排序法
针对已经排序好的两个或者两个以上的数列(或数据文件),通过合并方式将其组成一个大的且已排好序的数列(或数据文件)。
基数排序法
此方法按比较的方向分为最高位优先(MSD)和最低位优先(LSD)两种方式。MSD是从最左边的位数开始比较,LSD是从最右边的位数开始比较。
59 | 95 | 7 | 34 | 60 | 168 | 171 | 259 | 372 | 45 | 88 | 133 |
把每个整数按个位数相同放到同一个列表下
个位数 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
数据 | 60 | 171 | 372 | 133 | 34 |
95 45 | 7 |
88 168 |
59 259 |
合并后
60 | 171 | 372 | 133 | 34 | 95 | 45 | 7 | 168 | 88 | 59 | 259 |
然后是十位数,再到百位是或千位数,以此类推最后完成合并。
7 | 34 | 35 | 45 | 60 | 88 | 95 | 133 | 168 | 171 | 259 | 372 |
package sort;
import java.util.Random;
/**
* 基数排序法
*/
public class Radix {
int size = 12;
int[] data = new int[12];
//随机生成数据
public void inputarr(){
Random random = new Random();
for (int i = 0; i < data.length; i++) {
data[i] = (Math.abs(random.nextInt(999)))+1;
}
}
public void showData(){
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + " ");
}
System.out.print("\n");
}
public void radix(){
int i,j,k,n,m;
for (n = 1; n<= 100 ; n=n*10) { //n为基数,从个位数开始排序
//设置暂存数组,【0-9位数】【数据个数】
int[][] tmp = new int[10][data.length];
for (i = 0; i<data.length ; i++) {
m = (data[i] /n )%10; //m为n位数的值,如36取十位数(36 / 10)%10 = 3
tmp[m][i] = data[i];
}
k = 0;
for (i = 0; i<10 ; i++) {
for (j = 0; j< data.length ; j++) {
if (tmp[i][j] != 0){
data[k] = tmp[i][j];
k++;
}
}
}
System.out.print("经过"+n+"位数排序后:");
showData();
}
}
}
堆积树排序法
堆积数排序法是选择排序法的改进版,减少选择排序法中的比较次数,进而减少排序时间。用到二叉树的技巧,利用堆积树来排序。分为最大堆积数和最小堆积数两种。
最大堆积数:
1.一棵完整的二叉树
2.所有节点的值都大于或等于它左、右子节点的值。
3.树根是堆积数最大的。
最小堆积数:
1,一颗完全的二叉树。
2.所有节点的值都小于或等于它左、右子节点的值。
3.树根是堆积数最小的。
package sort;
/**
* 堆积数排序法
*/
public class Three {
public void showData(int[] data){
for (int i = 0; i < data.length; i++) {
System.out.print(data[i] + " ");
}
System.out.print("\n");
}
public void heap(int[] data, int size){
int i, j, tmp;
for (i = (size / 2); i>0 ; i--) { //建立堆积数节点
ad_heap(data, i, size - 1);
}
System.out.print("堆积内容:");
for (i = 1; i<size ; i++) { //原始堆积树内容
System.out.print("["+data[i]+"] ");
}
System.out.print("\n");
for (i = size - 2; i > 0 ; i--) { //堆积排序
tmp = data[i + 1]; //头尾节点交换
data[i + 1] = data[1];
data[1] = tmp;
ad_heap(data,1, i); //处理剩余节点
System.out.print("处理过程:");
for (j = 1; j<size ; j++) {
System.out.print("["+data[j]+"] ");
}
}
}
public void ad_heap(int[] data, int i, int size){
int j, tmp, post;
j = 2* i;
tmp = data[i];
post = 0;
while (j <= size && post==0){
if (j < size){
if (data[j] < data[j+1]){
j++;
}
}
if (tmp >= data[j]){
post = 1;
}else {
data[j /2] = data[j];
j = 2 * j;
}
}
data[j / 2] = tmp;
}
}