緒論
身為程序員,十大排序是對每一個程序員都應該掌握的算法,現在比較流行的算法如快速排序、歸並排序等,對算法的時間復雜度和空間復雜度的掌握都有要求。本文將分享常見的十大排序算法,基於Java和C語言實現,讓你能夠掌握!
對於排序的分類,可以根據不同的角度比如時間、空間復雜度、比較非比較等角度來划分。我們通常的十大排序都是內部排序,通常的話,基於[比較和非比較]這個層次來划分:
(1)交換類
[1]冒泡排序
基本思想:循環遍歷多次,每次從前往后把大元素往后調,每次確定一個最大(最小)元素,多次到達排序序列。
實現代碼:(Java)
/*
* 1、冒泡排序
*/
public static void maoPaoSort(int[] array) {
for(int i=array.length-1;i>=0;i--) {
for(int j=0;j<i;j++) {
if(array[j]>=array[j+1]) {
int t=array[j];
array[j]=array[j+1];
array[j+1]=t;
}
}
}
}
實現代碼:(C語言)
void bubble_sort(int a[], int n)
{
int i,j,temp;
for (j=0;j<n-1;j++)
{
for (i=0;i<n-1-j;i++)
{
if(a[i]>a[i+1])
{
temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;
}
}
}
}
[2]快速排序
基本思想:將一個序列分為2部分,序列左邊全部小於一個數,序列右邊全部大於一個數。然后利用遞歸的思想再將左序列當成一個完整的序列再進行排序,同樣把序列的右側也當成一個完整的序列進行排序。
實現代碼:(Java)
/*
* 2、快速排序
*/
public static void quickSort(int[] array,int left,int right) {
int low=left;
int high=right;
if(low>high) {
return ;
}
int k=array[low];
while(low<high) {
while(low<high&&array[high]>=k) {
high--;
}
array[low]=array[high];
while(low<high&&array[low]<=k) {
low++;
}
array[high]=array[low];
}
array[low]=k;
quickSort(array,left,low-1);
quickSort(array,low+1,right);
}
實現代碼:(C語言)
void QuickSort(int* data, int left, int right, int direction)
{
int i = left, j = right, index = data[left];
if (data == NULL)
return;
if (right >= sizeof(*data)/sizeof(int))return;
if (left < 0)
return;
if (left >= right)
return;
while(i<j)
{
while(data[j]<=index)
j--;
data[i] = data[j];
while(data[i]>=index&&i < j)
i++;
data[j]=data[i];
}
data[i]=index;
QuickSort(data,left,i-1,direction);
QuickSort(data,i+1,right,direction);
}
(2)插入類
[3]直接插入排序
基本思想:簡單的說,就是按身高來排序,從第一個開始,如果前面有比自己高的,就直接插入到合適的位置。一直到隊伍的最后一個完成插入,整個隊列才能滿足有序。
實現代碼:(Java)
/*
* 直接插入排序
*/
public static void insertSort(int[] array) {
int temp=0;
for(int i=1;i<array.length;i++) {
temp=array[i];
for(int j=i-1;j>=0;j--) {
if(array[j]>temp) {
array[j+1]=array[j];
array[j]=temp;
}else {
break;
}
}
}
}
實現代碼:(C語言)
void insertsort(int *k,int n)
{
int i,j;
int temp;
for(i=1;i<n;i++)
{
temp = k[i];
j = i - 1;
while(j>=0 && k[j]>temp)
{
k[j+1] = k[j];
j--;
}
k[j+1] = temp;
}
}
[4]希爾排序
基本思想:希爾排序是特殊的插入排序,直接插入排序每次插入前的遍歷步長為1,而希爾排序是將待排序列分為若干個子序列,對這些子序列分別進行直接插入排序,當每個子序列長度為1時,再進行一次直接插入排序時,結果一定是有序的。常見的划分子序列的方法有:初始步長(兩個子序列相應元素相差的距離)為要排的數的一半,之后每執行一次步長折半。
實現代碼:(Java)
/*
* 希爾排序
*/
public static void shellSort(int[] array) {
int len=array.length;
int temp=0;
for(;len>=1;len/=2) {
for(int i=len;i<array.length;i++) {
temp=array[i];
for(int j=i-len;j>=0;j-=len) {
if(array[j]>temp) {
array[j+len]=array[j];
array[j]=temp;
}else {
break;
}
}
}
}
}
實現代碼:(C語言)
void shellSort(int *a, int len)
{
int i, j, k, tmp, gap;
for(gap=len/2;gap>0;gap/=2) {
for(i=0;i<gap;++i) {
for(j=i+gap;j<len;j+=gap) {
tmp=a[j];
k=j-gap;
while(k>=0&&a[k]>tmp) {
a[k+gap]=a[k];
k-=gap;
}
a[k+gap]=tmp;
}
}
}
}
(3)選擇類
[5]簡單選擇排序
基本思想:首先,選出最小的數,放在第一個位置;然后,選出第二小的數,放在第二個位置;以此類推,直到所有的數從小到大排序。
實現代碼:(Java)
/*
* 簡單選擇排序
*/
public static void selectSort(int[] array) {
for(int i=0;i<array.length-1;i++) {
int min=i;
for(int j=i+1;j<array.length;j++) {
if(array[j]<array[min]) {
min=j;
}
}
if(min!=i) {
swap1(array,i,min);
}
}
}
public static void swap1(int[] array,int i,int j) {
int t=array[i];
array[i]=array[j];
array[j]=t;
}
實現代碼:(C語言)
void SelectSort(int a[],int n){
int mix,temp;
int i,j;
for(i=0;i<n-1;i++){
mix=i;
for(j=i+1;j<n;j++)
if(a[j]<a[mix])
mix=j;
if(i!=mix) {
temp=a[i];
a[i]=a[mix];
a[mix]=temp;
}
}
}
[6]堆排序
基本思想:將待排序序列構造成一個大頂堆,此時,整個序列的最大值就是堆頂的根節點。將其與末尾元素進行交換,此時末尾就為最大值。然后將剩余n-1個元素重新構造成一個堆,這樣會得到n個元素的次小值。如此反復執行,便能得到一個有序序列了。
實現代碼:(Java)
/*
* 堆排序
*/
public static void swap2(int[] array,int m,int n) {
int t=array[m];
array[m]=array[n];
array[n]=t;
}
public static void shiftDown(int[] array,int index,int len) {
int left=index*2+1;
int right=index*2+2;
if(left>=len) {
return ;
}else if(right<len&&array[right]<array[index]&&array[right]<array[left]) {
swap2(array, index, right);
shiftDown(array, right, len);
}else if(array[left]<array[index]) {
swap2(array, index, left);
shiftDown(array, left, len);
}
}
public static void createHeap(int[] array) {
for(int i=array.length/2;i>=0;i--) {
shiftDown(array, i,array.length);
}
}
public static void heapSort(int[] array) {
int[] val=new int[array.length];
createHeap(array);
for(int i=0;i<array.length;i++) {
val[i]=array[0];
array[0]=array[array.length-1-i];
shiftDown(array, 0, array.length-i);
}
for(int i=0;i<array.length;i++) {
array[i]=val[i];
}
}
實現代碼:(C語言)
void AdjustDown(DataType* a, size_t n, int parent)
{
int child = parent * 2 + 1;
while(child < n)
{
if((child + 1 < n)&&(a[child+1]>a[child]))
{
++child;
}
if(a[child]>a[parent])
{
Swap(&a[child], &a[parent]);
parent=child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void HeapSort(DataType* a, size_t n)
{
assert(a);
for(int i = (n - 2) / 2; i >= 0; i--)
{
AdjustDown(a, n, i);
}
int end = n - 1;
while(end > 0)
{
Swap(&a[0], &a[end]);
AdjustDown(a, end, 0);
--end;
}
}
(4)歸並類
[7]歸並排序
基本思想:將已有序的子序列合並,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合並成一個有序表,稱為二路歸並, 使用中犧牲空間換取時間的算法。
實現代碼:(Java)
/*
* 歸並排序
*/
public static void mergeSort(int[] array,int left,int right) {
int mid=(left+right)/2;
if(left<right)
{
mergeSort(array, left, mid);
mergeSort(array, mid+1, right);
merge(array, left,mid, right);
}
}
public static void merge(int[] array,int l,int mid,int r) {
int lindex=l;
int rindex=mid+1;
int temp[]=new int[r-l+1];
int teamindex=0;
while (lindex<=mid&&rindex<=r) {
if(array[lindex]<=array[rindex])
{
temp[teamindex++]=array[lindex++];
}else {
temp[teamindex++]=array[rindex++];
}
}
while(lindex<=mid)
{
temp[teamindex++]=array[lindex++];
}
while(rindex<=r)
{
temp[teamindex++]=array[rindex++];
}
for(int i=0;i<teamindex;i++)
{
array[l+i]=temp[i];
}
}
實現代碼:(C語言)
void merge(int arr[], int start, int mid, int end) {
int result[ArrLen];
int k = 0;
int i = start;
int j = mid + 1;
while (i <= mid && j <= end) {
if (arr[i] < arr[j]){
result[k++] = arr[i++];
}
else{
result[k++] = arr[j++];
}
}
if (i == mid + 1) {
while(j <= end)
result[k++] = arr[j++];
}
if (j == end + 1) {
while (i <= mid)
result[k++] = arr[i++];
}
for (j = 0, i = start ; j < k; i++, j++) {
arr[i] = result[j];
}
}
void mergeSort(int arr[], int start, int end) {
if (start >= end)
return;
int mid = ( start + end ) / 2;
mergeSort(arr, start, mid);
mergeSort(arr, mid + 1, end);
merge(arr, start, mid, end);
}
(5)桶類排序
[8]桶排序
基本思想:把數組中的所有元素分為若干個數據塊,也就是若干個桶,然后對每個桶里的數據進行排序,最后將所有桶里的數據依次排列即可。
實現代碼:(Java)
/*
* 桶排序
*/
public static int[] bucketSort(int[] nums, int maxNum){
int[] sorted = new int[maxNum+1];
for(int i=0; i<nums.length; i++){
sorted[nums[i]] = nums[i]; //把數據放到對應索引的位置
}
return sorted;
}
實現代碼:(C語言)
typedef struct node {
int key;
struct node *next;
}KeyNode;
void bucket_sort(int keys[],int size,int bucket_size) {
int i,j;
KeyNode **bucket_table = (KeyNode **)malloc(bucket_size * sizeof(KeyNode*));
for(i = 0;i < bucket_size;i++) {
bucket_table[i] = (KeyNode*)malloc(sizeof(KeyNode));
bucket_table[i]->key = 0;
bucket_table[i]->next = NULL;
}
for(j = 0;j < size;j++) {
KeyNode *node = (KeyNode *)malloc(sizeof(KeyNode));
node->key = keys[j];
node->next = NULL;
int index = keys[j]/10;
KeyNode *p = bucket_table[index];
if(p->key == 0) {
bucket_table[index]->next = node;
(bucket_table[index]->key)++;
}else {
while(p->next != NULL && p->next->key <= node->key)
p = p->next;
node->next = p->next;
p->next = node;
(bucket_table[index]->key)++;
}
}
KeyNode * k = NULL;
for(i = 0;i < bucket_size;i++)
for(k = bucket_table[i]->next;k!=NULL;k=k->next)
printf("%d ",k->key);
printf("\n");
}
[9]計數排序
基本思想:先找到最小值min,再找最大值max。然后創建這個區間大小的數組,從min的位置開始計數,這樣就可以最大程度地壓縮空間,提高空間的使用效率。
實現代碼:(Java)
/*
* 計數排序
*/
public static void countSort(int[] array) {
int min=Integer.MAX_VALUE;
int max=Integer.MIN_VALUE;
for(int i=0;i<array.length;i++)
{
if(array[i]<min)
min=array[i];
if(array[i]>max)
max=array[i];
}
int count[]=new int[max-min+1];
for(int i=0;i<array.length;i++)
{
count[array[i]-min]++;
}
int index=0;
for(int i=0;i<count.length;i++)
{
while (count[i]-->0) {
array[index++]=i+min;
}
}
}
[10]基數排序
基本思想:將所有待比較數值(正整數)統一為同樣的數位長度,數位較短的數前面補零。然后,從最低位開始,依次進行一次排序。在每一次排序中,按照當前位把數組元素放到對應的桶當中,然后把桶0到桶9中的元素按先進先出的方式放回數組中。這樣從最低位排序一直到最高位排序完成以后, 數列就變成一個有序序列。
實現代碼:(Java)
/*
* 基數排序
*/
public static void radixSort(int[] array) {
List<Integer> bucket[]=new ArrayList[10];
for(int i=0;i<10;i++)
{
bucket[i]=new ArrayList<Integer>();
}
int max=0;
for(int i=0;i<array.length;i++)
{
if(array[i]>max)
max=array[i];
}
int divideNum=1;
while (max>0) {
for(int num:array)
{
bucket[(num/divideNum)%10].add(num);
}
divideNum*=10;
max/=10;
int idx=0;
for(List<Integer>list:bucket)
{
for(int num:list)
{
array[idx++]=num;
}
list.clear();
}
}
}
結語
十大排序算法就分享給大家了!下面是對算法的總結: