MergeSort为什么复制和合并比索引快?

问题描述

我正在尝试只比较分配函数而不是每个排序函数的时间差

  1. 复制并合并

复制:-创建2个新的数组子列表[包含索引]

->左=低->中1

-> right = mid-> high-1

合并:-合并左右数组并对其进行排序,并将其作为新列表返回以进行进一步排序

 final class MergeSortSpliterate extends RecursiveTask<List<Integer>>
 {
  private final List<Integer> mList;
 
  private MergeSortSpliterate(List<Integer> mList){this.mList = mList;}

  @Override
  public List<Integer> compute()
  {
   if(mList.size()>1)
   {
    int mid=mList.size()/2;

    ForkJoinTask<List<Integer>>
    leftSort=new MergeSortSpliterate(mList.subList(0,mid)).fork(),rightSort=new MergeSortSpliterate(mList.subList(mid,mList.size())).fork();

    ArrayList<Integer> mergedResults=new ArrayList();
    mergedResults.addAll(leftSort.join());
    mergedResults.addAll(rightSort.join());

    /*Not Doing Any Sorting just the partioning .I am trying to understand why this code is much faster[inspite of operations like sublist and addAll]*/
    return mergedResults;
   }
   return mList;
  }
 }
  1. 按索引排序并合并为原始文件

->仅对由高和低指定的数组部分进行排序

 final class MergeSortIndex extends RecursiveAction
 {
  private final int[] mList;
  private final int low,high;

  private MergeSortIndex(int[] mList,int low,int high)
  {
   this.mList = mList;
   this.low = low;
   this.high = high;
  }

  @Override
  public void compute()
  {
   if((high-low)>1)
   {
    int mid=(low+high)/2;

    ForkJoinTask<Void>
    leftSort=new MergeSortIndex(mList,mid).fork(),rightSort=new MergeSortIndex(mList,mid,high).fork();

    leftSort.join();
    rightSort.join();

    /*again not sorting here,just want to understand why this code is taking much longer than copy and merge*/
   }
  }
}

人们会凭直觉说基于索引的排序应该快得多,因为没有新的列表创建或子列表操作,但是当我按以下方式运行主代码

public static void main(String[] args) 
 {
  ForkJoinPool pool=new ForkJoinPool(3);
  
  A_Gui gui=new A_Gui("Merge Sort Spliterate",8);
  Logger logger=new Logger(pool,gui);
  logger.start();
 
  int mode=2;
  
  if(mode==1)
  {
   long start=System.currentTimeMillis();
   List<Integer> list=new ArrayList(List.of(6,1,5,2,8,10,12,3,4,15,2));
   list=pool.invoke(new MergeSortSpliterate(list));
   JOptionPane.showMessageDialog(null,"Finished copy & Merge Sort After "+(System.currentTimeMillis()-start));
   list.forEach((element)->System.out.print(element+","));
  }
  else
  {
   long start=System.currentTimeMillis();
   int[] elements={6,2};
   pool.invoke(new MergeSortIndex(elements,elements.length));
   JOptionPane.showMessageDialog(null,"Finished Index Sort After "+(System.currentTimeMillis()-start));
   for(int element:elements){System.out.print(element+",");}
  }
  
  pool.shutdown();
 }

我得到以下结果

mode=1[copy & Merge]                         
31ms    
                                      
16ms   
                                       
15ms                                          

mode=2[Index]

93ms

86ms

110ms

这些样本很少,但结果始终是模式1

起初,我以为Arrays.sort()引起了瓶颈,并且效率不如Collections.sort(),因此我删除了这两种方法只是为了了解每种情况下分配函数要花多长时间,这就是结果

由于没有创建和合并操作,索引显然应该更快,但事实并非如此

任何有见识的问题,或者我想指出的问题,将不胜感激

附加项 可能不需要这样做,但我尝试检查forkjoinpool的所有参数以进行调试。

final class A_Gui extends JFrame
{
 private JLabel labels[];
 
 A_Gui(String tittle,int labels)
 {
  super(tittle);

  JPanel panel=new JPanel();

  panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));

  setContentPane(panel);

  addLabels(labels);

  pack();

  setResizable(false);

  setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);

  setVisible(true);
 }

 private void addLabels(int num)
 {
  Dimension dim=new Dimension(300,50);

  labels=new JLabel[num];

  for(int i=0;i<labels.length;i++)
  {
   labels[i]=new JLabel();

   labels[i].setMinimumSize(dim);
   labels[i].setPreferredSize(dim); 
   labels[i].setMaximumSize(dim);

   add(labels[i]);
  } 
 }

 synchronized void set(int index,String value){      
  SwingUtilities.invokelater(()->labels[index].setText(value));      
 }
}



final class Logger extends Thread
 {
  private final ForkJoinPool pool;
  private final A_Gui gui;
  
  private Logger(ForkJoinPool pool,A_Gui gui)
  {
   this.pool=pool;
   this.gui=gui;
  }
  
  @Override
  public void run()
  {
   while(true)
   {
    gui.set(0,"Active Thread Count="+pool.getActiveThreadCount());
    gui.set(1,"Async Mode="+pool.getAsyncMode());
    gui.set(2,"Parallism="+pool.getParallelism());
    gui.set(3,"Pool Size="+pool.getPoolSize());
    gui.set(4,"Qued Submission Count="+pool.getQueuedSubmissionCount());
    gui.set(5,"Qued Task Count="+pool.getQueuedTaskCount());
    gui.set(6,"Running Thread Count="+pool.getRunningThreadCount());
    gui.set(7,"Steal Count="+pool.getStealCount());
    
    try{TimeUnit.MILLISECONDS.sleep(1);}
    catch(InterruptedException ex){}
   }
  }
 }

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)