package cqychen.algorithms.part01.charpter01;
import java.util.ArrayList;
import java.util.Scanner;
//此程序由cqychen编写,后续将继续跟进算法导论相应章节。
//本节主要的是归并排序,采用的是分治思想,即分而治之主要分为三个步骤
//1)分解
//2)解决
//3)合并
/**
* 这里主要编写的是泛型类
* @author cqychen
*
* @param <T>
*/
class GenericMergeSort<T extends Comparable<? super T>> {
private ArrayList<T> a = new ArrayList<>();
//编写相应的泛型方法
void merge(Integer p, Integer len_next, Integer q) {
Integer len1 = len_next - p + 1;
Integer len2 = q - len_next;
ArrayList<T> one = new ArrayList<T>();
ArrayList<T> two = new ArrayList<T>();
Integer i = 0;
Integer j = 0;
for (i = 0; i < len1; i++) {
one.add(i, a.get(p + i));
}
for (j = 0; j < len2; j++) {
two.add(j, a.get(len_next + j + 1));
}
one.trimToSize();
two.trimToSize();
//这里就不好加哨兵了。
i = j = 0;
Integer k=p;
while(i<len1&&j<len2){
if(one.get(i).compareTo(two.get(j))<0){
a.set(k++, one.get(i++));
}else{
a.set(k++, two.get(j++));
}
}
while(i<len1){
a.set(k++, one.get(i++));
}
while(j<len2){
a.set(k++, two.get(j++));
}
}
void mergesort(Integer p, Integer q) {
if (p < q) {
Integer len_next = (p + q) / 2;
mergesort(p, len_next);
mergesort(len_next + 1, q);
merge(p, len_next, q);
}
}
//进行初始化操作
void seta(ArrayList<T> a) {
System.out.println("这里我们采用的是泛型类的方法,这里进行初始化操作:");
this.a = a;
}
//打印结果
void printa() {
System.out.println("采用泛型的最后结果如下");
for (int i = 0; i < a.size(); i++) {
System.out.println(a.get(i));
}
}
}
/**
* 主类
* @author cqychen
*
*/
public class MergeSort {
//这里解决最后的合并问题。虽然在最开始写,但是是最后的步骤
//这里需要假定数组a中,从p到len_next以及len_next+1到q都是有序的
void Merge(Integer[] a, Integer p, Integer len_next, Integer q) {
//这里可以通过插入排序来完成归并过程,但是那就没必要了。
//这里还是采用的是以空间换取时间的方法。不然要归并排序何用啊\
Integer len1 = len_next - p + 1;
Integer len2 = q - len_next;
Integer[] one = new Integer[len1 + 1];
Integer[] two = new Integer[len2 + 1];
Integer i = 0;
Integer j = 0;
for (i = 0; i < len1; i++) {
one[i] = a[p + i];
}
for (j = 0; j < len2; j++) {
two[j] = a[j + len_next + 1];
}
//加上哨兵。使用最大值来做哨兵.按道理说应该是无限大。找不到啊。有风险的这样。不过这个是实验性质的嘛
one[len1] = Integer.MAX_VALUE;
two[len2] = Integer.MAX_VALUE;
i = j = 0;
/*for (Integer k = p; k < q + 1; k++) {
if (one[i] < two[j]) {
a[k] = one[i];
i++;
} else {
a[k] = two[j];
j++;
}
}*/
//这个是不采用哨兵的情况
Integer k=p;
while(i<len1&&j<len2){
if(one[i]<two[j]){
a[k++]=one[i++];
}else{
a[k++]=two[j++];
}
}
while(i<len1){
a[k++]=one[i++];
}
while(j<len2){
a[k++]=two[j++];
}
}
/**
* 这里之所以需要定义p和q主要是在分解后的传递参数需要这样的数字,不然怎么传递啊
* @param a
* @param p
* @param q
* @return
*/
Integer[] MergeSort(Integer[] a, Integer p, Integer q) {
if (p < q) {
Integer len_next = (p + q) / 2;
//这里进行分解
MergeSort(a, p, len_next);
MergeSort(a, len_next + 1, q);
Merge(a, p, len_next, q);//这里进行解决和归并
}
return a;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//首先定义一个普通的用于输入的数组。
Integer[] oraginal = new Integer[] { 23, 423, 221, 434, 5, 35, 67, 5677, 45, 777, 998, 98, 33 };
Integer len = oraginal.length;
MergeSort mergesort = new MergeSort();
mergesort.MergeSort(oraginal, 0, len - 1);//这里应该是len-1,因为我比较喜欢从一个点到另一个点,都是有数字的。
System.out.println("采用归并排序得到的结果是:");
for (Integer i = 0; i < len; i++) {
System.out.println(oraginal[i]);
}
/**
* 这里采用的是变长数组,同时使用的是泛型类来完成对其他类型的排序。
*/
Scanner inputs = new Scanner(System.in);
ArrayList<Integer> input2 = new ArrayList<>();
for (Integer i = 0; i < 10; i++) {
Integer inputnum = inputs.nextInt();
input2.add(inputnum);
}
input2.trimToSize();//调整数组大小
System.out.println("输入的数组大小是:" + input2.size());
GenericMergeSort aa = new GenericMergeSort<>();
aa.seta(input2);
aa.mergesort(0, input2.size() - 1);
aa.printa();
//对字符串进行排序
ArrayList<String> input3 = new ArrayList<>();
for (Integer i = 0; i < 10; i++) {
String inputnum = inputs.next();
input3.add(inputnum);
}
input3.trimToSize();//调整数组大小
aa.seta(input3);
aa.mergesort(0, input3.size()-1);
aa.printa();
}
}
import java.util.ArrayList;
import java.util.Scanner;
//此程序由cqychen编写,后续将继续跟进算法导论相应章节。
//本节主要的是归并排序,采用的是分治思想,即分而治之主要分为三个步骤
//1)分解
//2)解决
//3)合并
/**
* 这里主要编写的是泛型类
* @author cqychen
*
* @param <T>
*/
class GenericMergeSort<T extends Comparable<? super T>> {
private ArrayList<T> a = new ArrayList<>();
//编写相应的泛型方法
void merge(Integer p, Integer len_next, Integer q) {
Integer len1 = len_next - p + 1;
Integer len2 = q - len_next;
ArrayList<T> one = new ArrayList<T>();
ArrayList<T> two = new ArrayList<T>();
Integer i = 0;
Integer j = 0;
for (i = 0; i < len1; i++) {
one.add(i, a.get(p + i));
}
for (j = 0; j < len2; j++) {
two.add(j, a.get(len_next + j + 1));
}
one.trimToSize();
two.trimToSize();
//这里就不好加哨兵了。
i = j = 0;
Integer k=p;
while(i<len1&&j<len2){
if(one.get(i).compareTo(two.get(j))<0){
a.set(k++, one.get(i++));
}else{
a.set(k++, two.get(j++));
}
}
while(i<len1){
a.set(k++, one.get(i++));
}
while(j<len2){
a.set(k++, two.get(j++));
}
}
void mergesort(Integer p, Integer q) {
if (p < q) {
Integer len_next = (p + q) / 2;
mergesort(p, len_next);
mergesort(len_next + 1, q);
merge(p, len_next, q);
}
}
//进行初始化操作
void seta(ArrayList<T> a) {
System.out.println("这里我们采用的是泛型类的方法,这里进行初始化操作:");
this.a = a;
}
//打印结果
void printa() {
System.out.println("采用泛型的最后结果如下");
for (int i = 0; i < a.size(); i++) {
System.out.println(a.get(i));
}
}
}
/**
* 主类
* @author cqychen
*
*/
public class MergeSort {
//这里解决最后的合并问题。虽然在最开始写,但是是最后的步骤
//这里需要假定数组a中,从p到len_next以及len_next+1到q都是有序的
void Merge(Integer[] a, Integer p, Integer len_next, Integer q) {
//这里可以通过插入排序来完成归并过程,但是那就没必要了。
//这里还是采用的是以空间换取时间的方法。不然要归并排序何用啊\
Integer len1 = len_next - p + 1;
Integer len2 = q - len_next;
Integer[] one = new Integer[len1 + 1];
Integer[] two = new Integer[len2 + 1];
Integer i = 0;
Integer j = 0;
for (i = 0; i < len1; i++) {
one[i] = a[p + i];
}
for (j = 0; j < len2; j++) {
two[j] = a[j + len_next + 1];
}
//加上哨兵。使用最大值来做哨兵.按道理说应该是无限大。找不到啊。有风险的这样。不过这个是实验性质的嘛
one[len1] = Integer.MAX_VALUE;
two[len2] = Integer.MAX_VALUE;
i = j = 0;
/*for (Integer k = p; k < q + 1; k++) {
if (one[i] < two[j]) {
a[k] = one[i];
i++;
} else {
a[k] = two[j];
j++;
}
}*/
//这个是不采用哨兵的情况
Integer k=p;
while(i<len1&&j<len2){
if(one[i]<two[j]){
a[k++]=one[i++];
}else{
a[k++]=two[j++];
}
}
while(i<len1){
a[k++]=one[i++];
}
while(j<len2){
a[k++]=two[j++];
}
}
/**
* 这里之所以需要定义p和q主要是在分解后的传递参数需要这样的数字,不然怎么传递啊
* @param a
* @param p
* @param q
* @return
*/
Integer[] MergeSort(Integer[] a, Integer p, Integer q) {
if (p < q) {
Integer len_next = (p + q) / 2;
//这里进行分解
MergeSort(a, p, len_next);
MergeSort(a, len_next + 1, q);
Merge(a, p, len_next, q);//这里进行解决和归并
}
return a;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//首先定义一个普通的用于输入的数组。
Integer[] oraginal = new Integer[] { 23, 423, 221, 434, 5, 35, 67, 5677, 45, 777, 998, 98, 33 };
Integer len = oraginal.length;
MergeSort mergesort = new MergeSort();
mergesort.MergeSort(oraginal, 0, len - 1);//这里应该是len-1,因为我比较喜欢从一个点到另一个点,都是有数字的。
System.out.println("采用归并排序得到的结果是:");
for (Integer i = 0; i < len; i++) {
System.out.println(oraginal[i]);
}
/**
* 这里采用的是变长数组,同时使用的是泛型类来完成对其他类型的排序。
*/
Scanner inputs = new Scanner(System.in);
ArrayList<Integer> input2 = new ArrayList<>();
for (Integer i = 0; i < 10; i++) {
Integer inputnum = inputs.nextInt();
input2.add(inputnum);
}
input2.trimToSize();//调整数组大小
System.out.println("输入的数组大小是:" + input2.size());
GenericMergeSort aa = new GenericMergeSort<>();
aa.seta(input2);
aa.mergesort(0, input2.size() - 1);
aa.printa();
//对字符串进行排序
ArrayList<String> input3 = new ArrayList<>();
for (Integer i = 0; i < 10; i++) {
String inputnum = inputs.next();
input3.add(inputnum);
}
input3.trimToSize();//调整数组大小
aa.seta(input3);
aa.mergesort(0, input3.size()-1);
aa.printa();
}
}