常用的8種排序算法(C語言)

1. 冒泡排序

#include <stdio.h>
int main(void)
{
	int a[10] = {1,2,3,4,5,6,7,8,9,10};
	int len = sizeof(a) / sizeof(a[0]);
	/* 大循環len-1次即可 */
	for(int i=0; i<len-1; i++){
		/*相鄰交換小循環,隨着最大值到最後確定,循環次數變少*/
		for(int k=0; k<len-1-i; k++){
			if(a[k] < a[k + 1]){
				/*交換*/
				int temp = a[k];
				a[k] = a[k+1];
				a[k+1] = temp;
			}
		}
	}
	for(int i=0; i<len; i++){
		printf("%d ", a[i]);
	}
	return 0;
} 

2. 選擇法排序

#include <stdio.h>
int main(void)
{
	int a[10] = {1,2,3,4,5,6,7,8,9,10};
	int len = sizeof(a) / sizeof(a[0]);
	/*大循環len-1次即可*/
	for(int i=0; i<len-1; i++){
		/*每次判斷最大數,依次往前放*/
		for(int k=i+1; k<len; k++){
			if(a[i] < a[k]){
				int temp = a[i];
				a[i] = a[k];
				a[k] =temp;
			}
		}
	}
	/*輸出*/
	for(int i=0; i<len; i++){
		printf("%d ", a[i]);
	}
	return 0;
} 

3. 插入法排序

#include <stdio.h>
int main(void)
{
	int a[10] = {1,2,3,4,5,6,7,8,9,10};
	int i, j;
	int len = sizeof(a) / sizeof(a[0]);
	for(i=1; i<len; i++){
		/*等待插入的值*/
		int wait = a[i];
		/*尋找插入點*/
		for(j=i-1; j>=0; j--){
			if(a[j] < wait){
				a[j + 1] = a[j];
			}
			else{
				break;
			}
		}
		/*出循環時 j 要減 1, 所以a[j+1]是插入的地方*/
		a[j + 1] = wait;
	}
	/*輸出*/	
	for(i=0; i<len; i++){
		printf("%d ", a[i]);
	}
	return 0;
}

4. 折半法排序

#include <stdio.h>
void binary_insert_sort(int a[], int len);
int main(void)
{
	int a[] = {73,108,112,118,101,70,105,115,104,67,46,99,111,109};
	int i, len;
	len=sizeof(a) / sizeof(a[0]);
	
	binary_insert_sort(a, len);
	
	for(i=0; i<len; ++i){
		printf("%d ",a[i]);
	}		
	return 0; 
}

void binary_insert_sort(int a[], int len){
	int low, mid, high;
	/*和插入排序差不多,也是將第二個元素先作爲待插入元素*/
	/*只不過在尋找插入位置的時候利用折半查找法*/
	for(int i=1; i<len; ++i){
		int temp = a[i];
		low = 0;
		high = i - 1;
		while(low <= high){     		/*這裏是 <= 不要搞錯,可以舉個栗子試試*/
			mid = (low + high) / 2;	
			if(temp < a[mid]){
				high = mid - 1;
			}		
			else{
				low = mid + 1;
			}
		}
		
		for(int j=i-1; j>high; --j){  	/* hight + 1 即爲正確位置的下標*/ 
			a[j + 1] = a[j];
		}
		a[high + 1] = temp;
	}
}

5. 希爾排序

#include <stdio.h>
int main(void)
{
	int a[10] = {1,2,3,4,5,6,7,8,9,10};
	int i, j, step;
	int len = sizeof(a) / sizeof(a[i]);
	for(int step=len/2; step>0; step/=2){/*步長*/
	
		for(i=0+step; i<len; i+=step){/*不是加 1 了,而是加步長*/
			int wait = a[i]; /*等待插入的數*/
			for(j=i-1; j>=0; j--){
				if(a[j] < wait){
					a[j + 1] = a[j];
				}
				else{
					break;
				}
			}
			a[j + 1] = wait;
		} 
	} 
	/*輸出*/	
	for(i=0; i<10; i++){
		printf("%d ", a[i]);
	}
	return 0;
}

6. 桶排序

#include <stdio.h>
int searchMax(int a[], int len);
int main(void)
{
	int max, len;
	int a[11] = {1,2,3,4,5,6,7,8,9,10,40};
	len = sizeof(a) / sizeof(a[0]);
	max = searchMax(a, len);
	int bucket[max + 1] = {0};/*創建 max + 1 個桶*/
	/*變長數組是c99以後的新增特性,傳入的並非變量,而是數值*/
	for(int i=0; i<len; i++){
		bucket[a[i]]++;
	}	
	/*輸出*/
	for(int i=max; i>0; i--){
		for(int k=bucket[i]; k>0; k--){/*考慮重複的數字*/
			printf("%d ", i);/*輸出桶的序號*/
		}
	}
	return 0;
} 
/*尋找最大數*/
int searchMax(int a[], int len){
	int max = a[0];
	for(int i=1; i<len; i++){
		if(a[i] > max){
			max = a[i];
		}
	}
	return max;
}

7. 快速排序

//遞歸的典型應用 
//二十世紀十大算法之一 
#include <stdio.h>
void quick_sort(int a[], int left, int right);

int main(void)
{
	int a[] = {73, 108, 112, 118, 101, 70, 105, 115, 104, 67, 46, 99, 111, 109};
	int i, len;
	len = sizeof(a) / sizeof(a[0]);
	quick_sort(a, 0, len-1);
	for(i=0; i<len; i++){
		printf("%d ", a[i]);
	}		
	return 0; 
}

void quick_sort(int a[],int left, int right){
	int i = left, j = right;
	int key;
	key = a[(left + right) / 2];
	while(i <= j){
		/* 從左到右找到大於基準點的元素*/
		 while (a[i] < key){
		 	i++;
		  } 
		  
		/* 從右到左找到大於基準點的元素*/
		while (a[j] > key) {
			j--;
		}
		
		/* 如果 i<=j,則互換 */
		if (i <= j) {
			int temp = a[i];
			a[i++] = a[j];
			a[j--] = temp;
		} 		
	}
	
	if(j > left) {
		quick_sort(a, left, j);
	}
	
	if(i < right) {
		quick_sort(a, i, right);
	}
}

8. 堆排序

  1. 父結點索引:(i - 1) / 2(這裏計算機中的除以2,省略掉小數)
  1. 左孩子索引:2 * i + 1
  1. 右孩子索引:2 * i + 2
  1. 最後一個父節點:n / 2 - 1
#include <stdio.h>
void creat_heap(int a[], int len);/*創建堆*/
void adjust(int a[], int root, int len); /*創建堆的過程*/
void heap_sort(int a[], int len);/*排序*/
void swap(int *a, int step1, int step2);/*交換數組中的兩個數*/

int main (void) {
	int a[] = {73,108,112,118,101,70,105,115,104,67,46,99,111,109};
	int len = sizeof(a) / sizeof(a[0]);
	
	heap_sort(a, len);
	
	for(int i=0; i<len; i++){
		printf("%d ", a[i]);
	}
	return 0;
}

/*調整堆*/
void adjust_heap(int a[], int i, int len){
	int j = i*2+1;  /*左孩子引索*/
	while(j < len){
		/*建立大堆,將 j 取值爲左右孩子中大孩子的下標 */
		if(j+1<len && a[j] < a[j + 1]){
			j++;
		}
		/*判斷若父節點大於兩個孩子節點,則無需交換*/
		if(a[i] > a[j]){
			break;/*說明該父結點和其孩子結點調整結束,退出循環,從下一個父結點調整*/ 
		} 
		/* 交換之後還要考慮該目前j結點與自己的孩子結點的數值比較,還要進行調整,將i當前結點換成j結點所在位置*/
		swap(a, i, j);
		i = j;
		j = 2*i+1;
	} 
}

/*創建一個堆*/
void creat_heap(int a[], int len){
	int i;
	for(i=len/2-1; i>=0; i--){
		adjust_heap(a, i, len);
	}
}

/*交換兩個元素*/
void swap(int *a, int step1, int step2) {
    int temp = *(a+step1);
    *(a+step1) = *(a+step2);
    *(a+step2) = temp;
}
/*排序*/
void heap_sort(int a[], int len){
	creat_heap(a, len);
	/*每次排出最大的一個元素之後,將該元素排除在堆外,調整堆後交換堆頂元素和堆的最後一個元素*/
	/*從最後一個開始*/
	for(int i=len-1; i>=0; i--){
		swap(a, i, 0);
		/*交換好堆後,重新調整堆*/
		adjust_heap(a, 0, i);
	}													
}					

  1. 我喜歡他這個動畫:https://www.jianshu.com/p/0d383d294a80
    在這裏插入圖片描述

  2. 先去大佬那看看啥是堆

  3. 大佬的圖解

  4. 實在不行去bi站看一眼:https://www.bilibili.com/video/av62952101/?spm_id_from=333.788.videocard.1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章