内部排序:待排序的记录存放在计算机随机存储器中进行的排序过程
外部排序:待排序记录的数量很大,内存一次不能容纳全部记录,在排序过程中需要对外存进行访问的排序过程。
稳定的排序方法:如果有两个元素相等,排序前后的相对位置不变则是稳定的,否则所用的排序方法就是不稳定的。
堆排序、快速排序、希尔排序、直接选择排序是不稳定的排序算法
而基数排序、冒泡排序、直接插入排序、折半插入排序、归并排序是稳定的排序算法。
(选择排序不稳定:4 (4) 2---- 2 (4) 4)
一、插入排序
直接插入排序:(稳定的)
刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳 定的。
public static void insertSort(int[] arr,int length){
int i,j;
for(i = 1;i < length;i++){
int temp = arr[i];//待插入的元素
for(j=i-1;j >= 0 && arr[j]>temp;j--){
arr[j+1]=arr[j];//元素后移,寻找插入位置
}
arr[j+1] = temp;
}
}
二、希尔排序
最大增量:gap = length/2, 缩小增量 gap = gap/2
如下图 length =10,增量依次是:5 ,3,1
public static void shellSort(int array[],int lenth){
int temp = 0;
int incre = lenth;
while(true){
incre = incre/2;
for(int k = 0;kk;j-=incre){
if(array[j]
冒泡排序:
冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改 变,所以冒泡排序是一种稳定排序算法。
public static void bubbleSort(int[] arr,int len){
bool isSwap=false;
for(int i=0;iarr[j+1])
{
int temp=arr[j];//交换
arr[j]=arr[j+1];
arr[j+1]=temp;
isSwap=true;
}
}
if(isSwap==false)
return;
}
三、快速排序
先取第一个元素为base,两个指针,left, right。
初始化: i =left, j =right
只要 i < j.执行以下循环:
从右边开始,找第一个小于base的数,放在 j 的位置,再从左向右找第一个大于base的数,放在i的位置。
将base放在 i 的位置,此时 i= j
再对(left , i - 1)执行快排
对(i +1,right)执行快排
#include
void quickSort(int a[],int left,int right)
{
int i=left;
int j=right;
int temp=a[left];
if(left>=right)
return;
while(i!=j)
{
while(i=temp)
j--;
if(j>i)
a[i]=a[j];
while(i
四、选择排序
它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
public static void selectSort(int array[],int lenth){
for(int i=0;i
public class StraightSelectionSort {
public static void sort(int a[]) {
int k=0;
for(int i=0;i
五、归并排序
先分解,再合并,
if(left < right) {
int mid = (left + right)/2;
sort(arr, left, mid, temp);//temp是中间变量
sort(arr, mid + 1,right, temp);
merge(arr, left, right, temp);
}
import java.util.Arrays;
public class MergeSort {
public static void main(String[] args) {
int[] arr = {9,8,7,6,5,4,3,2,1};
sort(arr);
System.out.println(Arrays.toString(arr));
}
private static void sort(int[] arr) {
// TODO Auto-generated method stub
int[] temp = new int[arr.length];
sort(arr, 0, arr.length - 1, temp);
}
private static void sort(int[] arr, int left, int right, int[] temp) {
// TODO Auto-generated method stub
if(left < right) {
int mid = (left + right)/2;
sort(arr, left, mid, temp);
sort(arr, mid + 1,right, temp);
merge(arr, left, right, temp);
}
}
private static void merge(int[] arr, int left, int right, int[] temp) {
// TODO Auto-generated method stub
int mid = (left + right)/2;
int i = left;
int j = mid + 1;
int k = 0;
while(i <= mid && j <= right) {
if(arr[i] < arr[j])
temp[k++] = arr[i++];
else
temp[k++] = arr[j++];
}
while(i <= mid)
temp[k++] = arr[i++];
while(j <= mid)
temp[k++] = arr[j++];
int t = 0;
while(left <= right)
arr[left++] = temp[t++];
}
}
运行结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
六、堆排序
大顶堆:每个结点的值 >= 左右孩子结点的值
小顶堆:每个结点的值 <= 左右孩子结点的值
升序:用大顶堆 降序:用小顶堆
对以下序列排序:4 6 8 5 9
初始化堆,调整堆,交换堆顶元素与末尾元素
#include
void swap(int *&arr,int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
void buildHeap(int *&arr,int i,int n){//以arr[i]为根建立堆(升序大顶堆)
int temp=arr[i];
for(int k=2*i+1;k=0;i--){//建好了堆
buildHeap(arr,i,n);
}
for(j=n-1;j>=0;j--){
swap(arr,j,0);
buildHeap(arr,0,j);
}
}
int main(int argc, char** argv) {
int arr[]={4,12,35,98,4,44,58,13,15};
heapSort(arr,9);
for(int i=0;i<9;i++){
printf("%d ",arr[i]);
}
return 0;
}