赞
踩
打卡第九天
快速排序==》 C++异常处理没有搞定(lll¬ω¬)
排序数组本身就是数组旋转的一个特例。
在对数组进行排序或查找时,要注意数组中有相同数字的特例,比如下面的旋转数组的时候
查找:顺序查找、二分查找、哈希表查找、二叉排序查找
排序:插入排序、冒泡排序、归并排序、快速排序
实现快速排序算法的关键在于先在数组中选择一个数字,接下来把数组中的数字分为两部分,比选择的数字小的移到数组的左边,比选择的数字大的移到数组的右边
突然就卡在快速排序了,自己都有点懵了,因为之前用python实现的时候是使用了一个新的数组,这一次要在原来的数组里面不使用新的空间进行划分,直接看图吧
选择的用于进行标志的是每个数组的最后一个数data[end]=5
。第一轮for
循环,small=-1,因为4<5,所以这一轮的small可以加1,small表示的是最新的比flag小的数的位置,又因为small已经指向当前的位置了,所以就不用进行交换了;第二轮同理;第三轮的时候,由于8>5,所以small不用改变,最新的small还是上一轮的3;第四轮的时候,1<5,所以这一轮的small应该指向的是1,所以small+1,之后还要把small现在指向的位置的数的值和1进行交换;后面以此类推……
//快速排序算法
//交换两个数的值
void Swap(int *x, int *y)
{
int p;
p = *x;
*x = *y;
*y = p;
}
int Partition(int data[], int length, int start, int end)
{
if (data == nullptr || start < 0 || end >= length || length <= 0)
throw new std::exception("不合格的输入!");
int small = start - 1; //指向最小的数
int flag = data[end]; //用于进行划分的标志
for (int i = 0; i < length; i++)
{
if (data[i] < flag) {
small++;
Swap(&data[i], &data[small]);
}
}
//最后还要将最后一个数放到前面,和其他小的数放到一起
++small;
Swap(&flag, &data[small]);
return small; //返回的是最后一个较小的数的位置,即大数与小数划分处
}
void QuickSort(int data[], int length, int start, int end)
{
if (start == end)
return; //只有一个数不需要排序
int index = Partition(data, length, start, end);
if (index > start)//如果存在小的序列
QuickSort(data, length, start, index - 1);
if (index < end)//如果存在大数的序列
QuickSort(data, length, index + 1, end);
}
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
不是很懂c++的异常处理问题,这个代码存在问题,关于异常处理的,所以没有用测试用例运行。。。之后要是弄懂了会回来看的
如下图,奇怪的是我这不是对这个异常进行处理了吗?恳请各位路过的朋友能解个疑[/抱拳]【问题说明:这是在函数里面try-catch
的,之后有试过在调用该函数的地方try-catch
也不行】
为员工年龄进行排序,要求时间复杂度在O(n)内,允许使用常数范围内辅助空间,不得大于O(n)
使用统计的方法,先对员工的年龄进行统计,用一个数组存储某一年龄出现的次数times,之后在返回的ages数组中填入times次该年龄出现的次数。
//给员工年龄进行排序
void SortAges(int ages[], int length)
{
if (ages == nullptr || length == 0)
return;
const int oldestAge = 99;
int timeOfAges[100];
//对传进来的年龄进行统计
for (int i = 0; i < length; i++) {
int age = ages[i];
if (age < 0 || age>99)
throw new std::exception("年龄超出统计范围了!");
++timeOfAges[age];
}
int index = 0;
for (int i = 0; i <= oldestAge; i++)
{
for (int j = 0; j < timeOfAges[i]; j++)
{
ages[index] = i;
index++;
}
}
}
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.
1、旋转之后的数组实际上可以划分为两个排序的子数组,而且前面子数组的元素都大于或等于后面子数组的元素。最小的元素刚好是两个子数组的分界线。这道题可以说是部分排序的,在一开始就有提到部分排序的数组的查找可以使用二分查找法
2、第一个元素大于或等于最后一个元素。找到中间的元素,如果该中间元素位于前面的递增子数组,那么它应该大于或等于第一个指针指向的元素。此时数组中最小的元素应该在该中间元素的后面。可以把第一个指针指向该中间元素,缩小查找范围。移动后第一个指针仍然指向第一个子数组的元素。
3、第一个指针总是指向第一个子数组的元素,第二个指针总是指向第二个子数组的元素。最终第一个指针会指向第一个子数组的最后一个元素,第二个指针会指向第二个子数组的第一个元素。此时,第二个指针指向的正好是最小的元素,这就是循环结束的条件
int Min(int array[], int length)
{
if (array == nullptr || length <= 0)
throw new exception("不合法输入!");
int index1 = 0;
int index2 = length - 1;
//为什么是初始化为index1?而不是index2?
//因为有可能旋转数组旋转的是排序数组的前面0个元素,这样就相当于没有旋转了
//直接输出第一个元素就好了,因为while循环都不用进去了
int indexMiddle = index1;
while (array[index1] >= array[index2]) {
//循环退出条件,找到最小值的位置了
if (index2 - index1 == 1) {
indexMiddle = index2;
break;
}
indexMiddle = (index1 + index2) / 2;
//如果middle在前面的子数组中
if (array[indexMiddle] >= array[index1])
index1 = indexMiddle;
//如果middle在后面的子数组中,往前移后面的指针,缩小查找范围
else if (array[indexMiddle] <= array[index2])
index2 = indexMiddle;
}
return array[indexMiddle];
}
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
一种特殊的情况:数组{1,0,1,1,1}和数组{1,1,1,0,1}都是排序数组{0,1,1,1,1}的旋转数组。在这两数组中,第一个数字、中间的数字、最后一个数字都是1,无法判断中间的1是前面的子数组的还是后面的子数组的。很混乱,比如前面的例子,中间的1是位于后面的子数组;第二个例子,中间的1是位于后面的子数组。这样就不得不采用顺序查找的方法了。
//顺序查找
int MinInOrder(int array[], int index1, int index2)
{
int result = array[index1];
for (int i = 0; i <= index2; i++)
{
if (array[i] < result)
result = array[i];
}
return result;
}
int MinChoose(int array[], int length)
{
if (array == nullptr || length <= 0)
throw new exception("不合法输入!");
int index1 = 0;
int index2 = length - 1;
//为什么是初始化为index1?而不是index2?
//因为有可能旋转数组旋转的是排序数组的前面0个元素,这样就相当于没有旋转了
//直接输出第一个元素就好了,因为while循环都不用进去了
int indexMiddle = index1;
while (array[index1] >= array[index2]) {
//循环退出条件,找到最小值的位置了
if (index2 - index1 == 1) {
indexMiddle = index2;
break;
}
indexMiddle = (index1 + index2) / 2;
//修改的地方:
//如果下标为index1,indexMiddle,index2的三个元素的值都相等,只能用顺序查找
if (array[index1] == array[index2] && array[index2] == array[indexMiddle])
return MinInOrder(array, index1, index2);
//如果middle在前面的子数组中
if (array[indexMiddle] >= array[index1])
index1 = indexMiddle;
//如果middle在后面的子数组中,往前移后面的指针,缩小查找范围
else if (array[indexMiddle] <= array[index2])
index2 = indexMiddle;
}
return array[indexMiddle];
}
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。