查找、排序、符号表、散列表等算法实现(1)
本文参考《算法(第4版)》
基本的查找、排序、符号表、散列表算法实现汇总1
1.比较和交换
package algorithms.model;
public class Smethod {
public static void exch(int[] a,int i, int j){
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static int less(int[] a,int i, int j){
if(a[i] < a[j])
return -1;
else if(a[i] > a[j])
return 1;
else return 0;
}
}
2.选择排序
package algorithms.rank;
import java.util.Arrays;
import algorithms.model.Smethod;
class Selection {
public static int[] sort(int[] a, int lo, int hi){
for(int i = lo; i < hi +1; i++){
int min = i;
for(int j = i+1; j < hi + 1; j++){
if(a[min]>a[j])
min = j;
}
Smethod.exch(a, i, min);
}
return a;
}
public static void main(String[] args) {
int[] a = {4,5,14,6,7,98,44,56,1,3};
for(int i : sort(a, 0, a.length-1))
System.out.print(i + " ");
}
}
3.插入排序
package algorithms.rank;
import algorithms.model.Smethod;
public class Insertion {
public static int[] sort(int[] a, int lo, int hi){
for(int i = lo + 1; i < hi + 1; i++)
for(int j = i; j > lo; j--){
if(a[j] < a[j-1])
Smethod.exch(a, j, j-1);
}
return a;
}
//测试用例
public static void main(String[] args) {
int[] a = {4,5,14,6,7,98,44,56,1,3};
for(int i : sort(a, 0, a.length-1))
System.out.print(i + " ");
}
}
4.希尔排序
package algorithms.rank;
import algorithms.model.Smethod;
class Shell {
public static int[] sort(int[] a, int lo, int hi){
int N = hi - lo + 1;
int h = 1;
while(h < N)
h = 3*h + 1;
while(h > 0){
for(int i = h; i < hi + 1; i++)
for(int j = i; j - h > lo - 1; j = j - h){
if(a[j] < a[j-h])
Smethod.exch(a, j, j-h);
}
h = h/3;
}
return a;
}
public static void main(String[] args) {
int[] a = {4,5,14,6,7,98,44,56,1,3,24,54,67,78,89,81,13,15};
for(int i : sort(a, 0, a.length-1))
System.out.print(i + " ");
}
}
5.归并排序
package algorithms.rank;
import algorithms.model.Smethod;
class Merge {
public static void merge(int[] a, int lo, int mid, int hi){
int[] auk = new int[a.length];
int i = lo;
int j = mid + 1;
for(int k = lo; k <= hi; k++)
auk[k] = a[k];
for(int k = lo; k <= hi; k++)
if(i > mid) a[k] = auk[j++];
else if (j > hi) a[k] = auk[i++];
else if (Smethod.less(auk, i, j) < 0) a[k] = auk[i++];
else a[k] = auk[j++];
}
public static void sort(int[] a, int lo, int hi){
if(hi <= lo) return;
int mid = lo + (hi - lo)/2;
sort(a, lo, mid);
sort(a, mid+1, hi);
merge(a, lo, mid, hi);
}
public static void main(String[] args) {
int[] b = {1,12,13,14,5,6,17,35,56};
merge(b,0,3,8);
for(int i : b)
System.out.print(i + " ");
System.out.println();
int[] a = {11,9,2,3,4,5,11,1,71};
sort(a,0,a.length-1);
for(int i : a)
System.out.print(i + " ");
}
}
6.快速排序
package algorithms.rank;
import algorithms.model.Smethod;
public class Quick {
public static void sort(int[] a, int lo, int hi){
if(hi<=lo) return;
int j = position(a, lo, hi);
sort(a, lo, j-1);
sort(a, j+1, hi);
}
public static int position(int[] a, int lo, int hi){
int v = a[lo];
int i = lo;
int j = hi + 1;
while(true){
while(a[++i] < v) if(i == hi) break;
while(a[--j] > v) if(j == lo) break;
System.out.println(i +" : " + j);
if(i >= j) break;
Smethod.exch(a, i, j);
for(int m : a){
System.out.print(m + " ");
}
System.out.println();
}
Smethod.exch(a, lo, j);
return j;
}
public static void main(String[] args) {
int[] a = {5,6,5,5,5,4};
int[] b = {6,5,4,3,2,1};
//int[] a = {5, 4};
int N = a.length;
sort(a, 0, N-1);
for(int i : a)
System.out.print(i + " ");
}
}
7.三向快速排序
package algorithms.rank;
import algorithms.model.Smethod;
class Quick3way {
public static void sort(int[] a, int lo, int hi){
if(hi<=lo) return;
int v = a[lo];
int lt = lo;
int i = lt + 1;
int gt = hi;
while(i <= gt){
int cmp = a[i] - v;
if (cmp < 0) Smethod.exch(a, lt++, i++);
else if(cmp > 0) Smethod.exch(a, gt--, i);
else i++;
}
sort(a, lo, lt - 1);
sort(a, gt + 1, hi);
}
public static void main(String[] args) {
int[] a = {11,9,11,11,78,56,81,35,32,31,33,45,78,64,11,11,11,11,33,33,33,33,33,2,3,4,5,11,1,71};
//System.out.print(a.length);
sort(a,0,a.length-1);
for(int i : a)
System.out.print(i + " ");
}
}
8.基于二叉堆的优先队列及堆排序
基于二叉堆的最大优先队列以及堆排序实现:
package algorithms.rank;
//基于二叉堆的最大优先队列以及堆排序实现
public class MaxPQ<T extends Comparable<T>>{
private T[] pq; //基于的数组
private int N = 0; //优先队列长度 ,持有元素的个数
public MaxPQ(int MaxN){//预先设定数组大小
pq = (T[])new Comparable[MaxN + 1];
}
public int size(){
return N;
}
public boolean isEmpty(){
return N == 0;
}
private boolean isFull(){
return N >= pq.length - 1;
}
private void resize(int max){
T[] temp = (T[])new Comparable[max]; //辅助数组,pq.length=max
for(int i = 1; i <= N; i++)
temp[i] = pq[i];
pq = temp;
}
private void exch(int i, int j){
T temp = pq[i];
pq[i] = pq[j];
pq[j] = temp;
}
private boolean less(int i, int j){
//System.out.println("pq["+i+"]="+pq[i]+",pq["+j+"]="+pq[j]+";N="+N);
return pq[i].compareTo(pq[j]) < 0;
}
private void swim(int k){//较大值上浮
while(k > 1 && less(k/2, k)){//k > 1即k=2,3时
exch(k, k/2);
k = k/2;
}
}
private void sink(int k){//较小值下沉
while(2*k <= N){
int j = 2*k;
if(j < N && less(j, j + 1)) j++;
if(!less(k, j)) break;
exch(k, j);
k = j;
}
}
//在长度为M的数组中下沉
private void sink(int k, int M){//较小值下沉 ;
while(2*k <= M){
int j = 2*k;
if(j < M && less(j, j + 1)) j++; //j < M在less(j, j + 1)之前;此处是j<M而不是j<N
if(!less(k, j)) break;
exch(k, j);
k = j;
}
}
//上浮堆排序
public void insert(T v){
if(isFull()) resize(2*pq.length);
pq[++N] = v; //索引0处不存储元素。
swim(N);
}
public T delMax(){
T max = pq[1]; //从根节点获取最大元素;
exch(1, N--); //根节点元素和最后一个交换,同时数组长度减1
pq[N+1] = null; //防止越界
sink(1); //恢复堆有序
if(N > 0 && N < pq.length/4) resize(pq.length/2);
//System.out.println("length= " + pq.length + " ,N = " + N);
return max;
}
public void sort(){ //堆排序
int M = N;//N是pq的当前长度属性,而M是个临时变量。数组的长度和数组存放的元素数量是不一样的。
for(int k = M/2; k >= 1; k--) //堆的构造
sink(k, M);
while(M > 1){ //下沉排序
exch(1, M--);
sink(1, M);
}
}
public void print(){//从数组的位置1开始使用;打印堆有序数组
for(int i = 1; i <= N; i++)
System.out.print(pq[i]+" ");
}
public void set(T[] b){
for(int i = 0; i < b.length; i++){
pq[i+1] = b[i];
N++;
}
}
public static void main(String[] args) {
Integer[] b = {11,19,21,13,4,5,15,1,45,11,24,54,6,7,3,71};
MaxPQ<Integer> MaxPQ2 = new MaxPQ<Integer>(b.length+1);
for(Integer v : b)
MaxPQ2.insert(v);
System.out.println("构造堆:");
MaxPQ2.print(); //71 54 45 24 21 19 15 13 11 4 11 5 6 7 3 1
System.out.println();
System.out.println("逐个删除最大值");
while(MaxPQ2.size()>0)
System.out.println(MaxPQ2.delMax()+" "); // 71 54 45 24 21 19 15 13 11 11 7 6 5 4 3 1
MaxPQ<Integer> MaxPQ3 = new MaxPQ<Integer>(b.length+1);
for(Integer v : b)
MaxPQ3.insert(v);
System.out.println();
System.out.println("构造堆:");
MaxPQ3.print(); //71 54 45 24 21 19 15 13 11 4 11 5 6 7 3 1
System.out.println();
System.out.println("堆排序:");
MaxPQ3.sort();
MaxPQ3.print(); //1 3 4 5 6 7 11 11 13 15 19 21 24 45 54 71
}
}
输出:
构造堆:
71 54 45 24 21 19 15 13 11 4 11 5 6 7 3 1
逐个删除最大值
71
54
45
24
21
19
15
13
11
11
7
6
5
4
3
1
构造堆:
71 54 45 24 21 19 15 13 11 4 11 5 6 7 3 1
堆排序:
1 3 4 5 6 7 11 11 13 15 19 21 24 45 54 71
基于二叉堆的最小优先队列以及堆排序实现:
package algorithms.rank;
//基于二叉堆的最小优先队列以及堆排序实现
public class MinPQ<T extends Comparable<T>>{
private T[] pq; //基于的数组
private int N = 0; //优先队列长度
public MinPQ(int MaxN){//预先设定数组大小
pq = (T[])new Comparable[MaxN + 1];
}
public int size(){
return N;
}
public boolean isEmpty(){
return N == 0;
}
private boolean isFull(){
return N == pq.length - 1;
}
private void resize(int max){
T[] temp = (T[])new Comparable[max]; //辅助数组
for(int i = 1; i <= N; i++)
temp[i] = pq[i];
pq = temp;
}
private void exch(int i, int j){
T temp = pq[i];
pq[i] = pq[j];
pq[j] = temp;
}
private boolean bigger(int i, int j){
return pq[i].compareTo(pq[j]) > 0;
}
private void swim(int k){//较小值上浮
if(k <= 1) return;
while(k > 1 && bigger(k/2, k)){//k > 1即k=2,3时
exch(k, k/2);
k = k/2;
}
}
private void sink(int k){//较大值下沉
if(k < 1) return;
while(2*k <= N){
int j = 2*k;
if(j < N && bigger(j, j + 1)) j++;
if(!bigger(k, j)) break;
exch(k, j);
k = j;
}
}
//在长度为M的数组中下沉
private void sink(int k, int M){//较大值下沉 ;
if(k < 1) return;
while(2*k <= M){
int j = 2*k;
if(j < M && bigger(j, j + 1)) j++;//j < M在less(j, j + 1)之前;此处是j<M而不是j<N
if(!bigger(k, j)) break;
exch(k, j);
k = j;
}
}
//使用上浮堆排序
public void insert(T v){
if(isFull()) resize(2*pq.length);
pq[++N] = v;
swim(N);
}
public T delMin(){
T min = pq[1]; //从根节点获取最小元素;
exch(1, N--); //根节点元素和最后一个交换,同时数组长度减1
pq[N+1] = null; //防止越界取值
sink(1); //恢复堆有序
if(N > 0 && N < pq.length/4) resize(pq.length/2);
//System.out.println("length= " + pq.length + " ,N = " + N);
return min;
}
public void sort(){ //进行堆排序
int M = N;//N是pq的当前长度属性,而M是个临时变量。数组的长度和数组存放的元素数量是不一样的。
for(int k = M/2; k >= 1; k--)
sink(k, M);
while(M > 1){
exch(1, M--);
sink(1, M);
}
}
public void print(){//从数组的位置1开始使用
for(int i = 1; i <= N; i++)
System.out.print(pq[i]+" ");
}
public void set(T[] b){
for(int i = 0; i < b.length; i++){
pq[i+1] = b[i];
N++;
}
}
public static void main(String[] args) {
Integer[] b = {11,19,21,13,4,5,15,1,45,11,24,54,6,7,3,71};
MinPQ<Integer> minPQ2 = new MinPQ<Integer>(b.length+1);
for(Integer v : b)
minPQ2.insert(v);
System.out.println("构造堆:");
minPQ2.print(); //1 4 3 11 11 6 5 19 45 13 24 54 21 15 7 71
System.out.println();
System.out.println("逐个删除最小值");
while(minPQ2.size()>0)
System.out.println(minPQ2.delMin()+" "); // 1 3 4 5 6 7 11 11 13 15 19 21 24 45 54 71
MinPQ<Integer> minPQ3 = new MinPQ<Integer>(b.length+1);
for(Integer v : b)
minPQ3.insert(v);
System.out.println();
System.out.println("构造堆:");
minPQ3.print(); //1 4 3 11 11 6 5 19 45 13 24 54 21 15 7 71
System.out.println();
System.out.println("堆排序:");
minPQ3.sort();
minPQ3.print(); //71 13 54 19 45 15 21 7 11 11 24 6 5 4 3 1
}
}
输出:
构造堆:
1 4 3 11 11 6 5 19 45 13 24 54 21 15 7 71
逐个删除最小值
1
3
4
5
6
7
11
11
13
15
19
21
24
45
54
71
构造堆:
1 4 3 11 11 6 5 19 45 13 24 54 21 15 7 71
堆排序:
71 54 45 24 21 19 15 13 11 11 7 6 5 4 3 1
9.基于有序数组的二分查找实现符号表
package algorithms.search;
/**
* 基于有序数组的二分查找实现符号表
* */
//Key, Value为泛型参数
public class BinarySearchST<Key extends Comparable<Key>, Value> {
private Key[] keys;
private Value[] vals;
private int N;
BinarySearchST(int capacity){
keys = (Key[])new Comparable[capacity];
vals = (Value[])new Object[capacity];
this.N = 0;
}
public int size(){
return N;
}
public boolean isFull(){
return N == keys.length;
}
public boolean isEmpty(){
return N == 0;
}
public void put(Key key, Value val){
int i = rank(key);
if(i < N && key.compareTo(keys[i])==0){
vals[i] = val;
return; //跳出函数,不再往下执行;
}
for(int j = N; j > i; j--){
keys[j] = keys[j-1];
vals[j] = vals[j-1];
}
keys[i] = key;
vals[i] = val;
N++;
}
public Value get(Key key){
if(isEmpty()) return null;
int i = rank(key);
if(i < N && key.compareTo(keys[i])==0)
return vals[i];
return null;
}
public Key min(){
return keys[0];
}
public Key max(){
return keys[N-1];
}
//选择排名为k的键;
public Key select(int k){
if( k < N && k >= 0)
return keys[k];
else return null;
}
//大于等于key的最小值
public Key ceiling(Key key){
int i = rank(key);
if( i == N ) return null;
return keys[i];
//or
// if( i < N) return keys[i];
// else return null;
}
//小于等于key的最大值
public Key floor(Key key){
int i = rank(key);
if(i < N && key.compareTo(keys[i])==0)
return keys[i];
return keys[i-1];
}
public boolean contains(Key key){
int i = rank(key);
if( i < N && key.compareTo(keys[i]) == 0)
return true;
return false;
}
//rank()方法返回小于键的键的数量,lo的取值范围为[0,N];
//大于中间值,小的索引往右移;小于中间值,大的索引往左移动
public int rank(Key key){
int lo = 0;
int hi = N - 1;
while(lo <= hi){
int mid = lo + (hi - lo)/2;
int cmp = key.compareTo(keys[mid]);
if(cmp < 0) hi = mid - 1;
else if(cmp > 0) lo = mid + 1;
else return mid;
}
return lo;
}
public String printKeys(){
return keys.toString();
}
public static void main(String[] args) {
BinarySearchST<Integer , Integer> bst = new BinarySearchST<Integer, Integer>(50);
for(int i = 0; i < 10; i++)
bst.put(i, i*2);
System.out.println(bst.N);
System.out.println(bst.printKeys());
System.out.println(bst.select(3));
System.out.println(bst.contains(3));
System.out.println(bst.get(4));
for(int i = 0; i < bst.N; i++)
System.out.print(bst.get(i)+ " ");
}
}
10.二叉树
package algorithms.search;
/*
* 二叉树实现
* */
class BST2<Key extends Comparable<Key>, Value> {
private Node root;
private class Node{
private Key key;
private Value val;
private Node left, right;
private int N;
Node(Key key, Value val, int N){
this.key = key;
this.val = val;
this.N = N;
}
}
public void print(){
print(root);
}
private void print(Node x){
if(x == null) return;
print(x.left);
System.out.println(x.key);
print(x.right);
}
public int size(){
return size(root);
}
private int size(Node x){
if(x == null) return 0;
else return x.N;
}
public Value get(Key key){
return get(root, key);
}
private Value get(Node x, Key key){
if(x == null) return null;
int cmp = key.compareTo(x.key);
if(cmp < 0) return get(x.left, key);
else if(cmp > 0) return get(x.right, key);
else return x.val;
}
public void put(Key key, Value val){
root = put(root, key, val);
}
private Node put(Node x, Key key, Value val){
if(x == null) return new Node(key, val, 1);
int cmp = key.compareTo(x.key);
if(cmp < 0) x.left = put(x.left, key, val);
else if(cmp > 0) x.right = put(x.right, key, val);
else x.val = val;
x.N = size(x.left) + size(x.right) + 1;
return x;
}
public Value min(){
return min(root).val;
}
private Node min(Node x){
if(x.left == null) return x;
return min(x.left);
}
public Value max(){
return max(root).val;
}
private Node max(Node x){
if(x.right == null) return x;
return max(x.right);
}
public void deleteMin(){
root = deleteMin(root);
}
private Node deleteMin(Node x){
if(x.left == null) return x.right;
x.left = deleteMin(x.left);
x.N = size(x.left) + size(x.right) + 1;
return x;
}
public Node delete(Key key){
return delete(root, key);
}
private Node delete(Node x, Key key){
if(x == null) return null;
int cmp = key.compareTo(x.key);
if(cmp < 0) x.left = delete(x.left, key);
else if(cmp > 0) x.right = delete(x.right, key);
else {
if(x.left == null) return x.right;
if(x.right == null) return x.left;
Node t = x;
x = min(t.right);
x.right = deleteMin(t.right);
x.left = t.left;
}
x.N = size(x.left) + size(x.right) + 1;
return x;
}
public Key select(int k){
return select(root, k).key;
}
private Node select(Node x, int k){
if(x == null) return null;
int t = size(x.left);
if(t > k) return select(x.left, k);
else if(t < k) return select(x.right, k-t-1);
else return x;
}
private int rank(Key key, Node x){
if(x == null) return 0;
int cmp = key.compareTo(x.key);
if(cmp < 0) return rank(key, x.left);
else if(cmp > 0) return 1 + size(x.left) + rank(key, x.right);
else return size(x.left);
}
public static void main(String[] args) {
BST2<String, Integer> bst = new BST2<String, Integer>();
String[] keys = "I love Beijing Gugong".split(" ");
Integer[] vals = {1,3,4,5};
int i = 0;
System.out.println(vals.toString());
for(String str : keys)
bst.put(str, vals[i++]);
bst.print();
System.out.println(bst.size());
}
}
package algorithms.search;
//基于拉链的散列表
public class SeparateChainingHashST<Key, Value> {
private int M;
private int N;
private SeparateChainingHashST<Key, Value>[] st;
public SeparateChainingHashST(){
this(997);
}
public SeparateChainingHashST(int M){
this.M = M;
st = (SeparateChainingHashST<Key, Value>[])new SeparateChainingHashST[M];
for(int i = 0; i < M; i++)
st[i] = new SeparateChainingHashST();
}
public int hash(Key key){
//Key的hashCode()若未覆盖Object的hashCode(),则key.hashCode()为Object的版本,取对象地址
return (key.hashCode()& 0x7fffffff)%M;
}
public Value get(Key key){
return (Value)st[hash(key)].get(key);
}
public void put(Key key, Value val){
st[hash(key)].put(key,val);
}
}
11.基于拉链的散列表
package algorithms.search;
//基于拉链的散列表
public class SeparateChainingHashST<Key, Value> {
private int M;
private int N;
private SeparateChainingHashST<Key, Value>[] st;
public SeparateChainingHashST(){
this(997);
}
public SeparateChainingHashST(int M){
this.M = M;
st = (SeparateChainingHashST<Key, Value>[])new SeparateChainingHashST[M];
for(int i = 0; i < M; i++)
st[i] = new SeparateChainingHashST();
}
public int hash(Key key){
//Key的hashCode()若未覆盖Object的hashCode(),则key.hashCode()为Object的版本,取对象地址
return (key.hashCode()& 0x7fffffff)%M;
}
public Value get(Key key){
return (Value)st[hash(key)].get(key);
}
public void put(Key key, Value val){
st[hash(key)].put(key,val);
}
}
12.基于线性探索的散列表
package algorithms.search;
import java.util.ArrayList;
import java.util.List;
import mPackage.newStack;
//基于线性探索的散列表
public class LinearProbingHashST<Key, Value> {
private int N;
private int M = 16;
private Key[] keys;
private Value[] vals;
LinearProbingHashST(){
keys = (Key[])new Object[M];
vals = (Value[])new Object[M];
}
LinearProbingHashST(int cap){
keys = (Key[])new Object[cap];
vals = (Value[])new Object[cap];
this.M = cap;
}
//Key的hashCode()若未覆盖Object版本的hashCode(),此处是默认取地址,相同的键会产生不同的散列值
//所以应该覆盖重写盖Object版本的hashCode(),保证相通的键产生相同的散列值
//hash()只是散列表的散列函数,要首先在类Key中保证key.hashCode()覆盖重写
//即要求Key的具体类型的类是同时覆盖equals()和hashCode()
//尝试去掉KeyTest的hasCode()代码运行看下结果
public int hash(Key key){
return (key.hashCode() & 0x7fffffff)%M;
}
public void put(Key key, Value val){
if(N >= M/2) resize(2*M);
int i;
for(i = hash(key); keys[i] != null; i = (i+1)%M )
if(keys[i].equals(key)){
vals[i] = val;
return;
}
keys[i] = key;
vals[i] = val;
N++;
}
public Value get(Key key){
for(int i = hash(key); keys[i] != null; i = (i+1)%M)
if( keys[i].equals(key) )
return vals[i];
return null;
}
public void resize(int cap){
LinearProbingHashST<Key, Value> st;
st = new LinearProbingHashST<Key, Value>(cap);
for(int i = 0; i < M; i++){
if(keys[i] != null)
st.put(keys[i], vals[i]);
}
keys = st.keys;
vals = st.vals;
M = st.M;
}
public boolean contains(Key key){
for(int i = hash(key); keys[i] != null; i = (i + 1)%M)
if(keys[i].equals(key))
return true;
return false;
}
public void delete(Key key){
if(!contains(key)) return; //防止为st空时进行删除;
int i = hash(key);
while(!keys[i].equals(key))
i = (i + 1)%M;
keys[i] = null;
vals[i] = null;
i = (i + 1)%M;
while(keys[i]!=null){
Key keyToRedo = keys[i];
Value valToRedo = vals[i];
keys[i] = null;
vals[i] = null;
N--; //N--;为什么放在put()前?
put(keyToRedo,valToRedo); //重新插入(移动)删除键后面对的键的散列值,即更新键的散列值;
i = (i + 1)%M;
}
N--;//针对于被删除的键
if(N >0 && N == M/8) resize(M/2);
}
public int getN(){
return this.N;
}
public int getM(){
return this.M;
}
public static void main(String[] args) {
LinearProbingHashST<KeyTest, ValueTest> st =
new LinearProbingHashST<KeyTest, ValueTest>();
for(int i = 0; i < 10; i++)
st.put(new KeyTest(i), new ValueTest(i*10));
System.out.println(st.hash(new KeyTest(3)));
System.out.println(st.hash(new KeyTest(3)));
System.out.println(st.hash(new KeyTest(4)));
System.out.println(st.contains(new KeyTest(3)));
System.out.println(st.get(new KeyTest(3)));
st.delete(new KeyTest(3));
System.out.println(st.contains(new KeyTest(3)));
System.out.println(st.getN());
LinearProbingHashST<KeyTest, ValueTest> st2 =
new LinearProbingHashST<KeyTest, ValueTest>();
//测试resize()
for(int i = 0; i < 100; i++)
st2.put(new KeyTest(i), new ValueTest(i*10));
System.out.println(st2.getN());
System.out.println(st2.getM());
}
}