- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
美好的一天 SO 社区,
我是一名 CS 学生,目前正在进行结合 MergeSort 和 InsertionSort 的实验。据了解,对于某个阈值 S,InsertionSort 将比 MergeSort 具有更快的执行时间。因此,通过合并两种排序算法,将优化总运行时间。
但是,在多次运行实验后,使用1000的样本大小,不同大小的S,每次实验的结果都没有给出确定的答案。这是获得的更好结果的图片(请注意,有一半的时间结果不是确定的):
现在,尝试样本大小为 3500 的相同算法代码:
最后,以500,000的样本量尝试相同的算法代码(注意y轴以毫秒为单位:
尽管从逻辑上讲,当 S<=10 时,Hybrid MergeSort 会更快,因为 InsertionSort 没有递归开销时间。然而,我的迷你实验的结果却不是这样。
目前,这些是教给我的时间复杂度:
合并排序:O(n log n)
插入排序:
最后,我找到了在线资源:https://cs.stackexchange.com/questions/68179/combining-merge-sort-and-insertion-sort声明:
混合合并插入排序:
我想问一下 CS 社区中是否有结果显示明确的证据表明混合合并排序算法在低于特定阈值 S 时将比普通合并排序算法工作得更好,如果是这样,为什么 ?
非常感谢 SO 社区,这可能是一个微不足道的问题,但它确实会澄清我目前关于时间复杂度和其他问题的许多问题:)
注意:我使用 Java 编写算法代码,运行时可能会受到 Java 在内存中存储数据的方式的影响。
Java 代码:
public static int mergeSort2(int n, int m, int s, int[] arr){
int mid = (n+m)/2, right=0, left=0;
if(m-n<=s)
return insertSort(arr,n,m);
else
{
right = mergeSort2(n, mid,s, arr);
left = mergeSort2(mid+1,m,s, arr);
return right+left+merge(n,m,s,arr);
}
}
public static int insertSort(int[] arr, int n, int m){
int temp, comp=0;
for(int i=n+1; i<= m; i++){
for(int j=i; j>n; j--){
comp++;
comparison2++;
if(arr[j]<arr[j-1]){
temp = arr[j];
arr[j] = arr[j-1];
arr[j-1] = temp;
}
else
break;
}
}
return comp;
}
public static void shiftArr(int start, int m, int[] arr){
for(int i=m; i>start; i--)
arr[i] = arr[i-1];
}
public static int merge(int n, int m, int s, int[] arr){
int comp=0;
if(m-n<=s)
return 0;
int mid = (n+m)/2;
int temp, i=n, j=mid+1;
while(i<=mid && j<=m)
{
comp++;
comparison2++;
if(arr[i] >= arr[j])
{
if(i==mid++&&j==m && (arr[i]==arr[j]))
break;
temp = arr[j];
shiftArr(i,j++,arr);
arr[i] = temp;
if(arr[i+1]==arr[i]){
i++;
}
}
i++;
}
return comp;
}
最佳答案
示例代码不是传统的合并排序。合并函数移动数组,而不是合并原始数组和临时工作数组之间的运行并返回。
我测试了自上而下和自下而上的合并排序,两者都需要大约 42 毫秒 == 0.042 秒来对 500,000 个 32 位整数进行排序,而图中的明显结果在大约 42 秒而不是 42 毫秒时慢了 1000 倍。我还测试了 10,000,000 个整数,排序需要 1 秒多一点。
过去,使用 C++,我将自底向上归并排序与混合自底向上归并/插入排序进行比较,对于 1600 万 (2^24 == 16,777,216) 个 32 位整数,混合排序大约为 8%使用 S == 16 更快。S == 64 比 S == 16 稍慢。Visual Studio std::stable_sort 是自下而上合并排序的变体(临时数组是原始数组大小的 1/2)并且插入排序,并使用 S == 32。
对于小型数组,插入排序比归并排序更快,归并排序结合了缓存局部性和使用插入排序对小型数组进行排序所需的指令更少。对于伪随机数据和 S == 16 到 64,插入排序大约是归并排序的两倍。
随着数组大小的增加,相对增益会减小。考虑到对自下而上归并排序的影响,S == 16,只有 4 个归并过程被优化。在我有 2^24 == 16,777,216 个元素的测试用例中,这是 4/24 = 1/6 ~= 16.7% 的遍数,导致大约 8% 的改进(因此插入排序大约是合并的两倍对这 4 次传球进行排序)。仅合并排序的总时间约为 1.52 秒,混合排序的总时间约为 1.40 秒,比仅需 1.52 秒的过程增加了 0.12 秒。对于自上而下的合并排序,S == 16,将优化递归的 4 个最深层次。
更新 - 时间复杂度为 O(n log(n)) 的混合就地合并排序/插入排序的示例 java 代码。 (注意 - 由于递归,辅助存储仍然在堆栈上消耗。)就地部分是在合并步骤期间通过交换合并区域中的数据与合并自区域中的数据来完成的。这不是一个稳定的排序(由于合并步骤中的交换,不保留相等元素的顺序)。排序 500,000 个整数大约需要 1/8 秒,所以我将其增加到 1600 万 (2^24 == 16777216) 个整数,这需要 4 秒多一点。如果没有插入排序,排序大约需要 4.524 秒,而使用 S == 64 的插入排序,排序大约需要 4.150 秒,大约有 8.8% 的增益。使用基本相同的 C 代码,改进幅度较小:从 2.88 秒减少到 2.75 秒,大约增加 4.5%。
package msortih;
import java.util.Random;
public class msortih {
static final int S = 64; // use insertion sort if size <= S
static void swap(int[] a, int i, int j) {
int tmp = a[i]; a[i] = a[j]; a[j] = tmp;
}
// a[w:] = merged a[i:m]+a[j:n]
// a[i:] = reordered a[w:]
static void wmerge(int[] a, int i, int m, int j, int n, int w) {
while (i < m && j < n)
swap(a, w++, a[i] < a[j] ? i++ : j++);
while (i < m)
swap(a, w++, i++);
while (j < n)
swap(a, w++, j++);
}
// a[w:] = sorted a[b:e]
// a[b:e] = reordered a[w:]
static void wsort(int[] a, int b, int e, int w) {
int m;
if (e - b > 1) {
m = b + (e - b) / 2;
imsort(a, b, m);
imsort(a, m, e);
wmerge(a, b, m, m, e, w);
}
else
while (b < e)
swap(a, b++, w++);
}
// inplace merge sort a[b:e]
static void imsort(int[] a, int b, int e) {
int m, n, w, x;
int t;
// if <= S elements, use insertion sort
if (e - b <= S){
for(n = b+1; n < e; n++){
t = a[n];
m = n-1;
while(m >= b && a[m] > t){
a[m+1] = a[m];
m--;}
a[m+1] = t;}
return;
}
if (e - b > 1) {
// split a[b:e]
m = b + (e - b) / 2;
w = b + e - m;
// wsort -> a[w:e] = sorted a[b:m]
// a[b:m] = reordered a[w:e]
wsort(a, b, m, w);
while (w - b > 2) {
// split a[b:w], w = new mid point
n = w;
w = b + (n - b + 1) / 2;
x = b + n - w;
// wsort -> a[b:x] = sorted a[w:n]
// a[w:n] = reordered a[b:x]
wsort(a, w, n, b);
// wmerge -> a[w:e] = merged a[b:x]+a[n:e]
// a[b:x] = reordered a[w:n]
wmerge(a, b, x, n, e, w);
}
// insert a[b:w] into a[b:e] using left shift
for (n = w; n > b; --n) {
t = a[n-1];
for (m = n; m < e && a[m] < t; ++m)
a[m-1] = a[m];
a[m-1] = t;
}
}
}
public static void main(String[] args) {
int[] a = new int[16*1024*1024];
Random r = new Random(0);
for(int i = 0; i < a.length; i++)
a[i] = r.nextInt();
long bgn, end;
bgn = System.currentTimeMillis();
imsort(a, 0, a.length);
end = System.currentTimeMillis();
for(int i = 1; i < a.length; i++){
if(a[i-1] > a[i]){
System.out.println("failed");
break;
}
}
System.out.println("milliseconds " + (end-bgn));
}
}
关于java - 算法 : Hybrid MergeSort and InsertionSort Execution Time,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46496692/
我最近不得不选择一个 Linux 发行版来从网站上下载。我面临三个选择; bt-hybrid 版本、iso-hybrid 版本和 webboot 版本。有什么区别? 最佳答案 bt - 仅用于下载 .
PWA 和混合应用之间有什么区别?之前有人问过这个问题,但我还没有找到合适的答案。 我知道 PWA 在浏览器中运行,您可以从应用商店获得混合应用。 但两者都使用带有 HTML 和 CSS 的 Java
PWA 和混合应用之间有什么区别?之前有人问过这个问题,但我还没有找到合适的答案。 我知道 PWA 在浏览器中运行,您可以从应用商店获得混合应用。 但两者都使用带有 HTML 和 CSS 的 Java
Hybrid App 是混合模式应用的简称,兼具 Native App 和 Web App 两种模式应用的优势,开发成本低,拥有 Web 技术跨平台特性。目前大家所知道的基于中间件的移动开发框架都是
我正在使用将Cordova用于Galaxy Tab E的混合android应用程序。 一切都可以在我的计算机浏览器上正常运行,除了音频文件外,其他选项卡上的功能均相同,但是声音不起作用。 我试过了 -
Closed. This question is off-topic。它当前不接受答案。
我正在使用 Xamarin Forms 构建一个应用程序,在此我实现了一个混合 webview。在 IOS 中,混合 Web View 具有缩放功能,我需要将其禁用。 这是我到目前为止尝试过的:-
我们必须将遗留的 POI 数据库从 MySQL 重新设计为 PostgreSQL。目前,所有实体都有 80-120 多个代表各个属性的属性。 我们被要求考虑新数据库的灵 active 和良好的设计方法
我决定学习如何在 Windows 上创建 Android APK 供个人/学习使用(不适用于 Android Play)。 我的设计计划是在 Android 应用程序上加载远程 HTML 页面,并允许
您能否推荐一个结构良好的 Python 模块,该模块结合了编译的 C 代码(例如使用 distutils)和解释的源代码?我认为“包”可以汇总解释模块和编译模块,但是如果可以将编译源和解释源合并到一个
对于我的网站,我需要有一种方法让用户输入他们的城市。 我想为此使用 2 个下拉列表:“州”和“城市”下拉列表。 “城市”列表中的选项取决于选择的“州”。 但是,必然会出现用户的“城市”不在下拉列表中的
我正在尝试将 AngularJS 1.6 应用程序与 Angular 5 一起转换为混合应用程序。我定义了以下简单过滤器: (function () { "use strict"; v
有没有一种方法可以点击默认的兴趣点并使用 MapKit 显示其弹出窗口? 如果您点击 POI 图标,我附上了它在 Apple Map App 上如何工作的屏幕截图。 如果您尝试在自己的应用程序上使用相
上下文:我正在使用 Cordova 6 和 SAPUI5 框架开发混合应用程序(目前只需要担心 Android)。 我想要的:快速将文件复制/移动到路径。也许得到 FileEntry来自 FileUp
我正在开始一个新的 WPF/Silverlight 自定义控件项目,并想对此进行单元测试。但是我对如何处理这个问题有点困惑。 此控件将基于 WPF 和 Silverlight 的相同代码库,并使用 #
我想在我的 Ionic 混合应用程序的通知栏中显示下载进度。like native app .我正在使用 cordova file transfer下载文件的插件。 Ionic 应用程序可以这样做吗?
我在移动设备上遇到点击问题,我正在英特尔 XDK 中进行调度,使用 cordova 作为程序来理解应用程序中的 native 命令。 当我单击某些输入或重新定向任何页面时,就会出现问题。为了执行上面提
是否可以通过 API(.NET 或 REST)创建应用服务混合连接端点?看来只能通过门户网站才能实现。 我知道可以选择使用旧的 BizTalk 服务混合连接来执行此操作,但我需要使用此选项来实现新的
我使用 Appium 和 Java 来自动化移动应用程序的测试。很明显,当我想为 Android 编写测试时,我使用 AndroidDriver driver = [..]对于 iOS,我需要使用 I
我对 Salesforce 混合移动应用程序开发有点陌生。 我有一个运行良好的混合应用程序。 但是最近上传APK到play store时,play store报错 Your APK has been
我是一名优秀的程序员,十分优秀!