Java数据结构和算法-作业2-编程部分

  1. BubbleSortApp.java部分
  2. /*
  3.  * 下述的作业题源自<<Java数据结构和算法(第二版)>>每章结束后留给的问题,
  4.  * 它们涵盖了每章的所有重点。目地在于自测,以确保自己已经基本理解该章的内容。
  5.  * 题源:第3章 简单排序
  6.  * 作者:半点闲
  7.  * 时间:2008.7.21 星期一
  8.  * 
  9.  * 3.1 bubbleSort.java程序(清单3.1)和BubbleSort专题applet中,in索引变量都是从左
  10.  * 到右移动的,直到找到最大数据项并把它移动到右边的out变量外。修改bubbleSort()方法,
  11.  * 使它成为双向移动的。这样,in索引先像以前一样,将最大的数据项从左移到右,当它到达out
  12.  * 变量位置时,它掉头并把最小的数据项从右移到左。需要两个外部索引变量,一个在右边(以
  13.  * 前的out变量),另一个在左边。
  14.  * 
  15.  * 3.4还有一种简单排序算法是奇偶排序。它的思路是在数组中重复两趟扫描。第一趟扫描选择所
  16.  * 有的数据项对,a[j]和a[j+1],j是奇数(j=1,3,5,……)。如果它们的关键字的值次序颠倒,
  17.  * 就交换它们。第二趟扫描对所有的偶数数据项进行同样的操作(j=2,4,6,……)。重复进行这
  18.  * 样两趟的排序直到数组全部有序。用oddEvenSort()方法替换bubbleSort.java程序(清单3.1)
  19.  * 中的bubbleSort()方法。确保它可以在不同数据量的排序中运行,还需要算出两趟扫描的次数。
  20.  * 奇偶排序实际上在多处理器环境中很有用,处理器可以分别同时处理每一个奇数对,然后又同时
  21.  * 处理偶数对。因为奇数对是彼此独立的,每一对都可以用不同的处理器比较和交换。这样可以非
  22.  * 常快速地排序。
  23.  */
  24. package bubblesortapp;
  25. /**
  26.  * @author Administrator
  27.  */
  28. public class Main {
  29.     /**
  30.      * @param args the command line arguments
  31.      */
  32.     public static void main(String[] args) {
  33.         // TODO code application logic here
  34.         int maxSize = 100;      //array size
  35.         ArrayBub arr;           //reference to array
  36.         arr = new ArrayBub(maxSize);    // create the array
  37.         
  38.         arr.insert(77);     //insert 10 items
  39.         arr.insert(99);
  40.         arr.insert(44);
  41.         arr.insert(55);
  42.         arr.insert(22);
  43.         arr.insert(88);
  44.         arr.insert(11);
  45.         arr.insert(00);
  46.         arr.insert(66);
  47.         arr.insert(33);
  48.         
  49.         arr.display();      //display items
  50.         //arr.bubbleSort();   //bubble sort them
  51.         //arr.display();      //display them again
  52.         //编程作业3.4
  53.         System.out.println("奇偶排序两趟扫描次数共计:" + arr.oddEvenSort());
  54.         arr.display();
  55.     }
  56. }
  57. class ArrayBub
  58. {
  59.     public ArrayBub(int max)    //constructor
  60.     {
  61.         a = new long[max];  //create the array
  62.         nElems = 0;         // no items yet
  63.     }
  64.     public void insert(long value)  //put element into array
  65.     {
  66.         a[nElems] = value;  //insert it
  67.         nElems++;           //increment size
  68.     }
  69.     public void display()   //displays array contents
  70.     {
  71.         for(int j=0; j<nElems; j++)         //for each element,
  72.             System.out.print(a[j] + " ");   //display it
  73.         System.out.println();
  74.     }
  75.  /**
  76.  * 3.1 bubbleSort.java程序(清单3.1)和BubbleSort专题applet中,in索引变量都是从左
  77.  * 到右移动的,直到找到最大数据项并把它移动到右边的out变量外。修改bubbleSort()方法,
  78.  * 使它成为双向移动的。这样,in索引先像以前一样,将最大的数据项从左移到右,当它到达out
  79.  * 变量位置时,它掉头并把最小的数据项从右移到左。需要两个外部索引变量,一个在右边(以
  80.  * 前的out变量),另一个在左边。
  81.  */
  82.     public void bubbleSort()
  83.     {
  84.         for(int out=nElems-1; out>1; out--) //outer loop (backward)
  85.         {
  86.             int in;
  87.             for(in=0; in<out; in++)         //inner loop (forward)
  88.                 if( a[in] > a[in+1])        //out of order?
  89.                     swap(in, in+1);         //swap them
  90.             //编程作业3.1
  91.             for(int j=in; j>0; j--)
  92.                 if( a[j] < a[j-1])
  93.                     swap(j,j-1);
  94.         }
  95.     }
  96.  /**
  97.  * 3.4还有一种简单排序算法是奇偶排序。它的思路是在数组中重复两趟扫描。第一趟扫描选择所
  98.  * 有的数据项对,a[j]和a[j+1],j是奇数(j=1,3,5,……)。如果它们的关键字的值次序颠倒,
  99.  * 就交换它们。第二趟扫描对所有的偶数数据项进行同样的操作(j=2,4,6,……)。重复进行这
  100.  * 样两趟的排序直到数组全部有序。用oddEvenSort()方法替换bubbleSort.java程序(清单3.1)
  101.  * 中的bubbleSort()方法。确保它可以在不同数据量的排序中运行,还需要算出两趟扫描的次数。
  102.  * 奇偶排序实际上在多处理器环境中很有用,处理器可以分别同时处理每一个奇数对,然后又同时
  103.  * 处理偶数对。因为奇数对是彼此独立的,每一对都可以用不同的处理器比较和交换。这样可以非
  104.  * 常快速地排序。
  105.  */
  106.     public int oddEvenSort()
  107.     {
  108.         int times = 0;
  109.         boolean exchenged = true;
  110.         
  111.         while (exchenged)
  112.         {
  113.             exchenged = false;
  114.             for(int i=0; i<nElems; i+=2)//偶数部分
  115.                 if((i+1) < nElems && a[i] > a[i+1])
  116.                 {
  117.                     swap(i,i+1);
  118.                     ++times;
  119.                     exchenged = true;
  120.                 }
  121.             
  122.             for(int i=1; i<nElems; i+=2)//奇数部分
  123.                 if((i+1) < nElems && a[i] > a[i+1])
  124.                 {
  125.                     swap(i,i+1);
  126.                     ++times;
  127.                     exchenged = true;
  128.                 }
  129.         }
  130.         return times;
  131.     }
  132.     /**
  133.      * 使用一个独立的方法不一定好,因为方法调用会增加一些额外的消耗。自己的程序里将交
  134.      * 换操作这段代码直接放到程序中。
  135.      * @param one
  136.      * @param two
  137.      */
  138.     private void swap(int one, int two)
  139.     {
  140.         long temp=a[one];
  141.         a[one] = a[two];
  142.         a[two] = temp;
  143.     }
  144.     private long[] a;  //ref to array a
  145.     private int nElems;//number of data items
  146. }
  147. InsertSortApp.java部分
  148. /*
  149.  * 下述的作业题源自<<Java数据结构和算法(第二版)>>每章结束后留给的问题,
  150.  * 它们涵盖了每章的所有重点。目地在于自测,以确保自己已经基本理解该章的内容。
  151.  * 题源:第3章 简单排序
  152.  * 作者:半点闲
  153.  * 时间:2008.7.23 星期三
  154.  * 
  155.  * 3.2在isertSort.java程序(清单3.3)中给ArrayIns类加一个median()方法.这个方法将返回
  156.  * 数组的中间值.(回忆一下,数组中一半数据项比中间值大,一半数据项比中间值小。)
  157.  * 
  158.  * 3.3在insertSort.java程序(清单3.3)中增加一个名为noDups()的方法,这个方法从已经有
  159.  * 序的数组中删掉重复的数据项而不破坏有序性。(可以用insertionSort()方法对数据排序,
  160.  * 或者也可以简单地用main()方法将数据有序地插入到表中。)一种解决方法是每发现一个重复
  161.  * 的数据,就从这个位置开始到数组结尾都向前移动一个位置,但这样就导致消耗很长的O(N2)的
  162.  * 时间级,起码在有很多重复数据项的情况下是这样的。在设计的算法中,不论有多少重复数据,
  163.  * 要确保数据项最多只能移动一次。这样算法只消耗O(N)数量级的时间。
  164.  * 
  165.  * 3.5修改insertSort.java程序(清单3.3)中的insertionSort()方法,使它可以计算排序过
  166.  * 程中复制和比较的次数并显示出总数。为计算比较的次数,要把内层while循环的两个条件分开。
  167.  * 用这个程序测量各种数量的逆序数据排序的复制和比较次数。结果满足O(N2)吗?与已经基本有
  168.  * 序的数据(仅有很少的数据无序)的情况一样吗?从对基本有序数据排序的表现中可得出关于这
  169.  * 个算法效率的什么结论?
  170.  * 
  171.  * 3.6有一个有趣的方法用来删除数组中相同的数据项。插入排序算法中用一个循环嵌套算法,将
  172.  * 数组中的每一个数据项与其他数据项一一比较。如果要删除相同的数据项,可以这样做(参见第
  173.  * 2章第2.6小节)。修改insertSort.java中的insertionSort()方法,使它可以在排序过程中
  174.  * 删除相同的数据项。方法如下:当找到一个重复数据项的时候,通常用一个小于任何值的关键值
  175.  * 来改写这个相同数据项(如果所有值都是正数,则可取-1)。于是,一般的插入排序算法就会像
  176.  * 处理其他数据项一样,来处理这个修改了关键值的数据项,把它移到下标为0的位置。从现在开
  177.  * 始,算法可以忽略这个数据项。下一个相同的数据项将被移到下标为1的位置,依此类推。排序
  178.  * 完成后,所有相同的数据项(现在关键值为-1)都在数组的开头部分。可以改变数组的容量并
  179.  * 把需要的数据前移动数组下标为0的位置。
  180.  */
  181. package insertsortapp;
  182. /**
  183.  *
  184.  * @author Administrator
  185.  */
  186. public class Main {
  187.     /**
  188.      * @param args the command line arguments
  189.      */
  190.     public static void main(String[] args) {
  191.         int nRet;
  192.         int maxSize = 100;  //array size
  193.         ArrayIns arr;       //reference to array
  194.         arr = new ArrayIns(maxSize);//create the array
  195.         
  196.         /*编程作业3.5 问题1:用这个程序测量各种数量的逆序数据排序的复制和比较次数。结果满足O(N2)吗?*/
  197.         for(int i=9; i>=0; i--)//1.初始化为逆序数组
  198.             arr.insert(i);
  199.         arr.display();
  200.         nRet = arr.insertionSort();
  201.         arr.display();
  202.         System.out.println("编程作业3.5 问题1:比较复制总数:" + nRet );
  203.         
  204.         /*编程作业3.5 问题2:与已经基本有序的数据(仅有很少的数据无序)的情况一样吗?*/
  205.         ArrayIns arr1 = new ArrayIns(maxSize); 
  206.         arr1.insert(00); //insert 10 items
  207.         arr1.insert(11);
  208.         arr1.insert(22);
  209.         arr1.insert(44);
  210.         arr1.insert(55);
  211.         arr1.insert(33);
  212.         arr1.insert(66);
  213.         arr1.insert(88);
  214.         arr1.insert(77);
  215.         arr1.insert(99);
  216.         arr1.display();
  217.         nRet = arr1.insertionSort();
  218.         arr1.display();
  219.         System.out.println("编程作业3.5 问题2:比较复制总数:" + nRet);
  220.         
  221.         //编程作业3.3
  222.         ArrayIns arr2;
  223.         arr2 = new ArrayIns(maxSize);
  224.         arr2.insert(00); //insert 10 items
  225.         arr2.insert(11);
  226.         arr2.insert(22);
  227.         arr2.insert(22);
  228.         arr2.insert(44);
  229.         arr2.insert(55);
  230.         arr2.insert(33);
  231.         arr2.insert(55);
  232.         arr2.insert(66);
  233.         arr2.insert(88);
  234.         arr2.insert(77);
  235.         arr2.insert(66);
  236.         arr2.insert(99);
  237.         arr2.display();
  238.         arr2.noDups();//删除重复项
  239.         arr2.display();
  240.         
  241.         //编程作业3.2
  242.         System.out.println("中间值:" + arr.median());
  243.     }
  244. }
  245. class ArrayIns
  246. {
  247.     public ArrayIns(int max)//constructor
  248.     {
  249.         a = new long[max];  //create the array
  250.         nElems = 0;         //no items yet
  251.     }
  252.     public void insert(long value)//put element into array
  253.     {
  254.         a[nElems] = value;  //insert it
  255.         nElems++;           //increment size
  256.     }
  257.     public void display()//displays array contents
  258.     {
  259.         for(int j=0; j<nElems; j++)     //for each element,
  260.             System.out.print(a[j] + " ");//display it
  261.         System.out.println("");
  262.     }
  263.  /**
  264.  * 3.5修改insertSort.java程序(清单3.3)中的insertionSort()方法,使它可以计算排序过
  265.  * 程中复制和比较的次数并显示出总数。为计算比较的次数,要把内层while循环的两个条件分开。
  266.  * 用这个程序测量各种数量的逆序数据排序的复制和比较次数。结果满足O(N2)吗?与已经基本有
  267.  * 序的数据(仅有很少的数据无序)的情况一样吗?从对基本有序数据排序的表现中可得出关于这
  268.  * 个算法效率的什么结论?
  269.  *
  270.  * 3.6有一个有趣的方法用来删除数组中相同的数据项。插入排序算法中用一个循环嵌套算法,将
  271.  * 数组中的每一个数据项与其他数据项一一比较。如果要删除相同的数据项,可以这样做(参见第
  272.  * 2章第2.6小节)。修改insertSort.java中的insertionSort()方法,使它可以在排序过程中
  273.  * 删除相同的数据项。方法如下:当找到一个重复数据项的时候,通常用一个小于任何值的关键值
  274.  * 来改写这个相同数据项(如果所有值都是正数,则可取-1)。于是,一般的插入排序算法就会像
  275.  * 处理其他数据项一样,来处理这个修改了关键值的数据项,把它移到下标为0的位置。从现在开
  276.  * 始,算法可以忽略这个数据项。下一个相同的数据项将被移到下标为1的位置,依此类推。排序
  277.  * 完成后,所有相同的数据项(现在关键值为-1)都在数组的开头部分。可以改变数组的容量并
  278.  * 把需要的数据前移动数组下标为0的位置。
  279.   * 注明:这个题目我就不做了,没有什么新意。其实就是把noDups()中的代码和insertionSort()
  280.   * 代码混合后就能达到上述作业要求。
  281.  */
  282.     public int insertionSort()
  283.     {
  284.         int in,         /*被“标记”数据项应该插入的位置*/
  285.             out,        /*分界线(“标记”,它左边的数据项已经局部有序)*/
  286.             nCompar = 0,/*比较计数器*/
  287.             nCopy = 0;  /*拷贝计数器*/
  288.         
  289.         for(out=1; out<nElems; out++)//out=1,数组中至少得有2个数据项。
  290.         {
  291.             long temp = a[out];//移动前,先请“标记”值出列以腾出空间。
  292.             in = out;//开始移动。
  293.             while(in>0)
  294.             {
  295.                 if(a[in-1] >= temp)
  296.                 {
  297.                     a[in] = a[in-1];
  298.                     in--;
  299.                     nCompar++;
  300.                     nCopy++;
  301.                 }
  302.                 else
  303.                 {
  304.                     nCompar++;
  305.                     break;
  306.                 }
  307.             }
  308.             a[in] = temp;//insert marked item
  309.         }
  310.         return nCompar+nCopy;
  311.     }
  312.     public long median()
  313.     {
  314.         return a[nElems / 2];
  315.     }
  316.     /**
  317.      * 关于编程作业3.3
  318.      * 作者述:就目前来讲我暂时还想不出在不开辟新的空间,来达到书中作业要求的“要确保
  319.      * 数据项最多只能移动一次”这个目标。希望查看此源码的大侠们能给出更高效的方法。
  320.      * 关于下述代码
  321.      * 下述代码采用第2章编程作业:2.6 noDup()方法,在比上次严格的测试发现了源代码中隐
  322.      * 蔽的BUG(主要在“调整部份”),现已经修复我的Blog中有详细说明。
  323.      */
  324.     public void noDups()
  325.     {
  326.         //标记部分
  327.         int nCount = 0//标记计数器。
  328.         
  329.         for(int i=0; i<nElems; i++)
  330.             for(int j=0; j<i; j++)
  331.                 if(a[j] == a[i])
  332.                 {
  333.                     if(a[i] != -1)  //排除特殊标记
  334.                     {
  335.                         a[i] = -1;  //特殊标记,假设用户不会输入负值。
  336.                         nCount++;
  337.                     }
  338.                 }
  339.         //针对第2章编程作业2.6 noDup()方法中存在的BUG修改后的:调整部分
  340.         long[] b = new long[nElems - nCount];
  341.         int nLength = 0;
  342.         int nVariable = 0;//变数,根据-1值变化调整下标。
  343.         
  344.         for(int i=0; i<nElems; i++)
  345.         {
  346.             if(a[i] != -1)
  347.             {
  348.                 b[i - nVariable] = a[i];
  349.                 nLength++;
  350.             }
  351.             else
  352.                 nVariable++;
  353.         }
  354.         //重新赋值部份
  355.         nElems = nLength;
  356.         a = b;
  357.     }
  358.     private long[] a;   //ref to array a
  359.     private int nElems; //number of data items
  360. }
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值