【八大排序】

稳定性: 相同值的位置在排序后发生变化 那就说明此排序算法的稳定性差。

一 、直接插入排序

直接插入排序的时间复杂度是O(n^2)
空间复杂度是O(1)。

直接插入排序:每次从带排排序序列中取出一个值,放到已经排序好的序列中,然后依次保持有序

二、希尔排序

希尔排序:增效增量排序
原始数据:12 9 18 20 5 10 28 32 1 4 80 91 2 88 66
最小增量数组
(5, 3,1)注意最后一个增量必须为1。
从12向后数5**(增量为5)**,将10和12一个组。
第一组为12,10,80。
第二组为 9,28,91。
第三组为18,32,2。
第四组为20,1,88。
第五组为5,4,66。

在这里插入图片描述
每组依次排序,得到这个结果:
在这里插入图片描述
按增量3再进行排序:
在这里插入图片描述
最后按增量1进行排序:
在这里插入图片描述
此时排序完成。
直接插入越有序,排序越快,这也是希尔排序对插入排序优化的原因。
节省时间大概计算
for循环的处理顺序:
在这里插入图片描述
希尔排序的时间空间复杂度:
时间复杂度为O(N^1.3~1.7)
空间复杂度是O(1)
因为存在跳跃交换所以稳定性较低。

三、归并排序


在这里插入图片描述

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
void Merge_Sort(int* arr, int len, int gap)
{
	int low1 = 0;
	int hign1 = low1 + gap - 1;
	int low2 = hign1 + 1;
	int hign2 = low2+gap-1 <=len-1 ? low2 + gap - 1 : len - 1;
	int k = 0;
	int* brr = (int*)malloc(sizeof(int) * 30);
	while (low2 < len)
	{
		while (low1 <= hign1 && low2 <= hign2)
		{
			if (arr[low1] > arr[low2])
			{
				brr[k++] = arr[low2++];
			}
			if (arr[low1] <= arr[low2])
			{
				brr[k++] = arr[low1++];
			}
		}
			//for(int i=0;i<gap;++i)
			while (low1 <= hign1)
			{
				brr[k++] = arr[low1++];
			}
			while (low2 <= hign2)
			{
				brr[k++] = arr[low2++];
			}
			low1 = hign2 + 1;
			hign1 = low1 + gap - 1;
			low2 = hign1 + 1;//用low2确定右侧是否有数据的状态
			hign2 = low2 + gap - 1 < len ? low2 + gap - 1 : len - 1;
		
	}
		while (low1<len)
		{
			brr[k++] = arr[low1++];
		}
		for (int i = 0; i < len; ++i)
		{
			arr[i] = brr[i];
		}
		free(brr);
}
void Show(int* arr, int len)
{
	for (int i = 0; i < len; i++)
	{
		printf("%4d", arr[i]);
	}
}
void Merge(int* arr, int len)
{
	int gap = 0;
	for (int i = 1; i < len; i *= 2)
	{
		gap = i;
		Merge_Sort(arr,len,gap);
	}
}
int main()
{
	int arr[] = { 8423,34,45,56,67,78,879,345,45,12,90,84,8,12 };
	int len = sizeof(arr) / sizeof(arr[0]);
	Merge(arr, len);
	Show(arr, len);
	return 0;
}

归并排序的时间空间复杂度:

时间复杂度为:O(nlogn)
空间复杂度为:O(n)
归并排序不存在跳跃交换,遂稳定。


四、快排

因为存在跳跃交换,所以属于不稳定的排序。

时间复杂度为平均nlogn,空间复杂度为logn,理由是如下函数 在递归实现时,函数没结束时,
一直在申请栈空间(变量par).

`void Quick(int* arr,int left,int right)
{
int par=Quick_Sort(arr, left, right);
if (par > left + 1)
{
Quick(arr, left, par - 1);

}
if (par <right-1)
{
Quick(arr, par + 1,right);
}
}`

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
int Quick_Sort(int* arr, int left, int right)
{
	int tmp = arr[left];
	while(left<right)//确保至少有两个值  才进入排序循环*********
	{
	    
		while (left<right && arr[right]>tmp)
		{
			right--;
		}
		if (right == left)
		{
			arr[right] = tmp;
			return right;
		}
		
			arr[left] = arr[right];
		
		while (left < right && arr[left] <=tmp)// <=tmp 没加等号
		{
			left++;
		}
		if (left == right)
		{
			arr[left] = tmp;//这两行代码换成BREAK也可以。
			return left;
		}
	    arr[right] = arr[left];
	}
	arr[left] = tmp;//因为大循环的意思没领悟 所以这儿就没想清楚
	return left;
}
void Quick(int* arr,int left,int right)
{
	int par=Quick_Sort(arr, left, right);
	if (par > left + 1)
	{
		Quick(arr, left, par - 1);

	}
	if (par <right-1)
	{
		Quick(arr, par + 1,right);
	}
}
void Show(int* arr, int len)
{
	for (int i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr[] = { 12,34,45,56,23,34,56,2,234,45,23,34,45,67,23 };
	int len = sizeof(arr) / sizeof(arr[0]);
	Quick(arr,0,len-1);
	Show(arr, len);
	return 0;
}

不用递归的代码实现


void Quick_Stack(int* arr, int left, int right)
{
	std::stack<int> st;
	int par = Quick_Sort(arr, left, right);
	
	if (par > left + 1)
	{
		//=Quick_Sort(arr, left, par - 1);
		st.push(par - 1);
		st.push(left);

	}
	if (par < right - 1)
	{
		//Quick_Sort(arr, par + 1, right);
		st.push(right);
		st.push(par + 1);
	}

	while (!st.empty())
	{
		left=st.top();
		st.pop();
		right = st.top();
		st.pop();

		par=Quick_Sort(arr,left,right);
		if (par > left + 1)
		{
			//=Quick_Sort(arr, left, par - 1);
			st.push(par - 1);
			st.push(left);

		}
		if (par < right - 1)
		{
			//Quick_Sort(arr, par + 1, right);
			st.push(right);
			st.push(par + 1);
		}
	}
}

五、选择排序

void Select_Sort(int* arr, int len)
{
	int left = 0;
	int min = 0;
	int tmp = 0;
	while (left < len - 1)
	{
		min = left;

		for (int i = left; i < len; i++)
		{

			if (arr[i] < arr[min])
			{
				//tmp = min;
				min = i;
			}
		}
		tmp = arr[left];
		arr[left] = arr[min];
		arr[min] = tmp;
		left++;

	}
}
		void Show(int* arr, int len)
		{
			for (int i = 0; i < len; i++)
			{
				printf("%d ", arr[i]);
			}
			printf("\n");
		}
int main()
{
	int arr[] = { 12,2,34,4,32,44,3,23,34,89 };
	int len = sizeof(arr) / sizeof(arr[0]);
	Select_Sort(arr, len);
	Show(arr, len);
	
	return 0;
}


选择排序的时间空间复杂度:
时间复杂度:O(n^2)
空间复杂度:O(1)
不稳定

六、基数排序

时间复杂度为O(dn)
空间复杂度为O(dn)
稳定性:稳定

int Count = 0;
void Show(int* arr, int len)
{
	for (int i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
int Get_bit(int* arr, int len)
{
	int i = 0;
	int max = 0;
	while (i < len)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
		i++;
	}
	
	while (max / 10 != 0)
	{
		max /= 10;
		Count++;
	}
	Count++;
	//for (int j = 0; j < Count; ++j)
	//{
	//	Classify(arr, len);
	//}
	return Count;
}
		
int Gey_remainder(int n, int fin)
{
	for (int i = 0; i < fin; ++i)
	{
		n /= 10;
	}
	return n % 10;
}
void Classify(int* arr, int len,int fin)
{
	std::queue<int> bucket[10];
	for (int i = 0; i < len; i++)  
	{
	  int index = Get_remainder(arr[i], fin);
		bucket[index].push(arr[i]);
	}
	int k = 0;
	for (int i = 0; i <= 9; i++)
	{
		while (!bucket[i].empty()) //不能取一个就拉倒了,都得取走。
		{
			arr[k++] = bucket[i].front(); //1.一个筒子值都取完再取下一个筒子。
			bucket[i].pop();
		}
	}
}
void redix_sort(int* arr, int len)
{
	int fin=Get_bit(arr, len);
	for (int i = 0; i < fin; ++i)
	{
		Classify(arr, len,i); //i控制个位十位百位取余,控制趟数。

	}
	

}
int main()
{
	int arr[] = { 12,2,34657,23456,23,5,80,232,56,89,3,23,34,89 };
	int len = sizeof(arr) / sizeof(arr[0]);
	redix_sort(arr, len);
	Show(arr, len);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值