Day3:排序算法(1/2)

目录

一、基本的排序算法:

冒泡√:

        ①未优化版本

        ②优化后:

选择√

​插入√     

shell√

基数排序√        

                步骤:

桶(箱)√         

二、 运算时间测量:

法一:

 法二:的clock()方法和常数CLOCKS_PER_SEC​编辑

一、基本的排序算法:

冒泡√:

        冒泡思路:
            基于比较  
            循环比较相邻两个元素 如果不符合要求 就交换   最后那个已然符合要求
            每次冒出来一个
            所以循环  n-1 次 可以达成目标

            n^2-n

            O(n^2)

        ①未优化版本

void buble_sort(int* &arr, int len)
{
	for (int i = 0; i < len - 1; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			if (arr[j] > arr[j+1])
				swap(arr[j], arr[j + 1]);
		}
	}
}

             

        ②优化后:

                思路:就是一次遍历之后,发现一次都没有去交换,表明已经是有序的了。

void buble_sort(int* &arr, int len)
{
	int flag = -1;
	for (int i = 0; i < len - 1; i++)
	{
		flag = 0;
		for (int j = 0; j < len - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				swap(arr[j], arr[j + 1]);
				flag = 1;//说明至少交换过1次,有必要再继续进行下去
			}
		}
		if (flag == 0)
			break;
		travel(arr, 10);
	}
}

少运行3次~~~

        个人有关参数的心得:最外层for->就是总共需要的次数,归位n-1个即可,也就是最外层n-1次,内层的参数下界从0不断的把本次需要的最大升到本层的最高处(j-i-1),关于减去i+1是因为当i=1时,已经有一个归位了,只需要循环剩下的部分即可。

选择√

                选择:
                    每次选择最小的,放到应该放的位置
                    选 n-1 次完事

void select_sort(int*& arr, int len)
{
	for (int i = 0; i < len -1; i++)//只需要比较len-1即可。
	{
		int min_index = i;/*挑出最小的放在最前面,默认在i之后的数组里,下表为i的位置为min*/
		for (int j = i;j < len; j++)//此处必须是len,剩下的部分都要进行比较
		{
			if (arr[min_index] > arr[j])
				min_index = j;
		}
		if (min_index != i)
			swap(arr[min_index], arr[i]);
		travel(arr,10);
	}
}


插入√       

             插入思路:
                    把待排数组的第一个元素看成是一个有序数组
                    然后一个个的把其他元素插入到这个有序数组中去

            如何插入:
                临时存储待插入数据
                从待插数据的前一个位置开始 从后往前找插入位置
                没找到插入位置前  往后覆盖
                找到插入位置 结束循环
                然后待插数据覆盖当前位置

void insert_sort(int*& arr, int len)
{
	for (int i =0 ; i < len-1; i++)
	{
		int j;
		int temp=arr[i+1];//暂存带插入的元素
		arr[i + 1] = arr[i];//覆盖
		for ( j = i+1; j >0&&arr[j-1]>temp; j--)
		{//寻找适合插入的位置(注:less<int>)
			arr[j] = arr[j - 1];
		}
		arr[j] = temp;
		travel(arr, 10);
	}
}

                 注意:参数细节->尤其是arr[j-1]>temp和arr[j]=temp这两个地方。->画图

shell√

        shell思路:
             先分组 在组内做插入排序
              一般是先分成   len/2 组
               然后分成      len/2/2 组
                    。。。。   
                                           2组
                    最后                1组
                组的数量 我们称之为 步长(step)
                    step: len/2  len/4 ... 2 1   

        希尔排序时间复杂度是 O(n^(1.3-2)),空间复杂度为常数阶 O(1)。        

void shell_sort(int*& arr, int len)
{
	int step = len / 2;
	while (step)
	{
		for (int i = step; i < len; i++)//恰巧模拟了插入排序的依次向其中插一个一个元素的情况
		{//循环插入arr[i]
			int temp = arr[i];
			arr[i] = arr[i - step];
			int j ;
			for (j = i; j >= step&&arr[j-1]>temp; j-=step)
			{
				arr[j] = arr[j - step];
			}
			arr[j] = temp;
		}
		travel(arr, 10);
		step /= 2;
	}
}

如何将图中的思想转化为代码->写好希尔排序的参数很重要!!(隔一个step依次插入)

基数排序√        

                数组下标天然有序
                    限制超级多:
                        1. 只能是正整数    (如果有负数,转成正数先)
                        2. 不能重复
                        3. 需要特别注意空间

                    O(n)

                步骤:

                        1 .创建一个临时数组

                        2 .给临时数组全部赋值为一个不会出现的数

                        3 .根据数组下标来把a数组中数据放到临时数组中去

                        4 .依序把pTemp中数据放会原数组

                        5 .释放内存

void redix_sort(int*& p, int len, int max)
{
	int* pArr = new int[max + 1];//开辟内存
	int k=0;
	for (int i = 0; i < max + 1; i++)
	{
		pArr[i] = -1;//赋值一个不会出现的数字
	}
	for (int i = 0; i < len; i++)
	{
		pArr[p[i]] = p[i];//根据索引自动进行
	}
	for (int i = 0; i < max + 1; i++)
	{
		if (pArr[i] != -1)
			p[k++] = pArr[i];
	}
	delete[]pArr;
}

桶(箱)√         

                桶(箱)排序:    
                    先把数据分成若干个桶,然后桶内用其他排序方式排序,排完之后再合并
                    非常稳定

                    空间换时间

                注:思路图见->桶排序 - 简书 (jianshu.com)

                        依次让个位有序、让十位有序、让百位有序···

void bucket_sort(int*& p, int len)
{
	int** Arr = new int* [10];//0-9  1.先把桶准备好
	for (int i = 0; i < 10; i++)
	{
		Arr[i] = new int[len];
	}
	int wei = 1;
	while(wei<AREA)
	{
		for (int i = 0; i < 10; i++)
		{
			for (int j = 0; j < len; j++)
			{
				Arr[i][j] = -1;//初始化桶
			}
		}
		//2.在0-9的桶去对应,第一次的遍历为个位顺序,第二次为十位顺序
		for (int i = 0; i < 10; i++)//每个桶进行分类
		{
			for (int j = 0; j < len; j++)
			{
				if (p[j] / wei % 10 == i)
					Arr[i][j] = p[j];
			}
		}
		travel(p, len);
		//3. 放完之后,依次取出(第一次取出就已经能保证是个位有序的了。。。
		int k = 0;
		for (int i = 0; i < 10; i++)
		{
			for (int j = 0; j < len; j++)
			{
				if (Arr[i][j] != -1)
					p[k++] = Arr[i][j];
			}
		}
		wei *= 10;
	}
}

(其余下次)

归并、分组 快排、堆排序

20227.17补:计数排序(解决重复元素问题) 

void CountSort(int array[], int arrayNum) 
{
	//准备一个容器,
	int* countArray = (int*)calloc(sizeof(int), 100);	//calloc自动初始化位0
	assert(countArray);
	for (int i = 0; i < arrayNum; i++) 
	{
		countArray[array[i]]++;     //把数据当做数组下标,去统计元素出现次数
	}
	int* sortArray = (int*)malloc(sizeof(int) * arrayNum);
	assert(sortArray);
	int k = 0;
	for (int i = 0; i < 100; i++) 
	{
		//printf("%d\n", countArray[i]);
		while (k<arrayNum &&countArray[i] != 0) 
		{
			sortArray[k++] = i;
			countArray[i]--;
		}
	}
	memcpy(array, sortArray, arrayNum * sizeof(int));		//还原到原数组
	free(countArray);
	free(sortArray);
}

桶、基数排序的其他写法:

//8.基数排序(桶排序的升级版)
//拆分数字的每一位: 辅助函数
int getPosNum(int num, int pos) 
{
	int temp = 1;						//123
	for (int i = 0; i < pos - 1; i++)	//123/100
	{
		temp *= 10;						//123/10 12
	}
	return (num / temp) % 10;			//123/10=12%10=2
}
void BucketSort(int array[], int arrayNum, int pos) 
{
	int* bucketArray[10] = { NULL };
	for (int i = 0; i < 10; i++) 
	{
		bucketArray[i] = (int*)calloc(sizeof(int), arrayNum);
		assert(bucketArray[i]);
	}
	//装桶
	for (int i = 0; i < arrayNum; i++) 
	{
		int index = getPosNum(array[i], pos);
		for (int j = 0; j < arrayNum; j++) 
		{
			if (bucketArray[index][j] == 0) 
			{
				bucketArray[index][j] = array[i];
				break;
			}
		}
	}
	//出桶
	int k = 0;
	for (int i = 0; i < 10; i++) 
	{
		for (int j = 0; j < arrayNum; j++) 
		{
			if (bucketArray[i][j] != 0) 
			{
				array[k] = bucketArray[i][j];
				bucketArray[i][j] = 0;
				k++;
			}
		}
	}
}
//找最大值
int getMaxNum(int array[], int arrayNum)
{
	int max = array[0];
	for (int i = 1; i < arrayNum; i++) 
	{
		if (max < array[i])
			max = array[i];
	}
	return max;
}
//最大值有多位
int getMaxNumCount(int num) 
{
	int count = 1;
	while (num / 10) 
	{
		count++;
		num /= 10;
	}
	return count;
}
//基数排序
void RadixSort(int array[], int arrayNum) 
{
	int maxNum = getMaxNum(array, arrayNum);
	int loop = getMaxNumCount(maxNum);
	for (int i = 1; i <= loop; i++) 
	{
		BucketSort(array, arrayNum, i);
	}
}

二、 运算时间测量:

法一:

头文件:#include<windows.h>

函数:GetCurrentTime()返回ms

 法二:<time.h>的clock()方法和常数CLOCKS_PER_SEC(推荐)

核心:clock()&CLK_TCK&double强制转化

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Ocean__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值