希尔排序:① 先取一个正整数d1(d1<n)作为第一个增量,将全部n个记录分成d1组,把所有相隔d1的记录放在一组中,即对于每个k(k=1, 2, … d1),R[k], R[d1+k], R[2d1+k] , …分在同一组中,在各组内进行直接插入排序。这样一次分组和排序过程称为一趟希尔排序;
② 取新的增量d2<d1,重复①的分组和排序操作;直至所取的增量di=1为止,即所有记录放进一个组中排序为止。
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[] arr=new int[8];
for (int i = 0; i <8; i++) {
arr[i]=(int)(Math.random()*8000);
}
System.out.println("初始数据为:"+Arrays.toString(arr));
Date date1=new Date();
// SimpleDateFormat simpleDateFormat=new SimpleDateFormat(seconds);
// String str1=simpleDateFormat.format(date1);
// System.out.println("希尔排序前的时间是:"+date1);
shellSort2(arr);
Date date2=new Date();
// String str2=simpleDateFormat.format(date2);
// System.out.println("希尔排序后的时间是:"+date2);
}
//希尔排序【移位式】
public static void shellSort(int[] arr){
int temp=arr.length/2;
int t=0; //临时变量
int j=0;
int insertdata=0;
int sub=0;
int time=1;
while(temp>0){
for (int i = temp; i <arr.length; i++) {
insertdata=arr[i];
sub=i;j=i-temp;
while(j>=0&&insertdata<=arr[j]){
sub=j; //保存数据
arr[j+temp]=arr[j];
j-=temp;
}
arr[sub]=insertdata;
}
System.out.printf("第%d次变化的的数据为:",time++);
System.out.println(Arrays.toString(arr));
temp=temp/2;
}
}
//希尔排序【变换式】
public static void shellSort2(int[] arr){
int temp=arr.length/2;
int t=0; //临时变量
int time=1;
while(temp>0){
for (int i = temp; i <arr.length; i++) {
for (int j = i-temp; j >=0 ; j-=temp) {
if(arr[j+temp]<arr[j]){ //直接交换数据
t=arr[j];
arr[j]=arr[j+temp];
arr[j+temp]=t;
}
}
}
System.out.printf("第%d次变化的的数据为:",time++);
System.out.println(Arrays.toString(arr));
temp=temp/2;
}
}
冒泡排序:依次比较相邻的两个记录的关键字,若两个记录是反序的(即前一个记录的关键字大于后前一个记录的关键字),则进行交换,直到没有反序的记录为止。
public class BubbleSort{
2 public static void main(String[] args){
3 int score[] = {67, 69, 75, 87, 89, 90, 99, 100};
4 for (int i = 0; i < score.length -1; i++){ //最多做n-1趟排序
5 for(int j = 0 ;j < score.length - i - 1; j++){
//对当前无序区score[0......length-i-1]进行排序(j的范围很关键,这个范围是在逐步缩小的)
6 if(score[j] < score[j + 1]){ //把小的值交换到后面
7 int temp = score[j];
8 score[j] = score[j + 1];
9 score[j + 1] = temp;
10 }
11 }
12 System.out.print("第" + (i + 1) + "次排序结果:");
13 for(int a = 0; a < score.length; a++){
14 System.out.print(score[a] + "\t");
15 }
16 System.out.println("");
17 }
18 System.out.print("最终排序结果:");
19 for(int a = 0; a < score.length; a++){
20 System.out.print(score[a] + "\t");
21 }
22 }
23 }
快速排序:通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,再分别对这两部分记录进行下一趟排序,以达到整个序列有序。
void Quick_Sort(int *arr, int begin, int end){
if(begin > end)
return;
int tmp = arr[begin];
int i = begin;
int j = end;
while(i != j){
while(arr[j] >= tmp && j > i)
j--;
while(arr[i] <= tmp && j > i)
i++;
if(j > i){
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
arr[begin] = arr[i];
arr[i] = tmp;
Quick_Sort(arr, begin, i-1);
Quick_Sort(arr, i+1, end);
}
简单选择排序(Simple Selection Sort ,又称为直接选择排序)的基本操作是:通过n-i次关键字间的比较,从n-i+1个记录中选取关键字最小的记录,然后和第i个记录进行交换,i=1, 2, … n-1 。
1.工作原理
在未排序序列中找到最小(大)的元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)的元素,存放到已排序序列的末尾,直到所有元素排序完。
2.对于 n 个元素的时间复杂度为 O(n^2);
3.n比较大的话,效率也会与冒泡排序类似,不稳定。
void seletSort(int a[], int len)
{
int i, j, k;
for (i = 0; i < len; i++)
{
k = i; //初始化最小的标记
for (j = i; j < len; j++)
{
if (a[j] < a[k])
{
k = j;
}
}
int temp = a[i]; //交换值
a[i] = a[k];
a[k] = temp;
}
}
堆排序:由堆的定义知,堆是一棵以k1为根的完全二叉树。若对该二叉树的结点进行编号(从上到下,从左到右),得到的序列就是将二叉树的结点以顺序结构存放,堆的结构正好和该序列结构完全一致。
public static void heapSort(int[] arr) {
//1.构建大顶堆
for (int i = arr.length / 2 - 1; i >= 0; i--) {
//从第一个非叶子结点从下至上,从右至左调整结构
adjustHeap(arr, i, arr.length);
}
//然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换。
//2.调整堆结构+交换堆顶元素与末尾元素
for (int j = arr.length - 1; j > 0; j--) {
swap(arr, 0, j);//将堆顶元素与末尾元素进行交换
adjustHeap(arr, 0, j);//重新对堆进行调整
}
}
/**
* 调整大顶堆(仅是调整过程,建立在大顶堆已构建的基础上, 也就是说只调用一次,并没有得到大顶堆)
* 就是将arr[i] 的值放到本次 调整过程中适当的位置。
* @param arr : 数组
* @param i : 非叶子节点的索引
* @param length : 对多少个元素进行调整,这个length是逐渐减少的..
*/
public static void adjustHeap(int[] arr, int i, int length) {
int temp = arr[i];//先取出当前元素i
for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {//从i结点的左子结点开始,也就是2*i+1处开始
if (k + 1 < length && arr[k] < arr[k + 1]) {//如果左子结点小于右子结点,k指向右子结点
k++;
}
if (arr[k] > temp) {//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
arr[i] = arr[k];//把较大的值,赋给当前节点
i = k;//i 指向k,继续循环比较
} else {
break;
}
}
arr[i] = temp;//将temp值放到最终的位置
}
public static void swap(int[] arr, int a, int b) {
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}