十大经典排序算法

十大经典排序算法(附有动图演示哦吐舌头)

      


A>交换排序---冒泡排序

  a>冒泡排序(Bubble Sort)

 算法描述:比较两个相邻的元素,如果升序的话,前面的比后面的大,就交换,这样一轮下来,就会找到这组数据中最大的元素,然后抛开这个元素继续重复上述步骤.知道排完为止.   

   b>冒泡排序(Bubble Sort)动图演示


b>冒泡排序(Bubble Sort)代码实现

#include<stdio.h>
#include<stdlib.h>
void swap(int *a, int *b){
	int ret = 0;
	ret = *a;
	*a = *b;
	*b = ret;
}
void Bubble_sort(int *arr,int size){
	int i = 0;
	int j = 0;
	for ( i = 0; i < size-1; i++)
	{
		for (j = 0; j < size-1-i; j++)
		{
			if (arr[j]>arr[j+1])//这是升序的写法,降序将改为if(arr[j]<arr[j+1])
			{
				swap(&arr[j], &arr[j+1]);
			}
		}
	}
}
int main(){
	int i = 0;
	int arr[10] = { 2, 0, 4, 9, 3, 6, 8, 7, 1, 5 };
	int size = sizeof(arr) / sizeof(arr[0]);
	Bubble_sort(arr,size);
	for ( i = 0; i < size; i++)
	{
		printf("%d ", arr[i]);
	}
	system("pause");
	return 0;
}

A>交换排序---快速排序

   a>快速排序(Quick Sort)

     算法描述:任取待排序中的某一元素作为基准值,按照该排序码,将待排序集合分割成两个子序列,左边的序列比基准值小,右边的比基准值大.然后对左右子序列重复上述步骤.直到排完为止

   b>快速排序(Quick Sort)动图展示


   c>快速排序代码实现(Quick Sort)

#include "stack.h"
#include<stdio.h>
#include<stdlib.h>
void swap(int *a, int *b){
	int ret = 0;
	ret = *a;
	*a = *b;
	*b = ret;
}
//设定一个基准值,在保证不越界的情况下,从前往后查找比基准值小的元素,找到了然后停下来,若begin和end没有相遇,就交换,相遇了
//就交换begin和数组中基准值所代表的元素
int GetBaseKey(int *array,int left,int right){
	int mid = left + ((right - left) >> 1);
	if (array[left]<array[right]){
		if (array[mid]<array[left])
			return left;
		else if (array[mid]>array[right])
            return right;
	    else
	        return mid;
		
	}
	else
	{
		if (array[mid]>array[left])
		   return left;
	    else if (array[mid] < array[right])
		   return right;
		else
			return mid;
	}
}
//Hoare版本
int partion_hoare(int *array, int left, int right){
	int begin = left;
	int end = right - 1;
	int key_index = GetBaseKey(array, left, right-1);
	swap(&array[key_index], &array[right - 1]);
	int key = array[right-1];
	while (begin<end)
	{
		while ((begin<end)&&array[begin]<key)
		   begin++;
		while ((begin<end)&&array[end]>=key)
		   end--;
		if (begin<end)
		   swap(&array[begin], &array[end]);
		
	}
	if (begin!=right-1)
	   swap(&array[begin], &array[right-1]);
	return begin;
}
//快速排序---挖坑法
int partion_WK(int *array, int left, int right){
	int begin = left;
	int end = right-1;
	int key_index = GetBaseKey(array, left, right - 1);
	swap(&array[key_index], &array[right - 1]);
	int key = array[right - 1];
	while (begin<end)
	{
		while (begin<end&&array[begin]<key)
		  begin++;
		if (begin < end)
		{
			array[end] = array[begin];
			end--;
		}
		while (begin<end&&array[end]>key)
			end--;
		if (begin < end)
		{
			array[begin] = array[end];
			begin++;
		}
	}
	if (begin!=right-1)
	{
		array[begin] = key;
	}
	return begin;
}
//快速排序---前后指针
int partion_P(int *array, int left, int right){
	int pre = left-1;
	int pcur = left;
	int key_index = GetBaseKey(array, left, right - 1);
	swap(&array[key_index], &array[right - 1]);
	int key = array[right - 1];
	while (pcur<right)
	{
		if (array[pcur] < key&&(++pre) != pcur)
			swap(&array[pre], &array[pcur]);
		pcur++;
		
	}
	if ((++pre)!=right-1)
	{
		swap(&array[pre], &array[right-1]);
	}
	return pre;
}
//递归
void QuickSort(int *array,int left,int right){
	if (right-left>1)
	{
		//int base = partion_hoare(array, left, right);
        //int base = partion_WK(array, left, right);
		int base = partion_P(array, left, right);
		QuickSort(array, 0, base);
		QuickSort(array,base+1,right);
	}
}
//非递归,利用栈保存边界
int QuickSort_Nor(int *array,int size){
	int base = 0;
	int left = 0;
	int right = 0;
	SeqStack s;
	StackInit(&s);
	StackPush(&s,size);//保存右边界
	StackPush(&s, 0);//保存左边界
	while (!StackEmpty(&s))
	{
		left = StackTop(&s);
		StackPop(&s);
		right = StackTop(&s);
		StackPop(&s);
		if (left<right)
		{
			base = partion_hoare(array, left, right);
			StackPush(&s, right);//保存右边界
			StackPush(&s, base + 1);//保存左边界
			StackPush(&s, base);
			StackPush(&s, left);
		}
		
	}
	
}
int main(){
	int i = 0;
	int arr[] = {2,0,4,9,3,6,8,7,1,5};
	//int arr[] = {1,2,3,4,5,6};
	int size = sizeof(arr) / sizeof(arr[0]);
	//QuickSort(arr,0,size);
	QuickSort_Nor(arr, size);
	for (i = 0; i < size; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	system("pause");
	return 0;
}

B>插入排序---直接插入排序

   a>直接插入排序(Insertion sort)

  算法描述:从第一个元素开始,该元素已经排好序,继续取元素与排好序的元素依次进行比较,升序的话插入到比前一个大比后一个小的位置,然后重复上述步骤,直到插完元素为止.

  b>直接插入排序(Insertion sort)动图展示


  c>直接插入排序(Insertion sort)代码实现

#include<stdio.h>
#include<stdlib.h>
//二分查找相比较顺序查找而言,比较的次数比较少.
//插入排序在原本升序排升序,原本逆序排逆序,元素集合接近有序时,直接插入排序效率较高.
//直接插入排序,顺序查找
void insert_sort(int *pArr, int size){
	int i = 0;
	int key = 0;
	int end = 0;
	for ( i = 1; i < size; i++)
	{
		key = pArr[i];
		end = i - 1;
		while (end>=0&&key<pArr[end])
		{
			pArr[end+1]=pArr[end];
			end--;
		}
		pArr[end + 1] = key;
	}
}
//直接插入排序,二分查找
void insert_sort_second(int *pArr, int size){
	int left = 0;
	int right = size-1;
	int mid = 0;
	int i = 0;
	int key = 0;
	for (i = 1; i < size; i++)
	{
		key = pArr[i];
		left = 0;
		right = i - 1;
		//二分查找寻找待插入元素的位置
		while (left <= right)
		{
			mid = (left + right) >> 1;
			if (key<pArr[mid])
			{
				right = mid - 1;
			}
			else
			{
				left = mid + 1;
			}
		}
		//搬移left位置以后的元素
		right = i - 1;
		while (right>=left)
		{
			pArr[right + 1] = pArr[right];
			right--;
		}
		//插入元素
		pArr[left] = key;
    }
}
int main(){
	int i = 0;
	int array[9] = {2,6,4,9,5,8,7,0,1};
	int size = sizeof(array) / sizeof(array[0]);
	//insert_sort(array, size);
	insert_sort_second(array, size);
	for ( i = 0; i < size; i++)
	{
		printf("%d ", array[i]);
	}
	printf("\n");
	system("pause");
	return 0;
}

B>插入排序---希尔排序(直接插入排序的优化)

    a>希尔排序(Shell sort)     

   算法描述:对整个待排序序列进行分组,然后对每一组进行直接插入排序.

                                 

  b>希尔排序(Shell sort)动图展示


c>希尔排序(Shell sort)代码实现

#include<stdio.h>
#include<stdlib.h>
void Shell_Sort(int *pArr,int size){
	int i = 0;
	int key = 0;
	int end = 0;
	int gap = 3;
	while (gap > 0)
	{
		for (i = gap; i < size; i++)
		{
			key = pArr[i];
			end = i - gap;
			while (end >= 0 && key<pArr[end])
			{
				pArr[end + gap] = pArr[end];
				end=end-gap;
			}
			pArr[end + gap] = key;
		}
		gap--;
	}
}
int main(){
	int i = 0;
	int array[9] = { 2, 6, 4, 9, 5, 8, 7, 0, 1 };
	int size = sizeof(array) / sizeof(array[0]);
	Shell_Sort(array, size);
	for (i = 0; i < size; i++)
	{
		printf("%d ", array[i]);
	}
	printf("\n");
	system("pause");
	return 0;
}

C>选择排序---直接选择排序   

a>直接选择排序(Insertion sort)

   算法描述:在未排序的序列中找到最小的元素,存放到序列的首位置,找到最大的元素存放到序列的末尾.然后抛开首位和末尾,继续重复该步骤,直到排完为止.

 b>直接选择排序(Insertion sort)动图展示


 c>直接选择排序(Insertion sort)代码实现

#include<stdio.h>
#include<stdlib.h>
void swap(int *a,int *b){
	int ret = 0;
	ret = *a;
	*a = *b;
	*b = ret;
}
void Selection(int *arr,int size){
	int left = 0;
	int right = size - 1;
	int i = 0;
	while (left<right)
	{
		int MinIndex = left;
		int MaxIndex = left;
		for (i = left; i <= right; i++)
		{
			if (arr[MinIndex]>arr[i])
				MinIndex = i;
			if (arr[MaxIndex]<arr[i])
				MaxIndex = i;
		}
		swap(&arr[left],&arr[MinIndex]);
		if (MaxIndex==left)
		{
			MaxIndex = MinIndex;
		}
		swap(&arr[right], &arr[MaxIndex]);
		left++;
		right--;
	}
}
int main(){
	int i = 0;
	int arr[10] = {2,5,4,9,3,6,8,7,1,0};
	int size = sizeof(arr) / sizeof(arr[0]);
	Selection(arr,size);
	for ( i = 0; i < size; i++)
	{
		printf("%d ",arr[i]);
	}
	system("pause");
	return 0;
}
C>选择排序---堆排序   

a>堆排序(Heap sort)

   算法描述:若升序的话,就将堆调成一个大堆,若降序的话,就将堆调成一个小堆.从倒数第一个非叶子节点开始往根遍历,若当前节点的值都大于左右孩子,则不用动,若是小于,就将左右孩子当中最大的节点与当前节点交换,交换后就需要进行向下调整(因为交换会影响大堆结构).重复上述步骤,直到根节点为止.

  b>堆排序(Heap sort)动图展示


  c>堆排序(Heap sort)代码实现

#include "Heap.h"
#include<stdio.h>
#include<stdlib.h>
//向下调整 
void HeapAdjust(int *arrar,int size,int parent){
	int child = parent * 2 + 1;
	while (child<size)
	{
		if ((child + 1)<size&&arrar[child + 1]>arrar[child])
			child += 1;
		if (arrar[parent]<arrar[child])
		{
			swap(&arrar[parent], &arrar[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		  return;
	
	}
	
}
void HeapSort(int arrar[],int size){
	//1,建堆
	int root = ((size - 2) >> 1);
	int end = size - 1;
	for ( ;  root>=0; --root)
	{
		HeapAdjust(arrar, size, root);
	}
	//2,调整
	while (end)
	{
		swap(&arrar[end],&arrar[0]);
		HeapAdjust(arrar, end, 0);
        --end;
	}

}
int main(){
	int arrar[] = { 53, 17, 78, 9, 45, 65, 87, 23, 31 };
	int size = sizeof(arrar) / sizeof(arrar[0]);
	HeapSort(arrar,size);
	for (int i = 0; i <size; i++)
	{
		printf("%d ", arrar[i]);
	}
	system("pause");
	return 0;
}

D>归并排序(Merge Sort)   

   a>归并排序(Merge Sort)      

  算法描述:将待排序的元素序列分为两个长度相等的子序列,对每个子序列进行排序,然后将他们合并成一个序列,合并两个子序列的过程称为二路归并.

   b>归并排序(Merge Sort)动图展示     


  c>归并排序(Merge Sort)代码演示

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
#include<assert.h>
//归并
void MergeData(int *arr,int left,int mid,int right,int *temp){
	int temp_index = left;
	int left_L = left;
	int left_R = mid;
	int right_L = mid;
	int right_R = right;
	while (left_L<left_R && right_L<right_R)
	{
		if (arr[left_L]<arr[right_L])
		{
			temp[temp_index++] = arr[left_L++];

		}
		else
		{
			temp[temp_index++] = arr[right_L++];
		}

	}
	while(left_L<left_R)
	{
		temp[temp_index++] = arr[left_L++];
	}
	while (right_L<right_R)
	{
		temp[temp_index++] = arr[right_L++];
	}

}
//分组
//void *memcpy(void*dest, const void *src, size_t n);
//由src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内。
void _MergeSort(int *arr, int left, int right, int *temp){
	if ((right-left)>1)
	{
		int mid = left + ((right-left)>>1);
		_MergeSort(arr,left,mid,temp);
		_MergeSort(arr, mid, right, temp);
		MergeData(arr,left,mid,right,temp);
		memcpy(arr+left,temp+left,sizeof(int)*(right-left));
	}


}
//递归
void MergeSort(int *arr,int size){
	int *temp = (int *)malloc(size*sizeof(arr[0]));
	if (temp==NULL)
	{
		assert(0);
		return;
	}
	_MergeSort(arr,0,size,temp);
	free(temp);
}
//非递归
void MergeSort_Nor(int *arr, int size){
	int *temp = (int *)malloc(size*sizeof(arr[0]));
	if (temp == NULL)
	{
		assert(0);
		return;
	}
	int i = 0;
	int gap = 1;
	while (gap<size)
	{
		for (i = 0; i < size;i+=2*gap){
			int left = i;
			int mid = left + gap;
			int right = mid + gap;
			if (mid>size)
			{
				mid = size;
			}
			if (right>size)
			{
				right = size;
			}
			MergeData(arr, left, mid, right, temp);
		}
		memcpy(arr,temp,size*sizeof(arr[0]));
		gap=gap*2;
	}
	free(temp);
}
int main(){
	int arr[10] = { 2, 0, 4, 9, 3, 6, 8, 7, 1, 5 };
	int size = sizeof(arr) / sizeof(arr[0]);
	MergeSort(arr,size);
	//MergeSort_Nor(arr, size);
	for (int i = 0; i < size; i++)
	{
		printf("%d ", arr[i]);
	}
	system("pause");
	return 0;
}

E>计数排序(鸽巢原理)(Counting Sort)   

   a>计数排序(Counting Sort)        

  算法描述:找到待排序列中最大最小的元素,然后以此确定临时空间的大小,在临时空间中,以待排序列组中元素的大小为下标,该元素出现的次数为该下标对应的元素,根据临时空间的统计结果,重新对元素进行回收.

   b>计数排序(Counting Sort)动图展示     


  c>计数排序(Counting Sort)代码实例

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<malloc.h>
int GetMaxValue(int *arr,int size){
	int i = 0;
	int max = arr[0];
	for ( i = 1; i < size; i++)
	{
		if (arr[i]>max)
			max = arr[i];
	}
	return max;

}
int GetMinValue(int *arr, int size){
	int i = 0;
	int min = arr[0];
	for (i = 1; i < size; i++)
	{
		if (arr[i]<min)
			min = arr[i];
	}
	return min;

}
void _Count_Sort(int *arr, int *temp,int size,int ret,int min){
	int i = 0;
	int index = 0;
	//统计个数
	for ( i = 0; i < size; i++)
	{
		temp[arr[i]-min]++;
	}
	//回收,把temp里的数据回收到原空间里
	for ( i = 0; i <ret ; i++)
	{
		while (temp[i]--)
		{
			arr[index++] = i+min;
		}
	}
	free(temp);
}
void Count_Sort(int *arr,int size){
	int max = GetMaxValue(arr,size);
	int min = GetMinValue(arr, size);
	int ret = max - min + 1;
	int *temp = (int *)malloc(ret*sizeof(arr[0]));
	if (temp==NULL)
	{
		assert(0);
		return;
	}
	//memset作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法
	memset(temp,0,ret*sizeof(int));
    _Count_Sort(arr,temp,size,ret,min);
}
int main(){
	int i = 0;
	int arr[10] = {3,4,3,2,1,2,6,5,4,7};
	int size = sizeof(arr) / sizeof(arr[0]);
    Count_Sort(arr,size);
	for ( i = 0; i < size; i++)
	{
		printf("%d ", arr[i]);
	}
	system("pause");
	return 0;
}
F>基数排序(Radix Sort)----LSD(底关键码)

   a>基数排序(Radix Sort)    

  算法描述:把待排序中的元素按照低位先排序,然后收集,再按照高位排序,再收集,直至最高位.①,获取序列中的最大数,然后取得其位数,然后利用计数排序的特点,定义10个元素的数组,分别统计以待排序列元素的每一位为数组的下标的元素的个数,然后再定义一个数组存每个的起始地址.开一个辅助空间,放置元素.再回收这些元素.

 b>基数排序(Radix Sort)动图展示

 c>基数排序(Radix Sort)代码展示


#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>
#include<string.h>
//统计最大元素的位数
int GetMaxValue_BitCount(int *arr,int size){
	int i = 0;
	int count = 1;
	int ret = 10;
	for ( i = 0; i < size; i++)
	{
		while (arr[i] >= ret)
		{
			count++;
			ret *= 10;
		}
	}
	return count;
}
void _RadixSort(int *arr,int size,int *temp){
	int Max_BitCount = GetMaxValue_BitCount(arr, size);
	//存每个桶中元素的个数.
	int count[10] = { 0 };
	//存每个桶的起始地址
	int start_Addr[10] = { 0 };
	int i = 0;
	int ret = 1;
	int index = 0;
	while (Max_BitCount)
	{
		//统计个数
		for ( i = 0; i < size; i++)
		{
			count[arr[i] / ret % 10]++;
		}
		//计算地址
		for ( i = 1; i < 10; i++)
		{
			start_Addr[i] = start_Addr[i - 1] + count[i - 1];
		}
		//放置元素到临时空间中
		for (i = 0; i <size; i++){
			int Addr = arr[i]/ret% 10;
			temp[start_Addr[Addr]++] = arr[i];
		}
		//回收元素
		//memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。
		//void *memcpy(void *dest, const void *src, size_t n);
		memcpy(arr,temp,size*sizeof(arr[0]));
		ret *= 10;
		Max_BitCount--;
	}

}
void RadixSort(int *arr,int size){
	int *temp = (int *)malloc(size*sizeof(arr[0]));
	if (temp==NULL)
	{
		assert(0);
		return;
	}
	_RadixSort(arr,size,temp);
	free(temp);
}
int main(){
	int arr[11] = {198,254,378,852,761,554,581,552,605,479,853};
	int size = sizeof(arr) / sizeof(arr[0]);
	RadixSort(arr,size);
	for (int  i = 0; i < size; i++)
	{
		printf("%d ", arr[i]);
	}
	system("pause");
	return 0;
}


  • 233
    点赞
  • 1388
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值