假设含有n个记录的序列为{r1,r2,…,rn},其相应的关键字分别为{k1,k2,…,kn},需确定1,2, 3, …, n的一种排列p1,p2,…,pn,使其相应的关键字满足kp1 ≤kp2≤…≤kpn非递减(或非递增)关系,即使得序列变成一个按关键字有序的序列{rp1,rp2,…,rpn}
[1, 2, 32, 23, 321, 45, 8, 90, 227, 99]从小到大排列(堆排序 我自己还没搞懂 先放着)
常见
排序
冒泡排序
先拿第1第2个数比较,谁大谁后面,接着第2个跟第3个,继续...,最后的那个数一定是最大的。接下来混乱的序列就少了一位,继续剩下的序列继续上面的一轮。这个过程就像一个波浪一次把最大值从前面推到后面
public static void main(String[] args) {
// TODO Auto-generated method stub
int []arr= {1, 2, 32, 23, 321, 45, 8, 90, 227, 99};
for(int i=0;i<arr.length-1;i++) {
for(int j=0;j<arr.length-i-1;j++) {
if(arr[j]>arr[j+1]) {
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
for(int a:arr) {
System.out.print(a+" ");
}
}
//1 2 8 23 32 45 90 99 227 321
选择排序
冒泡排序每次比较后符合要求的都去交换,有些处于中间值的,不是要不断的被交换,不是很浪费时间?能不能选出这段序列中最大的那个数,然后放到最后边? 这就是选择排序。
public static void main(String[] args) {
int []arr= {1, 2, 32, 23, 321, 45, 8, 90, 227, 99};
for(int i=0;i<arr.length-1;i++) {
int k=i;
//位置还不确定的数据
for(int j=i+1;j<arr.length;j++) {
if(arr[j]<arr[k]) {
k=j;
//遍历找到比k小的索引,然后把j赋给k;
}
}
if(i!=k) {
int temp=arr[i];
arr[i]=arr[k];
arr[k]=temp;
}
}
for(int a:arr) {
System.out.print(a+" ");
}
}
//1 2 8 23 32 45 90 99 227 321
插入排序
举个例子,假设现在桌面有几张牌,每次拿起一张,我们在排序的时候会很自然的将牌按照顺序插入合适的位置。这个思想就是插入排序。
public static void insertSort(int[] arr) {
int j = 0;
for (int i = 1; i < arr.length; i++) {
int temp = arr[i];//要插入的值,i位置空出来了
for (j = i; j > 0 && arr[j - 1] > temp; j--) {
arr[j] = arr[j - 1];//j-1 扔到空出来的位置
}
arr[j] = temp;//temp 扔到空出来的位置
}
}
//1 2 8 23 32 45 90 99 227 321
希尔排序
希尔排序排序是插入排序的改进算法,实现原理是将整个无序列分割成若干小的子序列分别进行插入排序,希尔排序并不稳定。该方法又称缩小增量排序。
public static void shellSort(int[] a) {
int dk;//步长
for (dk = a.length / 2; dk > 0; dk /= 2) {
for (int i = dk; i < a.length; i++) {
int temp = a[i];//要插入的值,i位置空出来了
int j;
for (j = i; j >= dk && temp < a[j - dk]; j -= dk)//步长为dk的插入排序
a[i] = a[j - dk]; //j - dk 扔到空出来的位置
a[j] = temp;//temp 扔到空出来的位置
}
}
}
//1 2 8 23 32 45 90 99 227 321
归并排序
将带排序序列分成小组,每个小组自己先弄成有序的,再汇总,这样这种分而治之思想的实际上就是归并排序。
public static void mergerSort(int arr[], int low, int high) {
int mid = (low + high) >> 1;
if (low < high) {
mergerSort(arr, low, mid);
mergerSort(arr, mid + 1, high);
merger(arr, low, mid, high);
}
}
public static void merger(int arr[], int low, int mid, int high) {
int temp[] = new int[high - low + 1]; //临时数组
int t = 0;//临时数组的首索引
int first = low;//第一个数组的首索引
int second = mid + 1;//第二个数组的首索引
// 将练个有序数组比较插入临时数组
while (first <= mid && second <= high) {
temp[t++] = arr[first] < arr[second] ? arr[first++] : arr[second++];
}
// 将数组剩余部分接到临时数组尾部
while (first <= mid) {
temp[t++] = arr[first++];
}
while (second <= high) {
temp[t++] = arr[second++];
}
// 将临时数据合并到原始数组
for (int i = 0; i < temp.length; i++) {
arr[i + low] = temp[i];
}
}
//1 2 8 10 23 32 45 90 99 227 321
快速排序
举个例子:上体育课的时候要高个子站后面矮个子站前面,教练没办法一开始就一眼看出谁高谁矮对,那么多人,肯定是随便逮一个逮个人,来以他为基准进行排序。要求小个子的站这人的前边,大个子的站后边。
而这就是快速排序的核心思想。
public static void quickSort(int arr[], int low, int high) {
if (low < high) {
int index = part(arr, low, high);
quickSort(arr, low, index - 1);
quickSort(arr, index + 1, high);
}
}
public static int part(int arr[], int low, int high) {
int s1=low,s2=high;//定义哨兵
int key = arr[low];
while (s1 < s2) {
while (s1 < s2 && (arr[s2] >= key)) {//哨兵2 向左巡逻 查找小于arr[low]的位置 停下
s2--;
}
swap(arr,s1, s2);
while (s1 < s2 && arr[s1] <= key) {//哨兵1 向右巡逻 查找大于arr[low]的位置 停下
s1++;
}
swap(arr, s1, s2);
}
return s1;
}
public static void swap(int arr[], int s1, int s2) {
int temp = arr[s1];
arr[s1] = arr[s2];
arr[s2] = temp;
}
//1 2 2 6 8 10 23 32 45 90 99 321