-
内部排序:待排序的记录存放在计算机随机存储器中进行的排序过程
-
外部排序:待排序记录的数量很大,内存一次不能容纳全部记录,在排序过程中需要对外存进行访问的排序过程。
-
稳定的排序方法:如果有两个元素相等,排序前后的相对位置不变则是稳定的,否则所用的排序方法就是不稳定的。
-
不稳定的排序: 选择排序、快速排序、希尔排序、堆排序
(选择排序不稳定:4 (4) 2---- 2 (4) 4)
(快速排序不稳定:5 3 4 (3) 8-------(3)3 4 5 8)
一、插入排序
直接插入排序:
二、希尔排序
最大增量:gap = length/2, 缩小增量 gap = gap/2
如下图 length =10,增量依次是:5 ,3,1
三、快速排序
先取第一个元素为base,两个指针,left, right。
初始化: i =left, j =right
只要 i < j.执行以下循环:
从右边开始,找第一个小于base的数,放在 j 的位置,再从左向右找第一个大于base的数,放在i的位置。
将base放在 i 的位置,此时 i= j
再对(left , i - 1)执行快排
对(i +1,right)执行快排
#include<stdio.h>
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<j&&a[j]>=temp)
j--;
if(j>i)
a[i]=a[j];//a[i]已经赋值给temp,所以直接将a[j]赋值给a[i],赋值完之后a[j],有空位
while(i<j&&a[i]<=temp)
i++;
if(i<j)
a[j]=a[i];
}
a[i]=temp;//把基准插入,此时i与j已经相等R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys
quickSort(a,left,i-1);/*递归左边*/
quickSort(a,i+1,right);/*递归右边*/
}
int main()
{
int a[9]={8,2,6,12,1,9,5,5,10};
int i;
quickSort(a,0,8);/*排好序的结果*/
for(i=0;i<8;i++)
printf("%4d",a[i]);
getchar();
return 0;
}
四、选择排序
它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
public class StraightSelectionSort {
public static void sort(int a[]) {
int k=0;
for(int i=0;i<a.length-1;i++){
k=i;
for(int j=i+1;j<a.length;j++){
if(a[j]<a[k]){ //找最小值
k=j;
}
}
if(k!=i){
int temp = a[k];
a[k] = a[i];
a[i] = temp;
}
}
}
}
五、归并排序
先分解,再合并,
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 <iostream>
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<n;k=2*k+1){
if(k+1<n&&arr[k]<arr[k+1]) {
k++;
}
if(temp<arr[k]){
arr[i]=arr[k];
i=k;
}else{
break;
}
}
arr[i]=temp;
}
void heapSort(int arr[],int n){
int i,j;
for(i=n/2-1;i>=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;
}