- BubbleSortApp.java部分
- /*
- * 下述的作业题源自<<Java数据结构和算法(第二版)>>每章结束后留给的问题,
- * 它们涵盖了每章的所有重点。目地在于自测,以确保自己已经基本理解该章的内容。
- * 题源:第3章 简单排序
- * 作者:半点闲
- * 时间:2008.7.21 星期一
- *
- * 3.1 bubbleSort.java程序(清单3.1)和BubbleSort专题applet中,in索引变量都是从左
- * 到右移动的,直到找到最大数据项并把它移动到右边的out变量外。修改bubbleSort()方法,
- * 使它成为双向移动的。这样,in索引先像以前一样,将最大的数据项从左移到右,当它到达out
- * 变量位置时,它掉头并把最小的数据项从右移到左。需要两个外部索引变量,一个在右边(以
- * 前的out变量),另一个在左边。
- *
- * 3.4还有一种简单排序算法是奇偶排序。它的思路是在数组中重复两趟扫描。第一趟扫描选择所
- * 有的数据项对,a[j]和a[j+1],j是奇数(j=1,3,5,……)。如果它们的关键字的值次序颠倒,
- * 就交换它们。第二趟扫描对所有的偶数数据项进行同样的操作(j=2,4,6,……)。重复进行这
- * 样两趟的排序直到数组全部有序。用oddEvenSort()方法替换bubbleSort.java程序(清单3.1)
- * 中的bubbleSort()方法。确保它可以在不同数据量的排序中运行,还需要算出两趟扫描的次数。
- * 奇偶排序实际上在多处理器环境中很有用,处理器可以分别同时处理每一个奇数对,然后又同时
- * 处理偶数对。因为奇数对是彼此独立的,每一对都可以用不同的处理器比较和交换。这样可以非
- * 常快速地排序。
- */
- package bubblesortapp;
- /**
- * @author Administrator
- */
- public class Main {
- /**
- * @param args the command line arguments
- */
- public static void main(String[] args) {
- // TODO code application logic here
- int maxSize = 100; //array size
- ArrayBub arr; //reference to array
- arr = new ArrayBub(maxSize); // create the array
- arr.insert(77); //insert 10 items
- arr.insert(99);
- arr.insert(44);
- arr.insert(55);
- arr.insert(22);
- arr.insert(88);
- arr.insert(11);
- arr.insert(00);
- arr.insert(66);
- arr.insert(33);
- arr.display(); //display items
- //arr.bubbleSort(); //bubble sort them
- //arr.display(); //display them again
- //编程作业3.4
- System.out.println("奇偶排序两趟扫描次数共计:" + arr.oddEvenSort());
- arr.display();
- }
- }
- class ArrayBub
- {
- public ArrayBub(int max) //constructor
- {
- a = new long[max]; //create the array
- nElems = 0; // no items yet
- }
- public void insert(long value) //put element into array
- {
- a[nElems] = value; //insert it
- nElems++; //increment size
- }
- public void display() //displays array contents
- {
- for(int j=0; j<nElems; j++) //for each element,
- System.out.print(a[j] + " "); //display it
- System.out.println();
- }
- /**
- * 3.1 bubbleSort.java程序(清单3.1)和BubbleSort专题applet中,in索引变量都是从左
- * 到右移动的,直到找到最大数据项并把它移动到右边的out变量外。修改bubbleSort()方法,
- * 使它成为双向移动的。这样,in索引先像以前一样,将最大的数据项从左移到右,当它到达out
- * 变量位置时,它掉头并把最小的数据项从右移到左。需要两个外部索引变量,一个在右边(以
- * 前的out变量),另一个在左边。
- */
- public void bubbleSort()
- {
- for(int out=nElems-1; out>1; out--) //outer loop (backward)
- {
- int in;
- for(in=0; in<out; in++) //inner loop (forward)
- if( a[in] > a[in+1]) //out of order?
- swap(in, in+1); //swap them
- //编程作业3.1
- for(int j=in; j>0; j--)
- if( a[j] < a[j-1])
- swap(j,j-1);
- }
- }
- /**
- * 3.4还有一种简单排序算法是奇偶排序。它的思路是在数组中重复两趟扫描。第一趟扫描选择所
- * 有的数据项对,a[j]和a[j+1],j是奇数(j=1,3,5,……)。如果它们的关键字的值次序颠倒,
- * 就交换它们。第二趟扫描对所有的偶数数据项进行同样的操作(j=2,4,6,……)。重复进行这
- * 样两趟的排序直到数组全部有序。用oddEvenSort()方法替换bubbleSort.java程序(清单3.1)
- * 中的bubbleSort()方法。确保它可以在不同数据量的排序中运行,还需要算出两趟扫描的次数。
- * 奇偶排序实际上在多处理器环境中很有用,处理器可以分别同时处理每一个奇数对,然后又同时
- * 处理偶数对。因为奇数对是彼此独立的,每一对都可以用不同的处理器比较和交换。这样可以非
- * 常快速地排序。
- */
- public int oddEvenSort()
- {
- int times = 0;
- boolean exchenged = true;
- while (exchenged)
- {
- exchenged = false;
- for(int i=0; i<nElems; i+=2)//偶数部分
- if((i+1) < nElems && a[i] > a[i+1])
- {
- swap(i,i+1);
- ++times;
- exchenged = true;
- }
- for(int i=1; i<nElems; i+=2)//奇数部分
- if((i+1) < nElems && a[i] > a[i+1])
- {
- swap(i,i+1);
- ++times;
- exchenged = true;
- }
- }
- return times;
- }
- /**
- * 使用一个独立的方法不一定好,因为方法调用会增加一些额外的消耗。自己的程序里将交
- * 换操作这段代码直接放到程序中。
- * @param one
- * @param two
- */
- private void swap(int one, int two)
- {
- long temp=a[one];
- a[one] = a[two];
- a[two] = temp;
- }
- private long[] a; //ref to array a
- private int nElems;//number of data items
- }
- InsertSortApp.java部分
- /*
- * 下述的作业题源自<<Java数据结构和算法(第二版)>>每章结束后留给的问题,
- * 它们涵盖了每章的所有重点。目地在于自测,以确保自己已经基本理解该章的内容。
- * 题源:第3章 简单排序
- * 作者:半点闲
- * 时间:2008.7.23 星期三
- *
- * 3.2在isertSort.java程序(清单3.3)中给ArrayIns类加一个median()方法.这个方法将返回
- * 数组的中间值.(回忆一下,数组中一半数据项比中间值大,一半数据项比中间值小。)
- *
- * 3.3在insertSort.java程序(清单3.3)中增加一个名为noDups()的方法,这个方法从已经有
- * 序的数组中删掉重复的数据项而不破坏有序性。(可以用insertionSort()方法对数据排序,
- * 或者也可以简单地用main()方法将数据有序地插入到表中。)一种解决方法是每发现一个重复
- * 的数据,就从这个位置开始到数组结尾都向前移动一个位置,但这样就导致消耗很长的O(N2)的
- * 时间级,起码在有很多重复数据项的情况下是这样的。在设计的算法中,不论有多少重复数据,
- * 要确保数据项最多只能移动一次。这样算法只消耗O(N)数量级的时间。
- *
- * 3.5修改insertSort.java程序(清单3.3)中的insertionSort()方法,使它可以计算排序过
- * 程中复制和比较的次数并显示出总数。为计算比较的次数,要把内层while循环的两个条件分开。
- * 用这个程序测量各种数量的逆序数据排序的复制和比较次数。结果满足O(N2)吗?与已经基本有
- * 序的数据(仅有很少的数据无序)的情况一样吗?从对基本有序数据排序的表现中可得出关于这
- * 个算法效率的什么结论?
- *
- * 3.6有一个有趣的方法用来删除数组中相同的数据项。插入排序算法中用一个循环嵌套算法,将
- * 数组中的每一个数据项与其他数据项一一比较。如果要删除相同的数据项,可以这样做(参见第
- * 2章第2.6小节)。修改insertSort.java中的insertionSort()方法,使它可以在排序过程中
- * 删除相同的数据项。方法如下:当找到一个重复数据项的时候,通常用一个小于任何值的关键值
- * 来改写这个相同数据项(如果所有值都是正数,则可取-1)。于是,一般的插入排序算法就会像
- * 处理其他数据项一样,来处理这个修改了关键值的数据项,把它移到下标为0的位置。从现在开
- * 始,算法可以忽略这个数据项。下一个相同的数据项将被移到下标为1的位置,依此类推。排序
- * 完成后,所有相同的数据项(现在关键值为-1)都在数组的开头部分。可以改变数组的容量并
- * 把需要的数据前移动数组下标为0的位置。
- */
- package insertsortapp;
- /**
- *
- * @author Administrator
- */
- public class Main {
- /**
- * @param args the command line arguments
- */
- public static void main(String[] args) {
- int nRet;
- int maxSize = 100; //array size
- ArrayIns arr; //reference to array
- arr = new ArrayIns(maxSize);//create the array
- /*编程作业3.5 问题1:用这个程序测量各种数量的逆序数据排序的复制和比较次数。结果满足O(N2)吗?*/
- for(int i=9; i>=0; i--)//1.初始化为逆序数组
- arr.insert(i);
- arr.display();
- nRet = arr.insertionSort();
- arr.display();
- System.out.println("编程作业3.5 问题1:比较复制总数:" + nRet );
- /*编程作业3.5 问题2:与已经基本有序的数据(仅有很少的数据无序)的情况一样吗?*/
- ArrayIns arr1 = new ArrayIns(maxSize);
- arr1.insert(00); //insert 10 items
- arr1.insert(11);
- arr1.insert(22);
- arr1.insert(44);
- arr1.insert(55);
- arr1.insert(33);
- arr1.insert(66);
- arr1.insert(88);
- arr1.insert(77);
- arr1.insert(99);
- arr1.display();
- nRet = arr1.insertionSort();
- arr1.display();
- System.out.println("编程作业3.5 问题2:比较复制总数:" + nRet);
- //编程作业3.3
- ArrayIns arr2;
- arr2 = new ArrayIns(maxSize);
- arr2.insert(00); //insert 10 items
- arr2.insert(11);
- arr2.insert(22);
- arr2.insert(22);
- arr2.insert(44);
- arr2.insert(55);
- arr2.insert(33);
- arr2.insert(55);
- arr2.insert(66);
- arr2.insert(88);
- arr2.insert(77);
- arr2.insert(66);
- arr2.insert(99);
- arr2.display();
- arr2.noDups();//删除重复项
- arr2.display();
- //编程作业3.2
- System.out.println("中间值:" + arr.median());
- }
- }
- class ArrayIns
- {
- public ArrayIns(int max)//constructor
- {
- a = new long[max]; //create the array
- nElems = 0; //no items yet
- }
- public void insert(long value)//put element into array
- {
- a[nElems] = value; //insert it
- nElems++; //increment size
- }
- public void display()//displays array contents
- {
- for(int j=0; j<nElems; j++) //for each element,
- System.out.print(a[j] + " ");//display it
- System.out.println("");
- }
- /**
- * 3.5修改insertSort.java程序(清单3.3)中的insertionSort()方法,使它可以计算排序过
- * 程中复制和比较的次数并显示出总数。为计算比较的次数,要把内层while循环的两个条件分开。
- * 用这个程序测量各种数量的逆序数据排序的复制和比较次数。结果满足O(N2)吗?与已经基本有
- * 序的数据(仅有很少的数据无序)的情况一样吗?从对基本有序数据排序的表现中可得出关于这
- * 个算法效率的什么结论?
- *
- * 3.6有一个有趣的方法用来删除数组中相同的数据项。插入排序算法中用一个循环嵌套算法,将
- * 数组中的每一个数据项与其他数据项一一比较。如果要删除相同的数据项,可以这样做(参见第
- * 2章第2.6小节)。修改insertSort.java中的insertionSort()方法,使它可以在排序过程中
- * 删除相同的数据项。方法如下:当找到一个重复数据项的时候,通常用一个小于任何值的关键值
- * 来改写这个相同数据项(如果所有值都是正数,则可取-1)。于是,一般的插入排序算法就会像
- * 处理其他数据项一样,来处理这个修改了关键值的数据项,把它移到下标为0的位置。从现在开
- * 始,算法可以忽略这个数据项。下一个相同的数据项将被移到下标为1的位置,依此类推。排序
- * 完成后,所有相同的数据项(现在关键值为-1)都在数组的开头部分。可以改变数组的容量并
- * 把需要的数据前移动数组下标为0的位置。
- * 注明:这个题目我就不做了,没有什么新意。其实就是把noDups()中的代码和insertionSort()
- * 代码混合后就能达到上述作业要求。
- */
- public int insertionSort()
- {
- int in, /*被“标记”数据项应该插入的位置*/
- out, /*分界线(“标记”,它左边的数据项已经局部有序)*/
- nCompar = 0,/*比较计数器*/
- nCopy = 0; /*拷贝计数器*/
- for(out=1; out<nElems; out++)//out=1,数组中至少得有2个数据项。
- {
- long temp = a[out];//移动前,先请“标记”值出列以腾出空间。
- in = out;//开始移动。
- while(in>0)
- {
- if(a[in-1] >= temp)
- {
- a[in] = a[in-1];
- in--;
- nCompar++;
- nCopy++;
- }
- else
- {
- nCompar++;
- break;
- }
- }
- a[in] = temp;//insert marked item
- }
- return nCompar+nCopy;
- }
- public long median()
- {
- return a[nElems / 2];
- }
- /**
- * 关于编程作业3.3
- * 作者述:就目前来讲我暂时还想不出在不开辟新的空间,来达到书中作业要求的“要确保
- * 数据项最多只能移动一次”这个目标。希望查看此源码的大侠们能给出更高效的方法。
- * 关于下述代码
- * 下述代码采用第2章编程作业:2.6 noDup()方法,在比上次严格的测试发现了源代码中隐
- * 蔽的BUG(主要在“调整部份”),现已经修复我的Blog中有详细说明。
- */
- public void noDups()
- {
- //标记部分
- int nCount = 0; //标记计数器。
- for(int i=0; i<nElems; i++)
- for(int j=0; j<i; j++)
- if(a[j] == a[i])
- {
- if(a[i] != -1) //排除特殊标记
- {
- a[i] = -1; //特殊标记,假设用户不会输入负值。
- nCount++;
- }
- }
- //针对第2章编程作业2.6 noDup()方法中存在的BUG修改后的:调整部分
- long[] b = new long[nElems - nCount];
- int nLength = 0;
- int nVariable = 0;//变数,根据-1值变化调整下标。
- for(int i=0; i<nElems; i++)
- {
- if(a[i] != -1)
- {
- b[i - nVariable] = a[i];
- nLength++;
- }
- else
- nVariable++;
- }
- //重新赋值部份
- nElems = nLength;
- a = b;
- }
- private long[] a; //ref to array a
- private int nElems; //number of data items
- }
Java数据结构和算法-作业2-编程部分
最新推荐文章于 2021-11-15 23:08:29 发布