算法---八大排序

算法

1.冒泡排序

//冒泡排序
//时间复杂度O(n^2) 
//空间复杂度O(1)
//稳定性:稳定
void Swap(int* ap, int* bp)
{
	assert(ap != NULL && bp != NULL);
	if (*ap > *bp)
	{
		int tmp = *ap;
		*ap = *bp;
		*bp = tmp;
	}
}
void BubbleSort(int* arr, int len)
{
	assert(arr != NULL);
	int i = 0, j = 0;
	for (i = 0; i < len; ++i)
	{
		for (j = 0; j < len - 1-i; ++j)
		{
			Swap(&arr[j], &arr[j + 1]);
		}
	}
}
int Print(int *arr, int len)
{
	assert(arr != NULL);
	BubbleSort(arr, len);
	for (int i = 0; i < len; ++i)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}
int main()
{
	int arr[] = { 2,32,4,45,29,56,43,81,7 };
	int len = sizeof(arr) / sizeof(arr[0]);
	Print(arr, len);
	return 0;
}

2.简单选择排序

//简单选择排序
//每一轮找到待排序序列的最小值和待排序序列的第一个值进行交换
//时间复杂度O(n^2)
//空间复杂度O(1)
//稳定性:不稳定
void SelectSort(int* arr, int len)
{
	assert(arr != NULL);
	int minindex;//保存最小值的下标,而不是最小值本身
	for(int i = 0; i < len - 1; ++i)//控制层数
	{
		minindex = i;
		for (int j = i + 1; j < len; ++j)//找到这一轮待排序序列的最小值的下标
		{
			if (arr[j] < arr[minindex])
			{
				minindex = j;
			}
		}
		//第二层for循环执行结束,可以确定待排序序列中最小值的下标,保存在minindex里面
		if (minindex != i)
		{
			int tmp = arr[minindex];
			arr[minindex] = arr[i];
			arr[i] = tmp;
		}
	}
}
int Print(int *arr, int len)
{
	assert(arr != NULL);
	SelectSort(arr, len);
	for (int i = 0; i < len; ++i)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}
int main()
{
	int arr[] = { 2,1,3,9,8,7 };
	int len = sizeof(arr) / sizeof(arr[0]);
	Print(arr, len);
	return 0;
}

3.直接插入排序

//直接插入排序
//依次从待排序序列中取值,向已排序序列中放,保证再次完全有序,直到将待排序序列中所有值取完
///时间复杂度O(n^2)  
//空间复杂度O(1)  
//稳定性:稳定
void InsertSort(int* arr, int len)
{
	int tmp = 0;
	int j;//j代表的是已排序序列中需要和tmp比较的值
	for (int i = 1; i <= len - 1; ++i)
	//i代表的是未排序序列中此次需要插入的值(变稳定)
	{
		tmp = arr[i];
		for (j = i - 1; j >= 0; --j)
		//j代表的是已排序序列中需要和tmp比较的值
		{
			if (arr[j] > tmp)
			{
				arr[j + 1] = arr[j];
			}
			else
			{
				break;
			}
		}
		arr[j + 1] = tmp;
	}
}
int Print(int *arr, int len)
{
	assert(arr != NULL);
	InsertSort(arr, len);
	for (int i = 0; i < len; ++i)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}
int main()
{
	int arr[] = { 9,7,10,2,5,12,6,99,55,3,2,6,5,21 };
	int len = sizeof(arr) / sizeof(arr[0]);
	Print(arr, len);
	return 0;
}

4.希尔排序

//希尔排序
//shell排序,缩小增量排序,对于直接插入排序的优化,每一次让数据变得更加稳定,直到增量为1的时候,彻底完全有序
//时间复杂度O(n^1.3~1.5)
//空间复杂度O(1)
//稳定性:不稳定
void Shell(int* arr, int len, int gap)
{
	int tmp = 0;
	int j;//j代表的是已排序序列中需要和tmp比较的值
	for (int i = gap; i < len; ++i)
	{
		tmp = arr[i];
		for (j = i - gap; j >= 0; j -= gap)
		{
			if (arr[j] > tmp)
			{
				arr[j + gap] = arr[j];
			}
			else
			{
				break;
			}
		}
		//此时内层for退出,代表着tmp最终的位置已经找到
		arr[j + gap] = tmp;
	}
}
void ShellSort(int* arr, int len)
{
	int brr[] = { 13,11,7,5,3,1 };
	int len_brr = sizeof(brr) / sizeof(brr[0]);
	for (int i = 0; i < len_brr; ++i)
	{
		Shell(arr, len, brr[i]);
	}
}
int Print(int *arr, int len)
{
	assert(arr != NULL);
	ShellSort(arr, len);
	for (int i = 0; i < len; ++i)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}
int main()
{
	int arr[] = { 9,7,10,2,5,12,6,99,55,3,2,6,5,21 };
	int len = sizeof(arr) / sizeof(arr[0]);
	Print(arr, len);
	return 0;
}

5.堆排序

//堆排序,如果需要升序排序,则需要大顶堆,则将去数据调整为大顶堆,再将根节点和最后一个节点交换数据
//时间复杂度:O(nlogn)(以2为底的n)
//空间复杂度O(n)
//稳定性:不稳定
//调整一次大顶堆
void AdjustHeap(int arr[], int start, int end)
{
	int tmp = arr[start];
	int i = start;
	int j = 2 * i + 1;
	for (j; j <= end; j = 2 * i + 1)
	{
		if (j<end && arr[j + 1]>arr[j])
		{
			j++;
		}

		if (arr[j] > tmp)
		{
			arr[i] = arr[j];
			i = j;
		}
		else
		{
			break;
		}
	}
	arr[i] = tmp;

}

void HeapSort(int* arr, int len)
{
	//最后一个叶子节点len-1,最后一个非叶子节点的下标为((len-1)-1)/2
	//初始状态下,调整大顶堆需要,从最后一个非叶子节点开始,从后向前,从下向上调整

	for (int i = (len-1-1)/2;i>=0;--i)
	{
		AdjustHeap(arr, i, len - 1);
		//第三个参数,找不到规则,直接填最大下标位置即可(饱和时救援)
	}
	//此时for循环执行结束,初始状态下最繁琐的调整大顶堆搞定
	for (int i = 0; i < len - 1; ++i)//轮数
	{
		int tmp = arr[0];//交换的是根节点arr[0],而不是arr[i]
		arr[0] = arr[len - 1 - i];
		arr[len - 1-i] = tmp;
		AdjustHeap(arr, 0, (len-1-i)-1);
	}

}

6.基数排序


```c
//基数排序(桶排序)
//时间复杂度:O(dn)
//空间复杂度:O(dn)
//稳定性:稳定
int Get_Fignure_Max(int* arr, int len)
{
	int max = arr[0];
	for (int i = 1; i < len; ++i)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
	}
	int count = 0;
	while (max != 0)
	{
		count++;
		max /= 10;
	}
	return count;
}
int Get_Num(int n, int index)
{
	for (int i = 0; i < index; ++i)
	{
		n = n / 10;

	}
	return n % 10;

}
static void Radix(int* arr, int len,int index)
{
	int brr[10][20];//申请的0-9号桶
	int crr[10] = { 0 };//用crr[i]里的值代表对应的i号桶里面有多少个值
	for (int i = 0; i < len; ++i)
	{
		int tmp = Get_Num(arr[i],index);//tmp保存着值arr[i[应该放的桶号
		brr[tmp][crr[tmp]++] = arr[i];

	}
	int k = 0;
	for (int i = 0; i <= 9; ++i)//桶号
	{
		for (int j = 0; j < crr[i]; ++j)
		{
			arr[k++] = brr[i][j];
		}
	}

}
void Radix_Sort(int* arr, int len)
{
	int count = Get_Fignure_Max(arr, len);
	for (int i = 0; i < count; ++i)
	{
		Radix(arr, len,i);//i=0以个位排序一次,i=1以十位排序一次,
	}
}
int Print(int* arr, int len)
{
	assert(arr != NULL);
	Radix_Sort(arr, len);
	for (int i = 0; i < len; ++i)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}
int main()
{
	int arr[] = { 7,5,23,4,67,45,66,99,54 };
	int len = sizeof(arr) / sizeof(arr[0]);
	Print(arr, len);
	return 0;
}

标题7.堆排序

//堆排序,如果需要升序排序,则需要大顶堆,则将去数据调整为大顶堆,再将根节点和最后一个节点交换数据
//时间复杂度:O(nlogn)(以2为底的n)
//空间复杂度O(n)
//稳定性:不稳定
//调整一次大顶堆
void AdjustHeap(int arr[], int start, int end)
{
	int tmp = arr[start];
	int i = start;
	int j = 2 * i + 1;
	for (j; j <= end; j = 2 * i + 1)
	{
		if (j<end && arr[j + 1]>arr[j])
		{
			j++;
		}
		if (arr[j] > tmp)
		{
			arr[i] = arr[j];
			i = j;
		}
		else
		{
			break;
		}
	}
	arr[i] = tmp;
}

void HeapSort(int* arr, int len)
{
	//最后一个叶子节点len-1,最后一个非叶子节点的下标为((len-1)-1)/2
	//初始状态下,调整大顶堆需要,从最后一个非叶子节点开始,从后向前,从下向上调整
	for (int i = (len-1-1)/2;i>=0;--i)
	{
		AdjustHeap(arr, i, len - 1);
		//第三个参数,找不到规则,直接填最大下标位置即可(饱和时救援)
	}
	//此时for循环执行结束,初始状态下最繁琐的调整大顶堆搞定
	for (int i = 0; i < len - 1; ++i)//轮数
	{
		int tmp = arr[0];//交换的是根节点arr[0],而不是arr[i]
		arr[0] = arr[len - 1 - i];
		arr[len - 1-i] = tmp;
		AdjustHeap(arr, 0, (len-1-i)-1);
	}
}

8.快速排序

//快速排序:重复划分,找基准值,将小于基准值的值全部放在左边,大于基准值的值全部放在右边:从右向左找比arr[left]更小的值,再从左向右找比arr[left]更大的值放过去,重复操作,直到left>=rigth退出
//综合情况来看,是最快的,数组越乱越有序,是每一次将基准值放到合适位置上
// 时间复杂度为O(nlogn)
// 空闲复杂度O(logn)
// 稳定性:不稳定
//
int Partition(int* arr, int left, int right)
{
	int tmp = arr[left];
	while (left < right)
	{
		while (left<right && arr[right]>tmp)
		{
			right--;
		}

if (left == right)
		{
			break;
		}
		arr[left] = arr[right];
		while (left < right && arr[left] <= tmp)
		{
			left++;
		}
		if (left == right)
		{
			break;
		}
		arr[right] = arr[left];
	}
	arr[left] = tmp;
	return left;
}
void Quick(int arr[], int left, int right)
{
	if (left < right)
	{
		int index = Partition(arr, left, right);
		if (left < index - 1)//保证基准值左边至少有两个值
		{
			Quick(arr, left, index - 1);
		}
		if (index + 1 < right)
		{
			Quick(arr, index + 1, right);
		}
	}
}
void QuickSort(int* arr, int len)
{
	Quick(arr, 0, len - 1);
}
int Print(int* arr, int len)
{
	assert(arr != NULL);
	QuickSort(arr, len);
	for (int i = 0; i < len; ++i)
	{
		printf("%d  ", arr[i]);
	}
	return 0;
}
int main()
{
	int arr[] = { 9,7,10,2,5,6,12,99,55,3,2,6,5,21 };
	int n = sizeof(arr) / sizeof(arr[0]);
	Print(arr, n);
	return 0;
}

均在vs上编译通过

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值