20182301 2019-2020-1「オブジェクト指向プログラミングとデータ構造」実験報告7
コース:「プログラミングとデータ構造」
クラス:1823
名:趙ペイ寧
学生ID:20182301の
実験先生:ジョニーの
実験日:2019年11月1日
必修/選択科目:必修
1.実験の内容
- 検索とソートは、クラスを定義し、実装linearSearch、選択ソートクラスメソッド、そして最後にテストを完了すること。試験は10未満、設計提出テストケース(正常、異常、境界、正のシーケンス、逆)が必要、実施例それらの学生IDを4に含まれるデータは、図の演算結果を提出します。
- あなたのコードのリファクタリング
(例えば:cn.edu.besti.cs1823.G2301)cn.edu.besti.cs1823(イニシャル+ 4桁の学生番号)パッケージにSorting.java Searching.javaにする。テストコードをテストパッケージを入れて、再コンパイル、コードを実行し、コンパイルに提出し、実行ショット(IDEA、コマンドライン) - 参考http://www.cnblogs.com/maybe2030/p/4715035.htmlは、提出され、スクリーンショットを検索し、テストの実行結果を追加するには、検索アルゴリズム検索アルゴリズムの多様性を学びます
- ヒルソート、ヒープソート、バイナリーツリーソート(少なくとも3):メソッドは、補助的な授業の実現について話ソート
テストアルゴリズム(通常、異常、国境)の実装、あなたが複数のソートアルゴリズムを記述している場合も、(スクリーンショットの実行結果を提出しますソートプログラムの3に欠陥がある、あなたが適切なようにして取得することができます) - Androidアプリは、実行ショットに提出見つけるためのアルゴリズムとテスト結果をソートするコードのクラウドにコードをプッシュする様々なを達成するために(行うために選出された、ポイント)
2.実験の手順と結果
最初の1:
- 最初の試験は、以下のように、長い前の二つの方法に関与する書き込みlinearSearch、選択ソート方法、などのように、比較的簡単です。
- 選択ソート方法
public static void selectionSort(Comparable[] data) {
int min;
for(int index=0;index<data.length-1;index++){
min=index;
for(int scan=index+1;scan<data.length;scan++)
if(data[scan].compareTo(data[min])<0)
min=scan;
swap(data,min,index);
}
}
private static void swap(Comparable[] data,int index1,int index2){
Comparable temp=data[index1];
data[index1]=data[index2];
data[index2]=temp;
}
- linearSearch方法
public static Comparable linearSearch(Comparable[] data,Comparable target){
Comparable result = null;
int index = 0;
while(result == null && index < data.length){
if(data[index].compareTo(target)==0)
result = data[index];
index++;
}
return result;
}
- この方法は、以下のようにコードは、テストを得るために2つだけのキーワード、最初、最後、電話を必要とします。
player[0] = new Contact("d", "j", "2301");
Contact target1 = new Contact("","","0505");
Contact found[] = new Contact[10];
found[0] = (Contact) Searching.linearSearch(player,target1);
- 最後に、検索するかどうかを判断します
for(int i=0;i<8;i++){
System.out.println("Test"+(i+1)+":");
if(found[i] == null)
System.out.println("Player was not found.");
else
System.out.println("Found: "+ found[i]);
}
第2
- 第二は、再構成の主な方法を理解するための最初のステップ、より単純です
- 復興には、コードを調整することであるが、ソフトウェアの拡張性を、理解維持・向上させるためのプログラムは、より合理的かつ容易にするためにソフトウェアの品質、性能、建築、デザインパターンを改善するために、プログラムの機能特性を変更しません。
- コマンドラインを確認するために第2のステップ
- 詳細な説明、コマンド・ライン・リンク2を参照してください
- コマンドラインを使用する場合は、問題がある、質問3を参照してください。
第三の
- まず、次のように、学習アルゴリズムとコードの実装を見つけます:
- linearSearch
public static int linearSearch(int[] data,int target){
int result = 0;
int index = 0;
while(result == 0 && index < data.length){
if(data[index]==target)
result = data[index];
index++;
}
return result;
}
- InsertionSearch
public static int InsertionSearch(int[] a, int x , int left, int right){
if(x<a[0]||x>a[a.length-1]){ //不加这句会抛出异常,若找的数不在范围内,则mid可能越界//
return -1; }
int mid = left + (x-a[left])/(a[right]-a[left])*(right-left);
if(left>right){
return -1; }
if(x<a[mid]){
return InsertionSearch(a,x,left,mid-1);
} else if(x>a[mid]){
return InsertionSearch(a,x,mid+1,right);
} else{
return a[mid];
}
}
- FibonacInsearch
- フィボナッチはバイナリサーチに基づいて記載されているフィボナッチに応じて分割されて下さい。F [n]は、ルックアップテーブルの元の長さの数は、F.拡張テーブル内の要素の数を見つけるためにルックアップよりもわずかに大きいに等しい列の行為フィボナッチ数のN-をフィボナッチこと分割が完了した、すなわち、F [N]番目要素は前半F [N-1]の要素、Fの後半に分割されている[N-2]の要素は、それが見つかるまで、再帰的にその部分の要素とを見つけるために検索します。フィボナッチの詳細情報を見つけるためにリンクを参照してください3
public static void fibonacci(int[] f){
f[0]=0;
f[1]=1;
for(int i=2;i<f.length;++i){
f[i]=f[i-1]+f[i-2];
}
}
public static int FibonacInsearch(int[] a, int x){
int left=0, right=a.length-1;
int k=0;
int FIB_MAX = 20;
int[] f = new int[FIB_MAX];
fibonacci(f);
while(a.length>f[k]-1){
k++;
}
int[] tmp = new int[f[k]-1];
System.arraycopy(a,0,tmp,0,a.length);//拷贝a元素到tmp中
for(int i=a.length;i<f[k]-1;++i){ //right以后的值都相同
tmp[i]=a[right];
}
while(left<=right){
int mid = left+f[k-1]-1;
if(x<a[mid]){
right=mid-1;
k-=1;
}
else if(x>a[mid]){
left=mid+1;
k-=2;
}
else{
if(mid<a.length)
return a[mid];
else //扩展里找到x,返回a的最后一个下标
return a.length-1;
}
}
return -1;
}
- バイナリツリーを検索
- 質量参加は、質問2を見ると、バイナリサーチの時、私は問題が発生しました。
//二叉树查找
private static Node root;
private Node temp;
public Searching2() {
root = null;
}
public void add(int data1) {//向二叉树插入元素
if (this.root == null) {
root = new Node(data1);
temp = root;//存下第一个节点
} else {
addW(root,data1);
}
}
public void addW(Node x,int data1) {//判定插入元素的位置
//当数据大于等于节点时,放右子树
if (data1 >= x.getData()) {
if (x.getRight() == null) {
x.setRight(new Node(data1));
} else {
addW(x.getRight(),data1);
}
}
else {//数据小于节点时,放左子树
if (x.getLeft() == null) {
x.setLeft(new Node(data1));
} else {
this.addW(x.getLeft(),data1);
}
}
}
public void print() {
root.print(); System.out.println();
}
public Node BSTreesearch(Node x,int data2) {//在二叉树中寻找元素
if(x==null)
return null;
if(data2==x.getData()){
return x;
}
else if(data2<x.getData()){
return BSTreesearch(x.getLeft(),data2);
}
else {
return BSTreesearch(x.getRight(),data2);
}
}
public int BS(int target){
Node k =BSTreesearch(root,target);
int po = k.getData();
return po;
}
public Node getRoot() {
return root;
}
- ブロック検索
public static int blocksearch(int[] index,int[] data,int target,int m){
int i = Bsearch(index,target);
System.out.println("在第"+i+"块");
if(i>=0){
int j = m*i;
int k = m*(i+1);
for(;j<k;j++){
if(data[j]==target)
return data[j];
}
}
return -1;
}
- ハッシュ・ルックアップ
public static int[] addhashlinear(int[] data){
int[] result=new int[13];
for(int i=0;i<data.length;i++){
int m=data[i]%13;
while(result[m]!=0)
m++;
result[m]=data[i];
}
return result;
}
public static int hashlinear(int[] data,int target){
int m = target%13;
while(data[m]!=target&&m<data.length-1){
m++;
}
return data[m];
}
- その他のアルゴリズムを検索示すように、テスト中に、または間違ってテストすることができ、正確です:
実験4
- クラスのレビューの話次のように、ソートされ、テストさ:
- シェルソート
public class shell {
public static void main(String[] args){
int gap,a,d,count=0,temp,l,okk;
int[] c=new int[10];
Arrays.fill(c,0);
String e,ok="";
Scanner scan=new Scanner(System.in);
System.out.println("输入数组数字:(空格隔开)");
e=scan.nextLine();
String[] f=e.split(" ");
count=f.length;
for(a=0;a<f.length;a++){
c[a]= Integer.parseInt(f[a]);
}
for(gap=f.length/2;gap>0;gap=gap/2){
for(d=gap;d<=f.length-1;d++){
l=d;
temp=c[l];
if(c[l]<c[l-gap]){
while(l-gap>=0&&temp<c[l-gap]){
c[l]=c[l-gap];
l-=gap;
}
c[l]=temp;
}
}
}
for(okk=0;okk<f.length;okk++){
ok+=c[okk]+" ";
}
System.out.println(ok);
}
}
- ヒープソート
public class dui {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int a, b, c, d, dd,head, kk, temp, i = 1;
String e;
System.out.println("请输入堆元素(以空格隔开)");
e = scan.nextLine();
String[] f = e.split(" ");
int[] count = new int[f.length];
// int[] fin=new int[f.length];
//以数组形式构造树
for (a = 0; a < f.length; a++) {
count[a] = Integer.parseInt(f[a]);
}
kk = count.length;//待排序的元素个数
String pp="";
for(int oo=0;oo<count.length;oo++){
pp=pp+count[oo]+" ";
}
System.out.println("堆排序前"+pp);
//排序
temp = kk;//排序中的下标
while (kk >= 3) {
temp = kk;
i=1;
while (temp > 1) {
c = temp / 2 - 1;
if (c==-1)
c=0;
if (i == 1) {
if (kk % 2 == 0) {
if (count[c * 2 + 1] > count[c]) {
int kkk = count[c];
count[c] = count[c * 2 + 1];
count[c * 2 + 1] = kkk;
}
}
if (kk % 2 != 0) {
if (count[c * 2 + 1] > count[c * 2 + 2] && count[c * 2 + 1] > count[c]) {
int kkk = count[c];
count[c] = count[c * 2 + 1];
count[c * 2 + 1] = kkk;
} else if (count[c * 2 + 2] > count[c * 2 + 1] && count[c * 2 + 2] > count[c]) {
int kkk = count[c];
count[c] = count[c * 2 + 2];
count[c * 2 + 2] = kkk;
}
}
} else {
if (count[c * 2 + 1] > count[c] || count[c * 2 + 2] > count[c]) {
if (count[c * 2 + 1] > count[c * 2 + 2]) {
int kkk = count[c];
count[c] = count[c * 2 + 1];
count[c * 2 + 1] = kkk;
} else {
int kkk = count[c];
count[c] = count[c * 2 + 2];
count[c * 2 + 2] = kkk;
}
}
}
temp--;
i++;
}
b = count[0];
count[0] = count[kk - 1];
count[kk - 1] = b;
kk--;
i++;
}
for(d=0;d<3;d++){
for(dd=d;dd<3;dd++){
if(count[dd]<count[d]){
head=count[dd];
count[dd]=count[d];
count[d]=head;
}
}
}
String ll="";
for(int hh=0;hh<count.length;hh++){
ll=ll+count[hh]+" ";
}
System.out.println("堆排序后"+ll);
}
}
- バイナリツリーの並べ替え
public class tree {
public static void main(String[] args){
int a,b,c,d,count;
int[] h=new int[10];
Arrays.fill(h,0);
leaf root=null;
String f,g;
Scanner scan=new Scanner(System.in);
System.out.println("请输入数组数字(空格隔开)");
f=scan.nextLine();
String[] e=f.split(" ");
for(c=0;c<e.length;c++){
h[c]= Integer.parseInt(e[c]);
}
//构造树
for(a=0;a<e.length;a++){
leaf temp=new leaf(h[a]);
if(root==null){
root=temp;
}
else{
leaf current=root;
while(true) {
if (temp.root > current.root) {
if(current.right==null) {current.right=temp; break;}
else current=current.right;
}
if(temp.root<current.root){
if(current.left==null){current.left=temp;break;}
else current=current.left;
}
}
}
}
root.dayin(root);
}
}
第五の
- Androidのは、それが解決把握した後、インターフェイスの問題に焦点を当てました
3.実験過程で発生した問題や決済処理
- 質問1:なぜリファクタリング?目標は、再構築するためには何に達することができますか?ときに私はリファクタリングが必要なのですか?再建の方法は何ですか?
- 問題1ソリューション:
- なぜリファクタリング?
- 復興のための最も基本的な理由のニーズを刻々と変化、および再構成は、すべての開発者が直面しなければならない宿題です。
- 元のコードの構造設計は、慎重に良いアーキテクチャで、設計されています。しかし、時間の経過とともに、需要の急増は、我々はオリジナルの特徴、追加された新機能を変更し続けなければならないが、また、必然的にいくつかの欠点を修正する必要がありました。変更を達成するためには、初期の設計フレームワークに違反する避けられません。時間が経つにつれて、ここに穴のソフトウェアアーキテクチャ。バグは、より多くの、より多くの困難は、新たな需要のための最初のコードの枠組みが徐々にサポートする能力を失い、新たな需要ますます困難達成するために維持するために、しかし制約となっています。最後に、開発コストの新たな要求は終わりが来るの人生のこのアプリを作る新しいソフトウェアの開発コストを、超えてしまいます。
- リファクタリングは回避にこのような現象を最大化することができます。システムは、方法を再構築用いて、特定のステージに展開された後、システムは、再仕上げの、内部構造の外部の特徴を変更しません。、構造定数調整システムを再構築変化する要件にシステムを可能にすることにより、常に適応する強力な能力を持っています。
- 目標は、再構築するためには何に達することができますか?
- 部分的な補正とソフトウェア設計の改善を持続
- もっと他の人が理解コードを作ります
- 隠されたコードの欠陥を見つけるヘルプ
- 長い目で見れば、ヘルプ、プログラミングの効率を向上させるプロジェクトスケジュールを増やす(スケジュールは品質の敵である、品質は友人の進捗状況です)
- ときに私はリファクタリングが必要なのですか?
- ファジィメソッド名は意味を持ちません。
- ビッグクラス
- ロング方法
- 質量参加の多数
- 実装するその機能の既存のコードは、あまりにも複雑で、そしてあなたはそれを解析しています。
- 明確にする必要があり、既存のコードのロジックよりもコードを変更します。
- 私たちは、プロジェクトの回帰テストをサポートするのに十分な時間、人材と財源を持っています。
- 古い既存のコードの非効率。
- 引き取り手のない、書き込みはこのカテゴリにコードの秋を吸います。
- コードエリア。このコードは一人だけでは大きなリスクをもたらす可能性がありますを変更し、変更することができます。
- 再建の方法は何ですか?
- クラス/メソッドの離脱を抽出します
- 「脂肪クラス」(xmppmanager.h)の方法、そのようなコードは、元のクラス属性臭いであるべきであり、新たなクラスに適切な数まで移動します。新しいクラスとメソッドの旧対応するクラス属性を削除する必要があります。加えて、それが含まれているので、時々、過度にこの方法を使用して、他のクラスによって肥大化クラスのいくつかは、クラスメソッドの他のメンバーの一員であるべきです。また、これらの方法は、適切なクラスに移動する必要があります。
- 分離条件
- 多くの場合、この方法は、(のif-else)、いくつかの分岐文が含まれているため、長いです。分岐条件が抽出され、いくつかの別の方法に移動させることができます。これは確かに大幅にコードの読みやすさと分かりやすさを向上させることができます。
- パラメータオブジェクト/保持グローバルオブジェクトを導入
- いくつかのパラメータは、メソッドに渡されます。既存の方法に関連したメソッドからのパラメータを追加または削除する必要の主な問題。このシナリオでは、(組み込まれたパラメータオブジェクト)からなるオブジェクトに関連する提案手法のパラメータは、ので、これらの通過は、この方法ではなく、それぞれの個々のパラメータオブジェクトこと。
- また意味のない数値定数のシンボル
- どこでも使用することが有意義とリテラル定数のためにそれらのためにという名前の定数を割り当てる必要があります。これは、大幅にコードの読みやすさとわかりやすさを向上させることができます。
- 改称
- 前述したように、あいまいなコードのメソッド名は、より良いビジネスコンテキストを通じてヘルプの開発者へのビジネス用語に関連付けすることができる意味のある名前に名前を変更する必要がありますいくつかのあいまいな名前のユーザビリティに影響を与えることができますコードを理解しています。
- メモリの最適化
- メモリ使用量適時リリースにプロジェクトをチェック。
- ハードコードされた削除し、それはモジュラー統一マクロ定義ファイルにコピーします
- 一般的な団結がマクロ定義ファイルを書き込みますコピーライティングコピーライティングを通していくつかの、
- クラス/メソッドの離脱を抽出します
- 質問2:オリジナルのバイナリコードに従ってを探すルートツリーの全ルート上を通過し、再帰的に困難であり、その後、新しいメソッドを記述し、次の通り:
- 問題2ソリューション:
public int BS(int target){
Node k =BSTreesearch(root,target);
int po = k.getData();
return po;
}
- テストコードに対応
@Test
public void testTestSearch() {
Node root;
Node temp;
int[] number = new int[]{20,18,23,1,9,10};
Searching2 tree = new Searching2();
for(int m=0;m<number.length;m++){
tree.add(number[m]);
}
assertEquals(1,tree.BS(1));
assertEquals(23,tree.BS(23));
}
最後のテストは成功しました
質問3:仮想マシンのコマンドラインを使用する場合、問題が発生します:
- 質問3ソリューション:
- 一般的な使用のない定義されたセットが存在しないので、これはあなたが報告されていないという一般的な警告を使用する場合、使用には影響しません、単なる警告、エラーではありません。再び時間後にJDK1.5汎用コンテナの定義を追加します
- 3つの解決策は、あります。
その他(知覚、思考、など)
実現は、基本的には、教師のレビュー内容について話しました、我々はまた、将来のレビューの多くを持って、比較的簡単です。