XJTUSE-数据结构-homework2

news2024/11/24 12:23:25

当时写的还挺痛苦的

不过现在看,原老师布置的作业真的有水平

现在来看大二数据结构的作业,真的很锻炼代码能力。有些题目,我现在写也不一定能很快写出来hhhh

当时写的作业感觉还是存在问题的!

任务概述

 

 

任务 1 :指定的 List ADT 实现

题目:见pdf

1、使用顺序数组作为存储表示:

数据设计:

  1. private int MAXLEN;  
  2. private char[] seqList = null;  
  3. private int cursor = -1;  
  4. private int tail = 0;

在使用顺序数组作为存储表示中,设计了以上几个私有变量,下面一一进行说明。

MAXLEN表示顺序数组的最大储存空间,这是因为顺序数组是依靠数组的存储空间实现的,必须在一开始规定好其数组的大小。

seqList 表示顺序数组,存储字符,初始化为null。

cursor  表示顺序数组的起始下标,初始化为-1。

tail   表示顺序数组的结尾下标,初始化为0。

算法设计:

  1. public void insert(char newElement) {  
  2.         //  after the cursor  
  3.         if (tail>=MAXLEN){  
  4.             return;  
  5.         }  
  6. //        空数组插入  
  7.         if (tail==0){  
  8.             cursor++;  
  9.             seqList[cursor] = newElement;  
  10.             tail++;  
  11.             return;  
  12.         }  
  13. //        非空插入  
  14.         for (int i=tail-1;i>cursor;i--){  
  15.             seqList[i+1] = seqList[i];  
  16.         }  
  17.         cursor++;  
  18.         seqList[cursor] = newElement;  
  19.         tail++;  
  20.     } 

根据题目中的插入要求,分成了三种基本情况:满数组,空数组,正常插入(非空数组)。根据要求可知道,要先判断满数组和空数组,若都不是,再进行正常插入。因为是顺序数组,所以说进行插入操作需要复制插入位置之后的所有元素,又因为剩下的操作均在常数项时间内能完成,由此插入操作的时间复杂度为O(n)   。

  1. public void remove() {  
  2.         tail--;  
  3.         //        空数组  
  4.         if (tail <= 0){  
  5.             tail = 0;  
  6.             cursor = -1;  
  7.             seqList = new char[MAXLEN];  
  8.             return;  
  9.         }  
  10.         for(int i=cursor;i<tail;i++){  
  11.             seqList[i] = seqList[i+1];  
  12.         }  
  13.         cursor = cursor%tail;  
  14.     }  

删除操作也分为两种基本情况:空数组,正常删除。在删除操作中,要把需要删除的元素后面的元素往前移一位,其它操作均为常数项,因此时间复杂度为O(n)   。需要注意的是,在删除操作中cursor = cursor%tail

很重要,这是因为当删除的元素位于数组的tail位置时,cursor需要指向首元素,因此需要上述操作。

  1. public void replace(char newElement) {  
  2.         if (cursor < 0){  
  3.             return;  
  4.         }  
  5.         seqList[cursor] = newElement;  
  6.     }  

替换操作比较简单,不进行说明,唯一需要注意的是当空数组时,无需操作,直接返回。时间复杂度为O(1)   。

  1. public void clear() {  
  2.         seqList = new char[MAXLEN];  
  3.         cursor = -1;  
  4.         tail = 0;  
  5.     }  

清空操作比较简单,不进行说明,时间复杂度为O(1)  。

  1. public boolean isEmpty() {  
  2.         if (tail == 0){  
  3.             return true;  
  4.         }  
  5.         return false;  
  6.     }  
  7. public boolean isFull() {  
  8.         if (tail == seqList.length){  
  9.             return true;  
  10.         }  
  11.         return false;  
  12.     }  

根据指向顺序数组的尾部的变量来判断顺序数组是否为空或者满,时间复杂度为O(1)  。

  1. public boolean gotoBeginning() {  
  2.         if (this.isEmpty()){  
  3.             return false;  
  4.         }  
  5.         cursor = 0;  
  6.         return true;  
  7.     }  
  8. public boolean gotoEnd() {  
  9.         if (this.isEmpty()){  
  10.             return false;  
  11.         }  
  12.         cursor = tail-1;  
  13.         return true;  
  14.     }  
  15. public boolean gotoNext() {  
  16.         if (cursor == tail-1){  
  17.             return false;  
  18.         }  
  19.         cursor++;  
  20.         return true;  
  21.     }  
  22. public boolean gotoPrev() {  
  23.         if (cursor <= 0){  
  24.             return false;  
  25.         }  
  26.         cursor--;  
  27.         return true;  
  28.     }  

以上方法都是改变cursor指向位置,不改变元素,因此处理方法大同小异,需要注意空数组,满数组等特殊情况即可。时间复杂度为O(1)  。

  1. public char getCursor() {  
  2.         return seqList[cursor];  
  3.     }  

返回即可,时间复杂度为O(1)  。

  1. public void showStructure(){  
  2.     if (tail == 0){  
  3.         System.out.printf("Empty list -1%n");  
  4.         return;  
  5.     }  
  6.     for(int i=0;i<tail;i++){  
  7.         System.out.printf("%c ",seqList[i]);  
  8.     }  
  9.     System.out.printf("%d%n",cursor);  
  10. }

展示顺序数组所含元素以及当前指向元素位置,时间复杂度为O(n)

2、使用单向链表作为存储表示

数据设计:

  1. //    成员变量  
  2.     public char element = ' ';//选择一个没有意义的字符作为初始化字符  
  3.     public LList next = null;  
  4.   
  5. //    类变量  
  6.     static public int cursor = -1;   //记录当前元素的位置的前一个位置  
  7.     static public LList dummy = new LList();  
  8.     static public LList head = dummy;//    初始化为哑节点  
  9.     static public LList cur = dummy;//指向当前元素的指针,初始化为哑节点  

数据分为成员变量和类变量,注释中已说明具体含义。需要重点说明的一点为,我编写的单向链表采用了哑节点的方式,虽然会带来操作上的一些理解困难,但是减少了一些操作的时间。需要和顺序数组区分的是,以链表实现的存储表示不需要提前确定最大容量。

算法设计:

  1.     public void insert(char newElement) {  
  2.         LList tem = new LList();  
  3.         tem.element = newElement;  
  4. //        判断是否为空,是的话直接插入  
  5.         if (isEmpty()){  
  6.             cur.next = tem;  
  7.             return;  
  8.         }  
  9. //        判断是否在尾部,是的话直接插入并且转化cur  
  10.         if (isFull()){  
  11.             cur.next.next = tem;  
  12.             cur = cur.next;  
  13.             return;  
  14.         }  
  15. //        后面有元素  
  16.         tem.next = cur.next.next;  
  17.         cur.next.next = tem;  
  18.         cur = cur.next;  
  19.     }  

插入操作分为三种情况:空数组,满数组,正常插入。由于使用了链表结构,插入操作难度大幅降低,只需要把需要插入位置前的元素指向插入元素,插入元素指向插入位置后的元素。因此,时间复杂度为O(1)  。

  1. public void remove() {  
  2.         if (isEmpty()){  
  3.             return;  
  4.         }  
  5.         if (isFull()){  
  6.             cur.next = null;  
  7.             cur = dummy;  
  8.             return;  
  9.         }  
  10.         cur.next = cur.next.next;  
  11.     }  

删除操作与插入操作大同小异,也是三种情况:空数组,满数组,正常删除。但是,由于采用了哑节点技术,使得我们删除操作得到了极大的优化,只需要把cur指针往前移即可。

因此,时间复杂度为O(1)  。

  1. public void replace(char newElement) {  
  2.         if (cur.next == null){  
  3.             return;  
  4.         }  
  5.         cur.next.element = newElement;  
  6.     }  

代替操作不能直接代替,需要先判断cur.next是否为null。因此,时间复杂度为O(1)  。

  1. public void clear() {  
  2.         cur =dummy;  
  3.         dummy.next = null;  
  4.     }  

清除操作只需要简单地改变两个类变量的值即可。因此,时间复杂度为O(1)  。

  1. public boolean isEmpty() {  
  2.         return head.next == null;  
  3.     }  
  4. public boolean isFull() {  
  5.         return cur.next.next == null;  
  6.     }  

判断是否为空数组和满数组时,只需要看各个指针的情况即可。因此,时间复杂度为O(1)  。

  1. public boolean gotoBeginning() {  
  2.         if (isEmpty()){  
  3.             return false;  
  4.         }  
  5.         cur = head;  
  6.         return true;  
  7.     }  
  8. public boolean gotoEnd() {  
  9.         if (isEmpty()){  
  10.             return false;  
  11.         }  
  12.         while (cur.next.next != null){  
  13.             cur = cur.next;  
  14.         }  
  15.         return true;  
  16.     }  
  17. public boolean gotoNext() {  
  18.         if (isEmpty()){  
  19.             return false;  
  20.         }  
  21.         if (isFull()){  
  22.             return false;  
  23.         }  
  24.         cur = cur.next;  
  25.         return true;  
  26.     } public boolean gotoPrev() {  
  27.         if (isEmpty()){  
  28.             return false;  
  29.         }  
  30.         if (cur == head){  
  31.             return true;  
  32.         }  
  33.         LList tem = head;  
  34.         while (tem.next != cur){  
  35.             tem = tem.next;  
  36.         }  
  37.         cur = tem;  
  38.         return true;  
  39.     }  

以上方法都是改变cur的指向位置,不改变元素,因此处理方法大同小异,需要注意空数组,满数组,在第一元素时不能向前移动,在最后一个元素不能向后移动等特殊情况即可。时间复杂度为O(1)  。

  1. public char getCursor() {  
  2.         return cur.next.element;  
  3.     }  

返回指向元素,时间复杂度为O(1)  。

  1. public void showStructure() {  
  2.         if(isEmpty()){  
  3.             System.out.printf("Empty list -1%n");  
  4.             return;  
  5.         }  
  6.         LList tem = head.next;  
  7.         while (tem.next != null){  
  8.             System.out.printf("%c ",tem.element);  
  9.             tem = tem.next;  
  10.         }  
  11.         cursor = getIntCursor();  
  12.         System.out.printf("%c %d%n",tem.element,cursor);  
  13.     }  

展示单向数组所含元素以及当前指向元素位置,cursor是获取当前指向元素在单向链表的下标,因此可以知道时间复杂度为O(n)。同时展示元素要一一遍历,时间复杂度为O(n)。

3、使用双向链表作为存储表示

数据设计:

  1. //    成员变量  
  2. public char element = ' ';//选择一个没有意义的字符作为初始化字符  
  3. public DList next = null;  
  4. public DList pre = null;  
  5.   
  6. //    类变量  
  7. static public int cursor = -1;   //记录当前元素的位置,无需提前一个位置  
  8. static public DList head = null;//    初始化  
  9. static public DList cur = head;//指向当前元素的指针  

双向链表的数据变量分为成员变量和类变量,具体含义在注释中已说明,不赘述。需要注意的是,在双向链表中,由于双向链表的特性,没有采用哑节点,指针指向当前元素的位置。

算法设计:

  1. public void insert(char newElement) {  
  2.     DList tem = new DList();  
  3.     tem.element = newElement;  
  4.       判断是否为空,是的话开始创建  
  5.     if (isEmpty()){  
  6.         cur = tem;  
  7.         head =cur;  
  8.         return;  
  9.     }  
  10.     tem.next = cur.next;  
  11.     tem.pre = cur;  
  12.     cur.next = tem;  
  13.     if (tem.next!=null){  
  14.         tem.next.pre = tem;  
  15.     }  
  16.     cur = tem;  
  17. }  

插入操作分为三种情况:空数组,正常插入。操作与单向链表类似,但是需要进行tem.next!=null判断,避免满数组插入时导致空指针错误,总而言之,双链表的插入操作时间复杂度为O(1)  。

  1. public void remove() {  
  2.     if (isEmpty()){  
  3.         return;  
  4.     }  
  5.     if (cur == head){  
  6.         cur = head.next;  
  7.         head = cur;  
  8.         return;  
  9.     }  
  10.     if (isFull()){  
  11.         cur.pre.next = null;  
  12.         cur = head;  
  13.         return;  
  14.     }  
  15.     cur.next.pre = cur.pre;  
  16.     cur = cur.next;  
  17.     cur.pre.next = cur;  
  18. }  

由于没有采用哑节点,因此需要判断的条件相较于单向链表较多,一共有四种情况:空列表,只有一个元素的列表,满列表,正常插入。尽管情况较多,但由于双向链表有指向前一元素的指针,因此删除操作只需要把前后元素“相连”,时间复杂度为O(1)  。

  1. public void replace(char newElement) {  
  2.     if (isEmpty()){  
  3.         return;  
  4.     }   

替换操作,时间复杂度为O(1)  。

  1. public void clear() {  
  2.     head = null;  
  3.     cur = head;  
  4. }  
  5. public boolean isEmpty() {  
  6.     return cur == null;  
  7. }  
  8. public boolean isFull() {  
  9.     return cur==null||cur.next==null;  
  10. }  

如上操作,都是对head,cur指针进行判断或者赋值,时间复杂度为O(1)  。

  1. public boolean gotoBeginning() {  
  2.     if (isEmpty()){  
  3.         return false;  
  4.     }  
  5.     cur = head;  
  6.     return true;  
  7. }  
  8. public boolean gotoEnd() {  
  9.     if (isEmpty()){  
  10.         return false;  
  11.     }  
  12.     while (cur.next != null){  
  13.         cur = cur.next;  
  14.     }  
  15.     return true;  
  16. }  
  17. public boolean gotoNext() {  
  18.     if (isEmpty()){  
  19.         return false;  
  20.     }  
  21.     if (isFull()){  
  22.         return false;  
  23.     }  
  24.     cur = cur.next;  
  25.     return true;  
  26. }  
  27. public boolean gotoPrev() {  
  28.     if (isEmpty()){  
  29.         return false;  
  30.     }  
  31.     if (cur == head){  
  32.         return true;  
  33.     }  
  34.     cur = cur.pre;  
  35.     return true;  
  36. }  

如上操作均为改变cur指针位置,只需要注意空数组,满数组等特殊情况即可。时间复杂度为O(1)  。

  1. public char getCursor() {  
  2.     return cur.element;  
  3. }  

返回cur指针当前元素即可,时间复杂度为O(1)  。

  1. public void showStructure() {  
  2.     if(isEmpty()){  
  3.         System.out.printf("Empty list -1%n");  
  4.         return;  
  5.     }  
  6.     DList tem = head;  
  7.     while (tem.next != null){  
  8.         System.out.printf("%c ",tem.element);  
  9.         tem = tem.next;  
  10.     }  
  11.     cursor = getIntCursor();  
  12.     System.out.printf("%d%n",cursor);  
  13. }  

与单向链表相似,不再赘述,时间复杂度为O(n)。


通过上述描述,时间复杂度整理成如下表格:

以我现在的角度来看,我感觉当时写的时间复杂度有问题!

测试:

根据题目要求,编写了测试类(见附录),下面就关键代码进行说明:

  1. switch (tem){  
  2.     case '+':  
  3.         tem = row.charAt(pivot++);  
  4.         list.insert(tem);  
  5.         break;  
  6.     case '-':  
  7.         list.remove();  
  8.         break;  
  9.     case '=':  
  10.         tem = row.charAt(pivot++);  
  11.         list.replace(tem);  
  12.         break;  
  13.     case '#':  
  14.         list.gotoBeginning();  
  15.         break;  
  16.     case '*':  
  17.         list.gotoEnd();  
  18.         break;  
  19.     case '>':  
  20.         list.gotoNext();  
  21.         break;  
  22.     case '<':  
  23.         list.gotoPrev();  
  24.         break;  
  25.     case '~':  
  26.         list.clear();  
  27.         break;  
  28.     default:  
  29.         break;  
  30. }

这是测试类最关键的代码,均按照题目要求进行相应的操作,这里的tem代表读取txt文件中的单个字符。

  1. Scanner in = new Scanner(new File("src/test.txt"));  
  2. Scanner in2 = new Scanner(new File("src/list_result.txt"));  

读取相应文件,一边后面的操作和校对答案。

  1. myAns = list.toString(); 

myAns为字符串,由于showStructure无返回值,不适合大量校准答案,因此我在顺序数组,单向链表,双向链表都重写了toString方法,这样子可以返回String类型,适合校准答案,返回的字符串为showStructure输出的字符串。

  1. boolean equals = myAns.strip().equals(ans.strip());  

这里使用了strip()方法,处理字符串后面的空格和换行符。

测试结果:

  1. 经检验测试结果和标准答案:true  
  2. 经检验测试结果和标准答案:true  
  3. 经检验测试结果和标准答案:true  

三种数据结构均为正确。

总结与收获:

通过上面三种数据结构的编写,我充分理解了顺序数组,单向链表和双向链表的构成,具体实现代码和时间空间的优缺点。

其中最让我感到印象深刻的就是单向链表的哑节点技术的应用,如果让没有听课的我进行单向链表的实现可能就不会采用哑节点技术,这将导致单向链表的删除操作的时间复杂度增加到O(n),这从性能的变化来讲是十分差劲的,因此一个小小的编程思想的影响导致时间复杂度大大降低,让我印象深刻。但是,我也注意到了,当我为了实现哑节点,增加了不少常系数时间的判断,这可能在数据量较少的情况下不如不使用哑节点。

然后,我还想说,双向链表的设计存在十分不足,我没有使用任何技巧,完全采用了个人的理解,这是因为作业的时间紧迫导致的,我现在想来也许可以增加两个无用的节点,大大简化判断流程和代码编写,希望未来有时间可以实现。

 

任务 2:栈和递归之间的关系

题目:略

1、使用递归思想,编写一个函数 permutationByRecursion,该函数用来生成给定的字符

串的全排列结果。

数据说明:

  1. static String str;  
  2. static char[] res; 

str为录入的字符串,但是不方便处理,更改其中的字符。

res为结果字符数组,因为是字符数组方便输出,更改字符,交换字符。

算法说明:

  1. res = new char[str.length()];  
  2. for(int i = 0;i<str.length();i++){  
  3.     res[i] = str.charAt(i);  
  4. }  

把字符串转换为字符数组,方便后续操作。

  1. public static void permutationByRecursion(int left,int right){  
  2.     if (left == right){  
  3.         System.out.print(res);  
  4.         System.out.print(" ");  
  5.     }  
  6.     for(int i=left;i<=right;i++){  
  7.         swap(res,left,i);  
  8.            //进入递归  
  9.         permutationByRecursion(left+1,right);  
  10.         swap(res,left,i);  
  11.     }  
  12. }  

1、基准情况就是当left == right,这个时候输出res,即一种情况。

2、输入时left=0,right=数组长度-1,因此第一次的for循环作用就是遍历数组,这保证了后面输出结果时不遗漏。每次操作如下:将i与left交换,然后再将剩下的left+1到right递归全排序,递归完成后再交换回来。在递归时会往基准情况靠近,因此避免了死递归,而且当到达基准情况时就会输出一种不重复全排序的情况,这是因为递归完成交换回来的操作。

3、全排序的时间复杂度明显为O(n!),而且无任何优化空间。

测试结果:

1、测试用例"abd",结果如下:

acd adc cad cda dca dac

2、测试用例"abcde",结果如下:

abcde abced abdce abdec abedc abecd acbde acbed acdbe acdeb acedb acebd adcbe adceb adbce adbec adebc adecb aecdb aecbd aedcb aedbc aebdc aebcd bacde baced badce badec baedc baecd bcade bcaed bcdae bcdea bceda bcead bdcae bdcea bdace bdaec bdeac bdeca becda becad bedca bedac beadc beacd cbade cbaed cbdae cbdea cbeda cbead cabde cabed cadbe cadeb caedb caebd cdabe cdaeb cdbae cdbea cdeba cdeab ceadb ceabd cedab cedba cebda cebad dbcae dbcea dbace dbaec dbeac dbeca dcbae dcbea dcabe dcaeb dceab dceba dacbe daceb dabce dabec daebc daecb decab decba deacb deabc debac debca ebcda ebcad ebdca ebdac ebadc ebacd ecbda ecbad ecdba ecdab ecadb ecabd edcba edcab edbca edbac edabc edacb eacdb eacbd eadcb eadbc eabdc eabcd

2、使用栈数据结构,将1中编写的算法转换成非递归函数

分析:本题与上课讲的实例汉诺塔基本一致,上课讲的汉诺塔是第一步将A柱上的n-1个盘子借助C柱移向B柱,第二步将A柱上仅剩的最后一个盘子移向C柱,第三步将B柱上的n-1个盘子借助A柱移向C柱,当改为栈结构时,需要再创建一个辅助类。但是,由于本题的特殊性,即字符串的全排序就是数字的全排序,可以进一步转化为数组下标的全排序,这样省去了创建一个类的工作,下面介绍“取巧”做法。

数据结构:

由于题目要求,我们创建了属于自己的栈:

  1. public class MyStack {  
  2.     public int[] listArr;  
  3.     private int tail = -1;//不仅是指向尾部的指针,也代表了元素大小  
  4.     public MyStack()  
  5.     public MyStack(int MAX)  
  6.     public void push(int t)  
  7.     public int pop()  
  8.     public boolean isHas(int x  
  9.     public boolean isEmpty()  
  10.     public void printAns(String s)  
  11. }  

具体的实现过程不再给出,详细的实现过程可以查看附录代码,我详细说明一下变量含义和方法参数及返回值和作用。

1、变量。有int[] listArr这个是数组,用来存储数据,充当栈。int tail如注释所描述,不赘述。

2、各个方法。pop是出栈并且返回整数,push是入栈,isHas是判断栈中是否有参数x,isEmpty是判断栈是否为空,空返回true,反之。printAns是根据栈中的数字按照不同顺序输出字符串s。

算法设计:

下面给出核心代码:

  1. while (!myStack.isEmpty()){  
  2.     int i = myStack.pop() + 1;//加一是为了与其位置匹配  
  3.     while (i < s.length()){  
  4.         if (!myStack.isHas(i)){  
  5.             myStack.push(i);  
  6.             //寻找未进栈的元素进栈  
  7.             for (int j = 0; j < s.length(); j++){  
  8.                 if (!myStack.isHas(j)){  
  9.                     myStack.push(j);  
  10.                 }  
  11.             }  
  12.             myStack.printAns(s);  
  13.             break;  
  14.         }  
  15.         i++;  
  16.     }  
  17. }  

这是最关键的代码段,其核心作用就是将栈中数字的排序从小到大改为从大到小,而且每当出现一种新的排序时就输出字符串。

现在来具体讲解。

1、出栈元素,要加1是为了与其位置匹配。

2、进行循环,判断栈中是否含有i,若不含有则压入栈,注意我们虽然压入的都是i,但是i已经进行了+1操作,所以实现了从大到小的变换。接着,寻找未进栈的元素并且将其压入栈,注意这里要从0到n,因为这样子保证了从小到大压入,保证了操作的一致性。当全部压入后,则找到了一个全新的排序,输出,停止循环。

3、若栈中含有i,则说明出栈元素前的栈中存在一个比出栈元素大一的元素(有点拗口),则通过不断地i++把这个i排除掉,然后进行下一次的while (!myStack.isEmpty())循环操作。

总的来说,该算法实现了数字排序从小到大改为从大到小。由于我们录入数据是0-n,因此在排序过程中一定实现了全排序。

测试:

测试类不再给出,较简单。

测试结果:

测试用例“abc”,结果如下:

abc acb bac bca cab cba

测试用例“abcd”,结果如下:

abcd abdc acbd acdb adbc adcb bacd badc bcad bcda bdac bdca cabd cadb cbad cbda cdab cdba dabc dacb dbac dbca dcab dcba

变形 1:当字符串中出现相同字符时,只给出完全不一样的排列组合

设计:数据设计,算法设计与1中的递归设计基本一致,只需要在递归之前加入相同字符不交换递归即可,如下代码。

  1. if (res[left]!=res[i]||i==left){  
  2.     swap(res,left,i);  
  3.     permutationByRecursion(left+1,right);  
  4.     swap(res,left,i);  
  5. }  

测试:

1、测试用例“aac”,结果如下:

aac aca caa

2、测试用例“aaaa”,结果如下:

aaaa

3、测试用例“aabc”,结果如下:

aabc aacb abac abca acba acab baac baca bcaa caba caab cbaa

(有些测试用例输出过大,附录和这里都不在给出,可以通过测试类测试)

变形 2:输出长度为 n 的字符串中取 k 个字符构成的所有全排列。

分析:因为在1递归中,直接定好了char[] res的长度,导致只能输出n个字符,而题目要求输出k个因此需要在后续进行修改,增加新的变量。同时,1中的递归思想和方法大体不变,只需要对具体实现过程进行小幅修改,改变递归基准条件,使其能取k个字符后输出而且保证是全排序。

数据设计:

  1. static String str;  
  2. static char[] strArr;  
  3. static char[] res;  

str还是录入的字符串

strArr是将录入的字符串转为字符数组

res和1递归中的res作用一致,不过长度不再为n,而为k

算法设计:

  1.     private static void permutationByRecursion(int k){  
  2. //        递归条件  
  3.         if (k==0){  
  4.             System.out.print(res);  
  5.             System.out.print(" ");  
  6.             return;  
  7.         }  
  8. //        把不重复字符加入(十分暴力^_^)  
  9.         for(char strArr:strArr){  
  10.             if (!has(res,strArr)){  
  11.                 res[res.length-k] = strArr;  
  12.             } else{  
  13.                 continue;  
  14.             }  
  15. //            进入递归  
  16.             permutationByRecursion(k-1);  
  17. //            重新置为表示字符  
  18.             res[res.length - k] = ' ';  
  19.         }  
  20.     }  

1、基准条件改为k==0,这与1递归中的left==right的设计思想是一模一样的;

2、第二步,把不重复的字符加入。has(res,strArr)这个函数是判断res字符数组中是否有与strArr字符一致的字符,若无,加入到res数组里面;若有,则忽略,继续。然后进入递归。最后再将其置为初始化的字符‘ ’。上述步骤与1递归中的先交换再递归再交换的核心思想是一模一样的,因此可以保证该算法的正确性,同时可以知道该算法的前置条件为一为无重复字符元素,二为‘ ’字符不参与排序。

3、总的来说,这个算法虽然具体实现过程相差1递归的程序有相差,但是,核心思想不变,都是先提取一个字符,让剩下的n-1个字符进行递归,当剩余元素为0时,达到基准情况返回一种全排序结果,而且由于for循环整个数组和递归完后的“善尾工作”——再初始化或者再交换,可以保证全排序的结果不重复不遗漏。

4、时间复杂度为题目中公式所示,证明略。

测试:

测试用例“abcd” 2 ,结果如下:

ab ac ad ba bc bd ca cb cd da db dc

测试用例“abcde” 4 结果如下:

abcd abce abdc abde abec abed acbd acbe acdb acde aceb aced adbc adbe adcb adce adeb adec aebc aebd aecb aecd aedb aedc bacd bace badc bade baec baed bcad bcae bcda bcde bcea bced bdac bdae bdca bdce bdea bdec beac bead beca becd beda bedc cabd cabe cadb cade caeb caed cbad cbae cbda cbde cbea cbed cdab cdae cdba cdbe cdea cdeb ceab cead ceba cebd ceda cedb dabc dabe dacb dace daeb daec dbac dbae dbca dbce dbea dbec dcab dcae dcba dcbe dcea dceb deab deac deba debc deca decb eabc eabd eacb eacd eadb eadc ebac ebad ebca ebcd ebda ebdc ecab ecad ecba ecbd ecda ecdb edab edac edba edbc edca edcb

有些用例的输出过大,附录和这里都不在给出,可以尝试使用附录的测试类测试。

总结与收获:

在本次任务中,我编写了字符串的全排序问题,并且进行相应的改善,这是十分有趣的。下面我对三次改善谈谈自己的收获。

首先,就是把递归改成了栈。在这一问题上,我花费了不小的力气,说实话,我上课听懂了汉诺塔,可后面自己写的时候,常常看着递归的代码想不出来怎么改成栈,不知道怎么组织类的结构来进行更改,因此我放弃了老师上课讲的汉诺塔改为栈的方法,当然我希望老师能把上课讲的汉诺塔改成栈的具体代码发给我,嘿嘿。言归正传,我在网上找到了更巧妙地改为栈的方法,加以自己的理解写出了如上代码,在编写过程中,我还看了几次网上的解释才理解通透,可以说这个递归改成栈是十分困难的,今后要多下功夫了。

然后是两次更改递归条件的问题。第一个主要判断是否相同,不相同再调用递归,就达到了问题要求,一样的输出只输出一次。第二个,由于一开始写程序就定死了输出个数,因此我按照相同的逻辑把具体实现过程进行了更改,改成了可以输出个数变化的情况。

任务 3:创建一个可自动调整空间大小的Queue 数据结构

题目:略

数据设计:

  1. private int maxSize = 2;  
  2. private int front = 0;  
  3. private int rear = 0;  
  4. private T[] listArray =(T[]) new Object[2]; 

下面对其变量进行说明。

maxSize为当前队列所能容纳的最多元素,这里需要说明因为采用了循环数组,因此能存储的元素数量总是小于maxSize,等于maxSize-1,这对于后面的程序编写会有一定的影响;front可以理解为队头指针,为了判断满队列,空队列,需要队头指针的前一位才是储存元素的首元素;

rear可以理解为队尾指针;

listArray就是数组,大小初始化为2。

算法设计:

  1. public ResizingQueue(){}   

构造方法,无需指定大小。

  1. public void enqueue(T element) throws IllegalArgumentException{  
  2.     if (element == null){  
  3.         throw new IllegalArgumentException();  
  4.     }  
  5.     if (isExpand()){  
  6.           expand()方法改变了大小,改变了front,rear,maxSize数值  
  7.         listArray = expand(maxSize,(maxSize-1)*2+1);  
  8.     }  
  9.     rear = (rear+1)%maxSize;  
  10.     listArray[rear] = element;  
  11. }  

enqueue方法将元素 element入队,如果队列满,则需要完成空间大小的调整。使用isExpand()方法判断是否为队列满,如果满队列,使用expand方法进行扩充,其中expand的两个参数为变换前的最大容量和变化后的最大容量,该方法返回T数组。扩充完毕后,再进行入队操作。

  1. public T dequeue() throws NoSuchElementException{  
  2.     if (isEmpty()){  
  3.         throw new NoSuchElementException();  
  4.     }  
  5.     listArray[front] = null;  
  6.     front = (front+1)%maxSize;  
  7.     T res =listArray[front];  
  8.     if (isShrink()){  
  9.         listArray = shrink(maxSize,(maxSize-1)/2);  
  10.     }  
  11.     return res;  
  12. }

dequeue()从队列中将队头元素删除并返回,如果队列的元素个数是当前容量的 1/4,那么完成空间大小的调整。首先进行空数组判断,若为空数组,抛出NoSuchElementException。若不为空数组,则先进行删除,再判断是否需要收缩数组。isShrink()判断队列的元素个数是当前容量的 1/4,若满足,则调用shrink方法,shrink方法的第一个参数为当前最大容量,后一个为收缩完成后的最大容量,返回值为T数组。

  1. public int size(){  
  2.     if (rear>=front){  
  3.         return rear-front;  
  4.     }  
  5.     return maxSize-front+rear;  
  6. }  

由于使用了循环数组,因此通过front和rear的两种情况的相对位置即可判断数组容量。

  1. public String toString() {  
  2.     String res = "";  
  3.     res += "[";  
  4.       不大于20的情况  
  5.     if (this.size()<=20){  
  6.         if (rear>=front){  
  7.             for (int i = front+1;i<=rear;i++){  
  8.                 res = res + listArray[i] + " ";  
  9.             }  
  10.         }  
  11.         else {  
  12.             for (int i = front+1;i<maxSize;i++){  
  13.                 res = res + listArray[i] + " ";  
  14.             }  
  15.             for (int i = 0;i<=rear;i++){  
  16.                 res = res + listArray[i] + " ";  
  17.             }  
  18.         }  
  19.     }  
  20.       大于20的情况  
  21.     else {  
  22.         int tem = (front+1)%maxSize;  
  23.         int count = 0;  
  24.           去前五个元素  
  25.         do{  
  26.             res = res + listArray[tem] + " ";  
  27.             tem = (tem+1)%maxSize;  
  28.             count++;  
  29.         }  
  30.         while (count<5);  
  31.         res += " ... ";  
  32.           取后五个元素  
  33.         while (count<this.size()-5){  
  34.             tem = (tem+1)%maxSize;  
  35.             count++;  
  36.         }  
  37.         while (count<this.size()){  
  38.             res = res + listArray[tem] + " ";  
  39.             tem = (tem+1)%maxSize;  
  40.             count++;  
  41.         }  
  42.     }  
  43.     res = res.strip()+"]";  
  44.     res += "\nelements: " + this.size() + " size:"+(this.maxSize-1);  
  45.     return res;  
  46. }  

虽然看上去比较“冗杂”,但都是针对不同情况的重复性的工作,按照题目要求分为不大于20的表示方式和大于20的表示方式,由于采用了循环数组,因此必须判断rear和front的相对位置。

测试:

编写了测试类(见附录),下面对关键代码进行说明:

  1. Scanner in = new Scanner(new File("src/test5000.txt"));  
  2. Scanner in2 = new Scanner(new File("src/ result5000.txt")); 

读取txt文件,便于后续操作。

  1. if (in.hasNextInt()){  
  2.     nextInt = in.nextInt();  
  3. //  System.out.printf("读取到的数字为:%d",nextInt);  
  4.     resizingQueue.enqueue(nextInt);  
  5. }

这是当读取到数字时,采用入队操作。

  1. if (nextChar == '-'){  
  2.     resizingQueue.dequeue();  
  3. }  
  4. if (nextChar == '?'){  
  5.     System.out.println(resizingQueue.toString());  
  6.     String tem1 = in2.nextLine();  
  7.     String tem2 = in2.nextLine();  
  8.     String res = tem1 + "\n" + tem2;  
  9.     System.out.println("res为:"+res);  
  10.     boolean temVertify = res.strip().equals(resizingQueue.toString().strip());  
  11.     System.out.println("比较结果为:"+temVertify);  
  12.     vertify = vertify && temVertify;  
  13. }  

当读取到’-’时,使用出队操作。当读取到’?’,需要调用toString方法,同时与结果进行比较。

测试结果:

  1. 经检验输出的字符串与结果符合判定:true  
  2. 经检验输出的字符串与结果符合判定:true  

result1000.txt result5000.txt分别调用测试类,结果如上。

总结与收获:

队列的编写有了前面顺序数组,单向链表,双向链表代码编写的经验,写起来速度了不少,遇到的困难和小问题都在调试的过程中解决了,总体来说,编程思想和前面三个有相似之处。

任务 4:基数排序

题目: 略

1、当数据序列是整数类型的数据的时候,数据序列中每个数据的位数不要求等宽

数据设计:

  1. static ResizingQueue[] resizingQueue = new ResizingQueue[10];  

数组大小为10是因为数字是0-9。

算法设计:

  1.     static void sort(int[] arr,int len){  
  2. //        初始化队列  
  3.         for(int i=0;i<resizingQueue.length;i++){  
  4.             resizingQueue[i] = new ResizingQueue<Integer>();  
  5.         }  
  6. //        变量+初始化  
  7.         boolean flag = true;  
  8.         int modNum = 0;  
  9.         int tem=0;  
  10. //        一位一位操作,直到最长的数字结束  
  11.         while (flag){  
  12.             modNum++;  
  13. //            入队,将数组数字按照顺序入队  
  14.             for (int i=0;i<len;i++){  
  15.                 int pivot = mod(arr[i],modNum);  
  16.                 tem = Math.max(tem,pivot);  
  17.                 resizingQueue[pivot].enqueue(arr[i]);  
  18.                 flag = (tem != 0);  
  19.             }  
  20.             tem = 0;  
  21.             int arrPivot = 0;  
  22. //            出队,重新给数组赋值  
  23.             for (int i=0;i<resizingQueue.length;i++){  
  24.                 while (!resizingQueue[i].isEmpty()){  
  25.                    arr[arrPivot++] = (int)resizingQueue[i].dequeue()
  26.                 }  
  27.             }  
  28.         }  
  29. //        输出  
  30.         for (int i=0;i<len;i++){  
  31.             System.out.printf("%d ",arr[i]);  
  32.         }  
  33.     } 

注释已经有部分讲解,下面进行更详细的讲解。

1、sort方法的第一个参数为数组,第二个参数为数组的长度。

2、定义了几个变量,进行说明。flag判断是否继续进行排序操作,当所有数字取模均为0时就不再继续;modNum记录取模次数,为mod方法的第二个参数;tem仅为辅助变量,改变flag的值。

3、入队操作,按照数字的每位数取模后的大小进入相应的队列数组中。

4、出队操作,按照顺序从队列数组的第0位到第9位出队,由于是队列,遵守先进先出原则,因此满足先后顺序。

5、当所有数字取模均为0时,数组有序,完成排序。由于数字量远远大于桶的数量(队列数组大小),因此时间复杂度为O(n)。

测试:

编写了主函数作为测试(见附录),主要思想为把文件中数字放入数组中,再调用sort方法。下面进行主要代码分析。

  1. while (in.hasNextInt()){  
  2.     int tem = in.nextInt();  
  3.     System.out.println(tem);  
  4.     arr[pivot++] = tem;  
  5. }  

当存在下一个数字时,存入数组。记录位置。

测试结果:

见附录

2、当数据序列是字符串类型的数据的时候,数据序列中每个字符串都是等宽的

数据设计:

  1. static ResizingQueue[] resizingQueue = new ResizingQueue[26];  

数组大小为26是因为字母是a-z。由于题目未明确说明,我把大写字母和小写字母视为一致。

算法设计:

  1.     static void sort(String[] arr,int len){  
  2. //        初始化队列数组  
  3.         for(int i=0;i<resizingQueue.length;i++){  
  4.             resizingQueue[i] = new ResizingQueue<String>();  
  5.         }  
  6. //        因为等宽,所以取第一个字符串长度作为长度  
  7.         int stringLen = arr[0].length();  
  8.         int tem=0;  
  9.         for (int k=0;k<stringLen;k++){  
  10. //            入队操作  
  11.             for (int i=0;i<len;i++){  
  12.                 int pivot = arr[i].toLowerCase().charAt(stringLen-k-1)-'a';  
  13.                 resizingQueue[pivot].enqueue(arr[i]);  
  14.             }  
  15.             tem = 0;  
  16.             int arrPivot = 0;  
  17. //            出队操作  
  18.             for (int i=0;i<resizingQueue.length;i++){  
  19.                 while (!resizingQueue[i].isEmpty()){  
  20.                     arr[arrPivot++] = (String) resizingQueue[i].dequeue();  
  21.                 }  
  22.             }  
  23.         }  
  24.         for (int i=0;i<len;i++){  
  25.             System.out.printf(arr[i]+" ");  
  26.         }  
  27.     }

sort方法的参数,步骤和核心思想与数字的基数排序基本一致,不再赘述,下面讲几个相异点:

1、由于字符串长度一致,因此不需要数字基数排序中的flag。

2、由于不区分大小写字母,因此先取小写(toLowerCase()的方法)再比较。

3、数字是依靠模运算取位数,字符串是运用charAt()方法取字符串的单个字符。

测试:

       编写了主函数作为测试,核心思想为把文件中字符串放入数组中,再调用sort方法。下面进行关键代码分析。

  1. while (in.hasNext()){  
  2.     arr[pivot++] = in.next();  
  3. }  

当存在下一个字符串时,把字符串存入数组,pivot记录存入下标。

测试结果:

见附录

总结与收获:

基数排序还是基于桶排序,按照从低位到高位依次桶排序,最后输出结果即可,可以注意到桶的个数,位数的个数,数据量共同决定的时间复杂度,这与课上学习的一致,强化了学习结果。

附录

任务一

  1. public class SeqList implements List{  
  2.     /*        这个是顺序数组实现的数据结构     */  
  3.     private int MAXLEN;  
  4.     private char[] seqList = null;  
  5.     private int cursor = -1;  
  6.     private int tail = 0;  
  7.   
  8. //  构造函数  
  9.     public SeqList(){  
  10.         this(10000);  
  11.     }  
  12.     public SeqList(int MAXLEN){  
  13.         this.MAXLEN = MAXLEN;  
  14.         seqList = new char[MAXLEN];  
  15.     }  
  16.   
  17.     @Override  
  18.     public void insert(char newElement) {  
  19.         //  after the cursor  
  20.         if (tail>=MAXLEN){  
  21.             return;  
  22.         }  
  23. //        空数组插入  
  24.         if (tail==0){  
  25.             cursor++;  
  26.             seqList[cursor] = newElement;  
  27.             tail++;  
  28.             return;  
  29.         }  
  30. //        非空插入  
  31.         for (int i=tail-1;i>cursor;i--){  
  32.             seqList[i+1] = seqList[i];  
  33.         }  
  34.         cursor++;  
  35.         seqList[cursor] = newElement;  
  36.         tail++;  
  37.     }  
  38.   
  39.     @Override  
  40.     public void remove() {  
  41.         tail--;  
  42.         //        空数组  
  43.         if (tail <= 0){  
  44.             tail = 0;  
  45.             cursor = -1;  
  46.             seqList = new char[MAXLEN];  
  47.             return;  
  48.         }  
  49.         for(int i=cursor;i<tail;i++){  
  50.             seqList[i] = seqList[i+1];  
  51.         }  
  52.         cursor = cursor%tail;  
  53.     }  
  54.   
  55.     @Override  
  56.     public void replace(char newElement) {  
  57.         if (cursor < 0){  
  58.             return;  
  59.         }  
  60.         seqList[cursor] = newElement;  
  61.     }  
  62.   
  63.     @Override  
  64.     public void clear() {  
  65.         seqList = new char[MAXLEN];  
  66.         cursor = -1;  
  67.         tail = 0;  
  68.     }  
  69.   
  70.     @Override  
  71.     public boolean isEmpty() {  
  72.         if (tail == 0){  
  73.             return true;  
  74.         }  
  75.         return false;  
  76.     }  
  77.   
  78.     @Override  
  79.     public boolean isFull() {  
  80.         if (tail == seqList.length){  
  81.             return true;  
  82.         }  
  83.         return false;  
  84.     }  
  85.   
  86.     @Override  
  87.     public boolean gotoBeginning() {  
  88.         if (this.isEmpty()){  
  89.             return false;  
  90.         }  
  91.         cursor = 0;  
  92.         return true;  
  93.     }  
  94.   
  95.     @Override  
  96.     public boolean gotoEnd() {  
  97.         if (this.isEmpty()){  
  98.             return false;  
  99.         }  
  100.         cursor = tail-1;  
  101.         return true;  
  102.     }  
  103.   
  104.     @Override  
  105.     public boolean gotoNext() {  
  106.         if (cursor == tail-1){  
  107.             return false;  
  108.         }  
  109.         cursor++;  
  110.         return true;  
  111.     }  
  112.   
  113.     @Override  
  114.     public boolean gotoPrev() {  
  115.         if (cursor <= 0){  
  116.             return false;  
  117.         }  
  118.         cursor--;  
  119.         return true;  
  120.     }  
  121.   
  122.     @Override  
  123.     public char getCursor() {  
  124.         return seqList[cursor];  
  125.     }  
  126.   
  127.     @Override  
  128.     public void showStructure(){  
  129.         if (tail == 0){  
  130.             System.out.printf("Empty list -1%n");  
  131.             return;  
  132.         }  
  133.         for(int i=0;i<tail;i++){  
  134.             System.out.printf("%c ",seqList[i]);  
  135.         }  
  136.         System.out.printf("%d%n",cursor);  
  137.     }  
  138.   
  139.     @Override  
  140.     public String toString() {  
  141.         return myResult();  
  142.     }  
  143.   
  144.     public String myResult(){  
  145.         String myAns = "";  
  146.         if (tail == 0){  
  147.             myAns = "Empty list -1 ";  
  148.             return myAns;  
  149.         }  
  150.         for(int i=0;i<tail;i++){  
  151.             myAns += seqList[i];  
  152.             myAns += " ";  
  153.         }  
  154.         myAns += cursor;  
  155.         myAns += " ";  
  156.         return myAns;  
  157.     }  
  158. }  

  1. public class LList implements List {  
  2.   
  3. //    成员变量  
  4.     public char element = ' ';//选择一个没有意义的字符作为初始化字符  
  5.     public LList next = null;  
  6.   
  7. //    类变量  
  8.     static public int cursor = -1;   //记录当前元素的位置的前一个位置  
  9.     static public LList dummy = new LList();  
  10.     static public LList head = dummy;//    初始化为哑节点  
  11.     static public LList cur = dummy;//指向当前元素的指针,初始化为哑节点  
  12.   
  13.     public LList(){  
  14.   
  15.     }  
  16.     @Override  
  17.     public void insert(char newElement) {  
  18.         LList tem = new LList();  
  19.         tem.element = newElement;  
  20. //        判断是否为空,是的话直接插入  
  21.         if (isEmpty()){  
  22.             cur.next = tem;  
  23.             return;  
  24.         }  
  25. //        判断是否在尾部,是的话直接插入并且转化cur  
  26.         if (isFull()){  
  27.             cur.next.next = tem;  
  28.             cur = cur.next;  
  29.             return;  
  30.         }  
  31. //        后面有元素  
  32.         tem.next = cur.next.next;  
  33.         cur.next.next = tem;  
  34.         cur = cur.next;  
  35.     }  
  36.   
  37.     @Override  
  38.     public void remove() {  
  39.         if (isEmpty()){  
  40.             return;  
  41.         }  
  42.         if (isFull()){  
  43.             cur.next = null;  
  44.             cur = dummy;  
  45.             return;  
  46.         }  
  47.         cur.next = cur.next.next;  
  48.     }  
  49.   
  50.     @Override  
  51.     public void replace(char newElement) {  
  52.         if (cur.next == null){  
  53.             return;  
  54.         }  
  55.         cur.next.element = newElement;  
  56.     }  
  57.   
  58.     @Override  
  59.     public void clear() {  
  60.         cur =dummy;  
  61.         dummy.next = null;  
  62.     }  
  63.   
  64.     @Override  
  65.     public boolean isEmpty() {  
  66.         return head.next == null;  
  67.     }  
  68.   
  69.     @Override  
  70.     public boolean isFull() {  
  71.         return cur.next.next == null;  
  72.     }  
  73.   
  74.     @Override  
  75.     public boolean gotoBeginning() {  
  76.         if (isEmpty()){  
  77.             return false;  
  78.         }  
  79.         cur = head;  
  80.         return true;  
  81.     }  
  82.   
  83.     @Override  
  84.     public boolean gotoEnd() {  
  85.         if (isEmpty()){  
  86.             return false;  
  87.         }  
  88.         while (cur.next.next != null){  
  89.             cur = cur.next;  
  90.         }  
  91.         return true;  
  92.     }  
  93.   
  94.     @Override  
  95.     public boolean gotoNext() {  
  96.         if (isEmpty()){  
  97.             return false;  
  98.         }  
  99.         if (isFull()){  
  100.             return false;  
  101.         }  
  102.         cur = cur.next;  
  103.         return true;  
  104.     }  
  105.   
  106.     @Override  
  107.     public boolean gotoPrev() {  
  108.         if (isEmpty()){  
  109.             return false;  
  110.         }  
  111.         if (cur == head){  
  112.             return true;  
  113.         }  
  114.         LList tem = head;  
  115.         while (tem.next != cur){  
  116.             tem = tem.next;  
  117.         }  
  118.         cur = tem;  
  119.         return true;  
  120.     }  
  121.   
  122.     @Override  
  123.     public char getCursor() {  
  124.         return cur.next.element;  
  125.     }  
  126.   
  127.     @Override  
  128.     public void showStructure() {  
  129.         if(isEmpty()){  
  130.             System.out.printf("Empty list -1%n");  
  131.             return;  
  132.         }  
  133.         LList tem = head.next;  
  134.         while (tem.next != null){  
  135.             System.out.printf("%c ",tem.element);  
  136.             tem = tem.next;  
  137.         }  
  138.         cursor = getIntCursor();  
  139.         System.out.printf("%c %d%n",tem.element,cursor);  
  140.     }  
  141.   
  142.     private String myRes(){  
  143.         if(isEmpty()){  
  144.             return "Empty list -1";  
  145.         }  
  146.         String myRes = "";  
  147.         LList tem = head.next;  
  148.         while (tem.next != null){  
  149.             myRes = myRes + " " + tem.element;  
  150.             tem = tem.next;  
  151.         }  
  152.         cursor = getIntCursor();  
  153.         myRes= myRes+" "+tem.element+" "+cursor;  
  154.         return myRes;  
  155.     }  
  156.   
  157.     @Override  
  158.     public String toString() {  
  159.         return myRes();  
  160.     }  
  161.   
  162.     private int getIntCursor(){  
  163.         if (isEmpty()){  
  164.             return -1;  
  165.         }  
  166.         LList tem = head;  
  167.         int intCursor = 0;  
  168.         while (tem.next!=cur.next){  
  169.             intCursor++;  
  170.             tem = tem.next;  
  171.         }  
  172.         return intCursor;  
  173.     }  
  174. }  

  1. public class DList implements List {  
  2.     //    成员变量  
  3.     public char element = ' ';//选择一个没有意义的字符作为初始化字符  
  4.     public DList next = null;  
  5.     public DList pre = null;  
  6.   
  7.     //    类变量  
  8.     static public int cursor = -1;   //记录当前元素的位置,无需提前一个位置  
  9.     static public DList head = null;//    初始化  
  10.     static public DList cur = head;//指向当前元素的指针  
  11.   
  12.     public DList(){  
  13.     }  
  14.     @Override  
  15.     public void insert(char newElement) {  
  16.         DList tem = new DList();  
  17.         tem.element = newElement;  
  18. //        判断是否为空,是的话开始创建  
  19.         if (isEmpty()){  
  20.             cur = tem;  
  21.             head =cur;  
  22.             return;  
  23.         }  
  24.         tem.next = cur.next;  
  25.         tem.pre = cur;  
  26.         cur.next = tem;  
  27.         if (tem.next!=null){  
  28.             tem.next.pre = tem;  
  29.         }  
  30.         cur = tem;  
  31.     }  
  32.   
  33.     @Override  
  34.     public void remove() {  
  35.         if (isEmpty()){  
  36.             return;  
  37.         }  
  38.         if (cur == head){  
  39.             cur = head.next;  
  40.             head = cur;  
  41.             return;  
  42.         }  
  43.         if (isFull()){  
  44.             cur.pre.next = null;  
  45.             cur = head;  
  46.             return;  
  47.         }  
  48.         cur.next.pre = cur.pre;  
  49.         cur = cur.next;  
  50.         cur.pre.next = cur;  
  51.     }  
  52.   
  53.     @Override  
  54.     public void replace(char newElement) {  
  55.         if (isEmpty()){  
  56.             return;  
  57.         }  
  58.         cur.element = newElement;  
  59.     }  
  60.   
  61.     @Override  
  62.     public void clear() {  
  63.         head = null;  
  64.         cur = head;  
  65.     }  
  66.   
  67.     @Override  
  68.     public boolean isEmpty() {  
  69.         return cur == null;  
  70.     }  
  71.   
  72.     @Override  
  73.     public boolean isFull() {  
  74.         return cur==null||cur.next==null;  
  75.     }  
  76.   
  77.     @Override  
  78.     public boolean gotoBeginning() {  
  79.         if (isEmpty()){  
  80.             return false;  
  81.         }  
  82.         cur = head;  
  83.         return true;  
  84.     }  
  85.   
  86.     @Override  
  87.     public boolean gotoEnd() {  
  88.         if (isEmpty()){  
  89.             return false;  
  90.         }  
  91.         while (cur.next != null){  
  92.             cur = cur.next;  
  93.         }  
  94.         return true;  
  95.     }  
  96.   
  97.     @Override  
  98.     public boolean gotoNext() {  
  99.         if (isEmpty()){  
  100.             return false;  
  101.         }  
  102.         if (isFull()){  
  103.             return false;  
  104.         }  
  105.         cur = cur.next;  
  106.         return true;  
  107.     }  
  108.   
  109.     @Override  
  110.     public boolean gotoPrev() {  
  111.         if (isEmpty()){  
  112.             return false;  
  113.         }  
  114.         if (cur == head){  
  115.             return true;  
  116.         }  
  117.         cur = cur.pre;  
  118.         return true;  
  119.     }  
  120.   
  121.     @Override  
  122.     public char getCursor() {  
  123.         return cur.element;  
  124.     }  
  125.   
  126.     @Override  
  127.     public void showStructure() {  
  128.         if(isEmpty()){  
  129.             System.out.printf("Empty list -1%n");  
  130.             return;  
  131.         }  
  132.         DList tem = head;  
  133.         while (tem.next != null){  
  134.             System.out.printf("%c ",tem.element);  
  135.             tem = tem.next;  
  136.         }  
  137.         cursor = getIntCursor();  
  138.         System.out.printf("%d%n",cursor);  
  139.     }  
  140.   
  141.     private String myRes(){  
  142.         if(isEmpty()){  
  143.             return "Empty list -1";  
  144.         }  
  145.         String myRes = "";  
  146.         DList tem = head;  
  147.         while (tem.next != null){  
  148.             myRes = myRes + " " + tem.element;  
  149.             tem = tem.next;  
  150.         }  
  151.         cursor = getIntCursor();  
  152.         myRes= myRes+" "+tem.element+" "+cursor;  
  153.         return myRes;  
  154.     }  
  155.   
  156.     @Override  
  157.     public String toString() {  
  158.         return myRes();  
  159.     }  
  160.   
  161.     private int getIntCursor(){  
  162.         if (isEmpty()){  
  163.             return -1;  
  164.         }  
  165.         DList tem = head;  
  166.         int intCursor = 0;  
  167.         while (tem != cur){  
  168.             intCursor++;  
  169.             tem = tem.next;  
  170.         }  
  171.         return intCursor;  
  172.     }  
  173. }  

  1. import java.io.File;  
  2. import java.io.FileNotFoundException;  
  3. import java.util.Scanner;  
  4.   
  5. public class ReadFile {  
  6.     public static void readFile() throws FileNotFoundException {  
  7. //        List list = new SeqList();  
  8. //        List list = new LList();  
  9.         List list = new DList();  
  10.         Scanner in = new Scanner(new File("src/test.txt"));  
  11.         Scanner in2 = new Scanner(new File("src/list_result.txt"));  
  12.         String row;  
  13.         String ans;  
  14.         String myAns;  
  15.         boolean vertify = true;  
  16.         while (in.hasNextLine() && in2.hasNextLine()){  
  17.             row = in.nextLine();  
  18.             ans = in2.nextLine();  
  19.             int pivot = 0;  
  20.             char tem;  
  21.             while(pivot!=row.length()){  
  22.                 tem = row.charAt(pivot++);  
  23.                 switch (tem){  
  24.                     case '+':  
  25.                         tem = row.charAt(pivot++);  
  26.                         list.insert(tem);  
  27.                         break;  
  28.                     case '-':  
  29.                         list.remove();  
  30.                         break;  
  31.                     case '=':  
  32.                         tem = row.charAt(pivot++);  
  33.                         list.replace(tem);  
  34.                         break;  
  35.                     case '#':  
  36.                         list.gotoBeginning();  
  37.                         break;  
  38.                     case '*':  
  39.                         list.gotoEnd();  
  40.                         break;  
  41.                     case '>':  
  42.                         list.gotoNext();  
  43.                         break;  
  44.                     case '<':  
  45.                         list.gotoPrev();  
  46.                         break;  
  47.                     case '~':  
  48.                         list.clear();  
  49.                         break;  
  50.                     default:  
  51.                         break;  
  52.                 }  
  53.             }  
  54.             myAns = list.toString();  
  55.             System.out.println(myAns.strip());  
  56.             System.out.println(ans.strip());  
  57.             boolean equals = myAns.strip().equals(ans.strip());  
  58.             System.out.println(equals);  
  59.             vertify = vertify&& equals;  
  60.         }  
  61.         System.out.printf("经检验测试结果和标准答案:%b",vertify);  
  62.     }  
  63.   
  64.     public static void main(String[] args) throws FileNotFoundException {  
  65.         readFile();  
  66.     }  
  67. }  

任务二

问题一第一问——递归版

  1. public class PermutationByRecursion {  
  2.     static String str;  
  3.     static char[] res;  
  4. //    初始化函数  
  5.     public static void permutationByRecursion(String s){  
  6.         str = s;  
  7.         res = new char[str.length()];  
  8.         for(int i = 0;i<str.length();i++){  
  9.             res[i] = str.charAt(i);  
  10.         }  
  11.         permutationByRecursion(0, res.length-1);  
  12.     }  
  13.     public static void permutationByRecursion(int left,int right){  
  14.         if (left == right){  
  15.             System.out.print(res);  
  16.             System.out.print(" ");  
  17.         }  
  18.         for(int i=left;i<=right;i++){  
  19.             swap(res,left,i);  
  20. //            进入递归  
  21.             permutationByRecursion(left+1,right);  
  22.             swap(res,left,i);  
  23.         }  
  24.     }  
  25. //交换方法  
  26.     private static void swap(char[] res,int left,int right){  
  27.         char temp = res[left];  
  28.         res[left] = res[right];  
  29.         res[right] = temp;  
  30.     }  
  31. }  

问题一栈版本

  1. public class MyStack {  
  2.     public int[] listArr;  
  3.     private int tail = -1;//不仅是指向尾部的指针,也代表了元素大小  
  4.     public MyStack(){  
  5.         this(10000);  
  6.     }  
  7.     public MyStack(int MAX){  
  8.         listArr = new int[MAX];  
  9.     }  
  10.     public void push(int t){  
  11.         listArr[++tail] = t;  
  12.     }  
  13.     public int pop(){  
  14.         return listArr[tail--];  
  15.     }  
  16.     public boolean isHas(int x){  
  17.         for (int i=0;i<=tail;i++){  
  18.             if (listArr[i]==x){  
  19.                 return true;  
  20.             }  
  21.         }  
  22.         return false;  
  23.     }  
  24.     public boolean isEmpty(){  
  25.         return tail==-1;  
  26.     }  
  27.     public int size(){  
  28.         return tail+1;  
  29.     }  
  30.     public void printAns(String s){  
  31.         for(int i=0;i<=tail;i++){  
  32.             System.out.printf("%c",s.charAt(listArr[i]));  
  33.         }  
  34.         System.out.printf(" ");  
  35.     }  
  36. }  

  1. public static void permutationByNoRecursion(String s){  
  2.     MyStack myStack = new MyStack();  
  3.     for (int i = 0; i < s.length(); i++){  
  4.         myStack.push(i);  
  5.     }  
  6.       从低到高排序输出  
  7.     myStack.printAns(s);  
  8.       开始循环  
  9.     while (!myStack.isEmpty()){  
  10.         int i = myStack.pop() + 1;//加一是为了与其位置匹配  
  11.         while (i < s.length()){  
  12.             if (!myStack.isHas(i)){  
  13.                 myStack.push(i);  
  14.                 //寻找未进栈的元素进栈  
  15.                 for (int j = 0; j < s.length(); j++){  
  16.                     if (!myStack.isHas(j)){  
  17.                         myStack.push(j);  
  18.                     }  
  19.                 }  
  20.                 myStack.printAns(s);  
  21.                 break;  
  22.             }  
  23.             i++;  
  24.         }  
  25.     }  
  26. }

问题二变形一

  1.     public static void permutationByRecursion(int left,int right){  
  2.         if (left == right){  
  3.             System.out.print(res);  
  4.             System.out.print(" ");  
  5.         }  
  6.         for(int i=left;i<=right;i++){  
  7. //            在递归前加入不重复的条件  
  8.             if (res[left]!=res[i]||i==left){  
  9.                 swap(res,left,i);  
  10.                 permutationByRecursion(left+1,right);  
  11.                 swap(res,left,i);  
  12.             }  
  13.         }  
  14.     }

问题二变形二

  1. public class PermutationByRecursion3 {  
  2.     static String str;  
  3.     static char[] strArr;  
  4.     static char[] res;  
  5.     public static void permutationByRecursion(String s,int k){  
  6.         str = s;  
  7.         strArr = new char[str.length()];  
  8.         res = new char[k];  
  9.         for(int i = 0;i<str.length();i++){  
  10.             strArr[i] = str.charAt(i);  
  11.         }  
  12. //        引入不会出现的字符作为区分符号‘ ’  
  13.         for(int i = 0;i<k;i++){  
  14.             res[i] = ' ';  
  15.         }  
  16.         permutationByRecursion(k);  
  17.     }  
  18.     private static void permutationByRecursion(int k){  
  19. //        递归条件  
  20.         if (k==0){  
  21.             System.out.print(res);  
  22.             System.out.print(" ");  
  23.             return;  
  24.         }  
  25. //        把不重复字符加入(十分暴力^_^)  
  26.         for(char strArr:strArr){  
  27.             if (!has(res,strArr)){  
  28.                 res[res.length-k] = strArr;  
  29.             } else{  
  30.                 continue;  
  31.             }  
  32. //            进入递归  
  33.             permutationByRecursion(k-1);  
  34. //            重新置为表示字符  
  35.             res[res.length - k] = ' ';  
  36.         }  
  37.     }  
  38. //    判断字符是否在字符数组内  
  39.     private static boolean has(char[] res,char s){  
  40.         for (char tem:res){  
  41.             if (tem == s){  
  42.                 return true;  
  43.             }  
  44.         }  
  45.         return false;  
  46.     }  
  47. }  

测试类(适用问题一问题二)

  1.     public static void main(String[] args) {  
  2. //        PermutationByRecursion.permutationByRecursion("abcde");  
  3. //        PermutationByRecursion2.permutationByRecursion("abcde");  
  4.         PermutationByRecursion3.permutationByRecursion("abcde",4);  
  5.     } 

任务三

  1. import java.util.NoSuchElementException;  
  2. import java.lang.IllegalArgumentException;  
  3.   
  4. public class ResizingQueue<T> {  
  5. //    成员变量外加初始化  
  6.     private int maxSize = 2;  
  7.     private int front = 0;  
  8.     private int rear = 0;  
  9.     private T[] listArray =(T[]) new Object[2];  
  10. //    无参构造方法  
  11.     public ResizingQueue(){}  
  12. //    入队操作,要注意空队列,满队列等情况  
  13.     public void enqueue(T element) throws IllegalArgumentException{  
  14.         if (element == null){  
  15.             throw new IllegalArgumentException();  
  16.         }  
  17.         if (isExpand()){  
  18. //            expand()方法改变了大小,改变了front,rear,maxSize数值  
  19.             listArray = expand(maxSize,(maxSize-1)*2+1);  
  20.         }  
  21.         rear = (rear+1)%maxSize;  
  22.         listArray[rear] = element;  
  23.     }  
  24.     public T dequeue() throws NoSuchElementException{  
  25.         if (isEmpty()){  
  26.             throw new NoSuchElementException();  
  27.         }  
  28.         listArray[front] = null;  
  29.         front = (front+1)%maxSize;  
  30.         T res =listArray[front];  
  31.         if (isShrink()){  
  32.             listArray = shrink(maxSize,(maxSize-1)/2);  
  33.         }  
  34.         return res;  
  35.     }  
  36.     public int size(){  
  37.         if (rear>=front){  
  38.             return rear-front;  
  39.         }  
  40.         return maxSize-front+rear;  
  41.     }  
  42.     public boolean isFull(){  
  43.         return front == (rear+1)%maxSize;  
  44.     }  
  45.     public boolean isEmpty(){  
  46.         return rear == front;  
  47.     }  
  48.     private boolean isExpand(){  
  49.         return isFull();  
  50.     }  
  51.     private boolean isShrink(){  
  52.         return size()<=(maxSize-1)/4;  
  53.     }  
  54.     private T[] expand(int eSize, int nSize){  
  55.         T[] tem = (T[]) new Object[nSize];  
  56.         int temPivot = 0;  
  57.         if (front>rear){  
  58.             for (int i=front;i<eSize;i++){  
  59.                 tem[temPivot++] = listArray[i];  
  60.             }  
  61.             for (int i=0;i<=rear;i++){  
  62.                 tem[temPivot++] = listArray[i];  
  63.             }  
  64.         }  
  65.         else {  
  66.             for (int i=front;i<=rear;i++){  
  67.                 tem[temPivot++] = listArray[i];  
  68.             }  
  69.         }  
  70.         maxSize = nSize;  
  71.         front = 0;  
  72.         rear = temPivot-1;  
  73.         return tem;  
  74.     }  
  75.     private T[] shrink(int eSize,int nSize){  
  76. //        需要对nSize进行判断  
  77.         nSize = (nSize<=3)?2:nSize;  
  78.         T[] tem = (T[]) new Object[nSize];  
  79.         int temPivot = 0;  
  80.         if (rear>=front){  
  81.             for (int i=front;i<=rear;i++){  
  82.                 tem[temPivot++] = listArray[i];  
  83.             }  
  84.         }  
  85.         else{  
  86.             for (int i=front;i<eSize;i++){  
  87.                 tem[temPivot++] = listArray[i];  
  88.             }  
  89.             for (int i=0;i<=rear;i++){  
  90.                 tem[temPivot++] = listArray[i];  
  91.             }  
  92.         }  
  93.         front = 0;  
  94.         rear = temPivot - 1;  
  95.         maxSize = nSize;  
  96.         return tem;  
  97.     }  
  98.     @Override  
  99.     public String toString() {  
  100.         String res = "";  
  101.         res += "[";  
  102. //        不大于20的情况  
  103.         if (this.size()<=20){  
  104.             if (rear>=front){  
  105.                 for (int i = front+1;i<=rear;i++){  
  106.                     res = res + listArray[i] + " ";  
  107.                 }  
  108.             }  
  109.             else {  
  110.                 for (int i = front+1;i<maxSize;i++){  
  111.                     res = res + listArray[i] + " ";  
  112.                 }  
  113.                 for (int i = 0;i<=rear;i++){  
  114.                     res = res + listArray[i] + " ";  
  115.                 }  
  116.             }  
  117.         }  
  118. //        大于20的情况  
  119.         else {  
  120.             int tem = (front+1)%maxSize;  
  121.             int count = 0;  
  122. //            去前五个元素  
  123.             do{  
  124.                 res = res + listArray[tem] + " ";  
  125.                 tem = (tem+1)%maxSize;  
  126.                 count++;  
  127.             }  
  128.             while (count<5);  
  129.             res += " ... ";  
  130. //            取后五个元素  
  131.             while (count<this.size()-5){  
  132.                 tem = (tem+1)%maxSize;  
  133.                 count++;  
  134.             }  
  135.             while (count<this.size()){  
  136.                 res = res + listArray[tem] + " ";  
  137.                 tem = (tem+1)%maxSize;  
  138.                 count++;  
  139.             }  
  140.         }  
  141.         res = res.strip()+"]";  
  142.         res += "\nelements: " + this.size() + " size:"+(this.maxSize-1);  
  143.         return res;  
  144.     }  
  145. }  

  1. import java.io.File;  
  2. import java.io.FileNotFoundException;  
  3. import java.util.Scanner;  
  4.   
  5. public class Test {  
  6.     public static void readFile() throws FileNotFoundException {  
  7. //        Scanner in = new Scanner(new File("src/test1000.txt"));  
  8. //        Scanner in2 = new Scanner(new File("src/result1000.txt")); 
  9.         Scanner in = new Scanner(new File("src/test5000.txt"));  
  10.         Scanner in2 = new Scanner(new File("src/result5000.txt"));  
  11.         ResizingQueue resizingQueue = new ResizingQueue<Integer>();  
  12.         int nextInt = 0;  
  13.         String nextString;  
  14.         boolean vertify = true;  
  15.         while (in.hasNext()){  
  16.             if (in.hasNextInt()){  
  17.                 nextInt = in.nextInt();  
  18. //                System.out.printf("读取到的数字为:%d",nextInt);  
  19.                 resizingQueue.enqueue(nextInt);  
  20.             }  
  21.             else{  
  22.                 nextString = in.next();  
  23.                 char nextChar;  
  24.                 int pivot=0;  
  25.                 while(pivot!=nextString.length()){  
  26.                     nextChar = nextString.charAt(pivot);  
  27.                     pivot++;  
  28.                     if (nextChar == '-'){  
  29.                         resizingQueue.dequeue();  
  30.                     }  
  31.                     if (nextChar == '?'){  
  32.                         System.out.println(resizingQueue.toString());  
  33.                         String tem1 = in2.nextLine();  
  34.                         String tem2 = in2.nextLine();  
  35.                         String res = tem1 + "\n" + tem2;  
  36.                         System.out.println("res为:"+res);  
  37.                         boolean temVertify = res.strip().equals(resizingQueue.toString().strip());  
  38.                         System.out.println("比较结果为:"+temVertify);  
  39.                         vertify = vertify && temVertify;  
  40.                     }  
  41. //                    System.out.printf("当前读取到的符号为:%c%n",nextChar);  
  42.                 }  
  43.             }  
  44. //            System.out.printf("当前队列最大容量:%d,当前队列容量:%d front为:%d rear为:%d%n",resizingQueue.getMaxSize(),resizingQueue.size(),resizingQueue.getFront(),resizingQueue.getRear());  
  45. //            System.out.printf(resizingQueue.toString()+"%n");  
  46.         }  
  47.         System.out.printf("经检验输出的字符串与结果符合判定:%b",vertify);  
  48.     }  
  49.   
  50.     public static void main(String[] args) throws FileNotFoundException {  
  51.         readFile();  
  52.     }  
  53. }  

任务四

  1. import java.io.File;  
  2. import java.io.FileNotFoundException;  
  3. import java.util.Scanner;  
  4.   
  5. public class RadixSortInt {  
  6.     static ResizingQueue[] resizingQueue = new ResizingQueue[10];  
  7. //    static int[] arr = {27,91,100,9,17,23,84,28,72,5,67,25};//仅为测试数组  
  8.     static void sort(int[] arr,int len){  
  9. //        初始化队列  
  10.         for(int i=0;i<resizingQueue.length;i++){  
  11.             resizingQueue[i] = new ResizingQueue<Integer>();  
  12.         }  
  13. //        变量+初始化  
  14.         boolean flag = true;  
  15.         int modNum = 0;  
  16.         int tem=0;  
  17. //        一位一位操作,直到最长的数字结束  
  18.         while (flag){  
  19.             modNum++;  
  20. //            入队,将数组数字按照顺序入队  
  21.             for (int i=0;i<len;i++){  
  22.                 int pivot = mod(arr[i],modNum);  
  23.                 tem = Math.max(tem,pivot);  
  24.                 resizingQueue[pivot].enqueue(arr[i]);  
  25.                 flag = (tem != 0);  
  26.             }  
  27.             tem = 0;  
  28.             int arrPivot = 0;  
  29. //            出队,重新给数组赋值  
  30.             for (int i=0;i<resizingQueue.length;i++){  
  31.                 while (!resizingQueue[i].isEmpty()){  
  32.                     arr[arrPivot++] = (int)resizingQueue[i].dequeue();  
  33.                 }  
  34.             }  
  35.         }  
  36. //        输出  
  37.         for (int i=0;i<len;i++){  
  38.             System.out.printf("%d ",arr[i]);  
  39.         }  
  40.     }  
  41.   
  42.     private static int mod(int num,int modNum){  
  43.         for(int i=0;i<modNum-1;i++){  
  44.             num = num/10;  
  45.         }  
  46.         return num%10;  
  47.     }  
  48.     public static void main(String[] args) throws FileNotFoundException {  
  49.         int[] arr = new int[10000];  
  50.         int pivot = 0;  
  51.         Scanner in = new Scanner(new File("src/radixSort1.txt"));  
  52.         while (in.hasNextInt()){  
  53.             int tem = in.nextInt();  
  54.             System.out.println(tem);   
  55.             arr[pivot++] = tem;  
  56.         }  
  57.         pivot--;  
  58.         sort(arr,pivot);  
  59.     }  
  60. }  

  1. import java.io.File;  
  2. import java.io.FileNotFoundException;  
  3. import java.util.Scanner;  
  4.   
  5. public class RadixSortString {  
  6.     static ResizingQueue[] resizingQueue = new ResizingQueue[26];  
  7. //    static String[] arr = {"Abc","bde","fad","abd","bef","fdd","abe"};//仅为测试数组  
  8.     static void sort(String[] arr,int len){  
  9. //        初始化队列数组  
  10.         for(int i=0;i<resizingQueue.length;i++){  
  11.             resizingQueue[i] = new ResizingQueue<String>();  
  12.         }  
  13. //        因为等宽,所以取第一个字符串长度作为长度  
  14.         int stringLen = arr[0].length();  
  15.         int tem=0;  
  16.         for (int k=0;k<stringLen;k++){  
  17. //            入队操作  
  18.             for (int i=0;i<len;i++){  
  19.                 int pivot = arr[i].toLowerCase().charAt(stringLen-k-1)-'a';  
  20.                 resizingQueue[pivot].enqueue(arr[i]);  
  21.             }  
  22.             tem = 0;  
  23.             int arrPivot = 0;  
  24. //            出队操作  
  25.             for (int i=0;i<resizingQueue.length;i++){  
  26.                 while (!resizingQueue[i].isEmpty()){  
  27.                     arr[arrPivot++] = (String) resizingQueue[i].dequeue();  
  28.                 }  
  29.             }  
  30.         }  
  31.         for (int i=0;i<len;i++){  
  32.             System.out.printf(arr[i]+" ");  
  33.         }  
  34.     }  
  35.     public static void main(String[] args) throws FileNotFoundException {  
  36.         String[] arr = new String[1000000];  
  37.         int pivot = 0;  
  38.         Scanner in = new Scanner(new File("src/radixSort2.txt"));  
  39.         while (in.hasNext()){  
  40.             arr[pivot++] = in.next();  
  41.         }  
  42.         pivot--;  
  43.         sort(arr,pivot);  
  44.     }  
  45. }  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1893371.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JSON字符串中获取一个指定字段的值

一、方式一&#xff0c;引用gson工具 测试报文&#xff1a; {"account":"yanxiaosheng","password":"123456" } 引入pom <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> <dependency><gr…

无人机测绘需要注意什么?

无人机测绘是一项高精度的测量工作&#xff0c;需要注意以下四点&#xff1a; 一、作业前准备&#xff1a;沟通相关事宜&#xff0c;现场勘查&#xff0c;飞行环境检查等&#xff1b; 二、航线规划与像控点布设&#xff1a;航线规划是任务规划的核心内容&#xff0c;需要综合…

【web APIs】快速上手Day05(Bom操作)

目录 Web APIs - 第5天笔记js组成window对象BOM定时器-延迟函数案例-5秒钟之后消失的广告 JS执行机制location对象案例-5秒钟之后跳转的页面 navigator对象histroy对象 本地存储&#xff08;今日重点&#xff09;localStorage&#xff08;重点&#xff09;sessionStorage&#…

交换机需要多大 buffer

有点违背直觉&#xff0c;但是真事儿&#xff0c;交换机过境的流越多&#xff0c;所需 buffer 越小&#xff0c;这是为什么&#xff1f; 范氏(范雅各布森&#xff0c;van jacobson)管道的 aimd 流建议 buffer_size 为 bdp&#xff0c;这很容易理解&#xff0c;因为 aimd 流最小…

适合弱电行业的项目管理软件!找企智汇软件!

随着科技的不断发展&#xff0c;弱电行业对于项目管理的需求日益增强。为满足这一需求&#xff0c;企智汇推出了一款专为弱电行业打造的工程项目管理系统。 企智汇弱电行业工程项目管理系统以其专业性、高效性和智能性&#xff0c;赢得了业界的广泛认可。该系统深入融合了弱电…

pycharm配置conda解释器

假如我新建了一个conda虚拟环境&#xff0c;名为python3.8

Ubuntu设置nacos开机以单机模式自启动

首先&#xff0c;需要安装jdk Ubuntu 安装JDK 创建Systemd服务单元文件 sudo vim /etc/systemd/system/nacos.service按i进入编辑模式&#xff0c;写入下面信息 [Unit] Descriptionnacos server Afternetwork.target[Service] Typeforking Environment"JAVA_HOME/opt/j…

AI 芯片之战:开启智能新时代的关键角逐

在科技发展的浪潮中&#xff0c;一场围绕 AI 芯片的激烈竞争正在全球范围内如火如荼地展开。多家巨头纷纷投身其中&#xff0c;使得这场混战已然进入白热化阶段。 AI 芯片&#xff0c;作为推动人工智能发展的核心硬件&#xff0c;其作用举足轻重。它能够高效地处理海量的数据&a…

IODD简介(1)

目录 1 IODD简介 1.1基本概述 1.2主要结构 1.3 数据类型 1 IODD简介 1.1基本概述 IODD&#xff08;IO Device Description&#xff09;是一组文件&#xff0c;该文件的作用&#xff1a;被工程工具用于PLC或主站。用于识别、配置、定义用于过程数据交换的数据结构参数化和…

软件测试常见的面试题(46道)

01、您所熟悉的测试用例设计方法都有哪些&#xff1f;请分别以具体的例子来说明这些方法在测试用例设计工作中的应用。 答&#xff1a;有黑盒和白盒两种测试种类&#xff0c;黑盒有等价类划分法&#xff0c;边界分析法&#xff0c;因果图法和错误猜测法。白盒有逻辑覆盖法&…

Android的高校讲座预约管理系-计算机毕业设计源码21634

摘 要 本系统旨在设计和实现一个基于Android平台的高校讲座预约管理系统&#xff0c;以提供管理员和普通用户便捷的讲座预约服务和全面的管理功能。系统将包括在线讲座发布、讲座预约、座位安排、签到信息记录等功能模块&#xff0c;旨在提高高校讲座活动的组织效率和用户体验。…

项目管理进阶之PDM

前言 项目管理进阶上新啦&#xff01; 今天博主带领大家认识一个项目经理必须掌握的好工具&#xff0c;好伙伴&#xff1a;PDM&#xff0c;即紧前关系绘图法。 那么接下来&#xff0c;先让我们一起安静下来&#xff0c;尝试做如下思考&#xff1a; 作为一个PM&#xff0c;如…

GPT的在线智能助考系统的设计-计算机毕业设计源码00068

摘要 随着人工智能技术的快速发展&#xff0c;智能辅助学习系统在教育领域日益受到重视。本研究旨在基于GPT构建在线智能助考系统&#xff0c;结合先进的自然语言处理技术&#xff0c;为用户提供智能问答、模拟考试、资源分享、交流论坛等功能&#xff0c;旨在提升用户学习效率…

深入Java腹地:序列化与反序列化的奥秘探索

在Java的广阔天地中&#xff0c;序列化与反序列化机制如同桥梁&#xff0c;连接着程序运行时的对象状态与持久化存储或网络传输之间的鸿沟。它们不仅是Java对象持久化、网络通信以及远程方法调用&#xff08;RMI&#xff09;等关键技术的基础&#xff0c;也是理解Java语言深层次…

vue中数组出现__ob__: Observer属性,导致不能正确使用问题解决

直接上图&#xff0c;如下图&#xff0c;数组中出现__ob__: Observer属性&#xff0c;导致无法取值。 解决方案为&#xff1a;JSON.parse(JSON.stringify(数组变量名))深拷贝数组&#xff0c;重新生成一个可枚举数组。 // 处理代码如let tempIds JSON.parse(JSON.stringify(i…

摄像机反求跟踪软件/插件 Mocha Pro 2024 v11.0.2 CE Win

AE/PR/OFX/达芬奇/AVX插件 | 摄像机反求跟踪软件Mocha Pro 2024 v11.0.2 CE Win-PR模板网 Mocha Pro 软件(插件)&#xff0c;用于平面运动跟踪、3D跟踪、动态观察、对象移除、图像稳定和PowerMesh有机扭曲跟踪等功能。整合了SynthEyes核心的3D跟踪算法&#xff0c;能够快速自动…

【有哪些GPU算力租用平台值得推荐】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

MySQL数据库数据迁徙:从本地到Linux服务器

"男人的浪漫&#xff0c;绝对是拥有一台属于自己的服务器" MySQL数据库数据迁徙就两步&#xff1a;本地导出和服务器导入。 本地导出 本地导出的时候&#xff0c;需要注意你的CMD命令行必须是以管理员身份运行。如果你的计算机找不到mysqldump这个命令&#xff0c;…

告别烦人的捆绑软件!一键获取真正纯净系统!

很多用户反映自己下载到的纯净版系统&#xff0c;总是携带着各种各样的捆绑软件&#xff0c;特别影响自己的操作体验感&#xff0c;想知道哪里才有真正纯净的操作系统&#xff1f;以下系统之家小编给大家分享做到真正纯净的电脑操作系统。这些系统经过优化&#xff0c;去除乱七…

无忧易售功能:刊登页面文本翻译,无缝对接全球买家

每一个词语&#xff0c;每一句话&#xff0c;都承载着产品的灵魂和品牌的故事&#xff0c;无忧易售的刊登页面文本翻译服务&#xff0c;一键操作即可将你的产品介绍、详情或广告文案转化为多语言版本&#xff0c;轻松管理&#xff0c;高效发布。 一、Allegro、OZON、Coupang、…