我正在做我的作业,并且有一个问题要求我们对结构数组进行排序
结构citizen
由int id
和boolean gender
组成,其中id
是在1到100之间随机生成的,
gender
取决于id
是奇数还是偶数,奇数= true
(男性)甚至= false
(女性)
例如a = {33, true}
这个问题要求我按性别对citizen[]
数组进行排序,看起来很简单,但它有以下要求:
以线性时间O(N)
运行没有新阵列
只能使用恒定的额外空间
我正在考虑使用计数排序,但是如果没有新数组,似乎有点难以实现,是否有任何建议?
答案 0 :(得分:8)
由于这是一个家庭作业问题,我不打算提供代码。以下内容足以让您入门。
按性别“排序”这里实际上意味着分成两组。通用排序不能比O(n * log(n))更好,但是可以在具有恒定空间的O(n)中进行分区。
考虑同时从两端迭代(while循环,两个索引指针初始化为first和last元素),寻找“错误”部分中的元素。当你在每一端找到一个这样的元素时,交换它们。请注意,指针只在跳过已经在右边部分的元素时才会相互独立移动,当然也可以在交换后立即移动,这是“已经在右边部分中的元素”的子例。
当索引指针在中间某处相遇时退出。
这不是一般目的。如果密钥数量未知,则无法执行此操作。
答案 1 :(得分:3)
由于您只有两个要排序的值,您可以使用一种交换计数排序(我无法找到任何相关的论文)。 在那种情况下有优化的空间,但这将是你的工作。
根据您的问题,这是一个特殊排序的伪代码:
integer maleIndex = 0 // Current position of males in the array
for i=0 until array.size do
if array.at(i) is a male then
// after a while, all female will end up at the end
// while all male will end up at the beginning
swap(array.at(maleIndex), array.at(i))
maleIndex = maleIndex + 1
end
end
答案 2 :(得分:2)
一种方法类似于QuickSort中的分区阶段,或类似于中值/等级查找算法QuickSelect。
我将描述算法的大纲,但不提供任何代码。希望翻译很容易。
您基本上想要重新组织数组,以便一个性别位于开头,另一个位于数组的末尾。您将阵列分为三个部分:
在算法开始时,i设置为0,因此第一个区域为空,j设置为n-1,因此第二个区域为空。基本上整个阵列都处于未知状态。
然后,以特定方式迭代数组。在每一步,你看看公民[i] .gender。如果它是第一个性别,你可以不管它并增加i。如果是第二性别,则将A [i]与A [j]交换并递减j。当我等于j时你停止。
为什么这是正确的?好吧,在每一步我们都可以看到保持三个区域的约束,假设它保持开始(它确实),并且第一个或第二个区域增加。最后,第二个区域没有元素,因此我们只在开始时留下第一个性别,在结束时留下第二个性别。
为什么它是线性的?好吧,在每一步中,我们都会对数组中的一个元素做出一个恒定时间的决定。有这样的元素,所以时间是线性的。或者,迭代测试可以表示为while (j - i > 0)
,表达式j - i
从n-1
开始,每次迭代都会减少1
。