现在的位置: 首页 > 综合 > 正文

我在北京找工作(三):java实现算法<2> 直接插入排序+不可变类

2017年12月16日 ⁄ 综合 ⁄ 共 2312字 ⁄ 字号 评论关闭

 

2013年9月3日 貌似看的排序算法实现的有点没难度,但还是一步一步稳扎稳打的来。

 

1、直接插入排序

直接插入排序(Insertion Sort)的基本思想:将数组分为有序区和无序区,每次将一个无序区的元素安琪关键字大小插入到有序区的适当位子,知道无序区元素个数为0,则排序完成。

同样的,我们设数组长度为N。
实现步骤:
<1> 初始时,下标为0的元素,也就是数组中的第一个元素自成有序区,其余皆为无序区元素。
<2> 将无序区的第一个元素插入到当前有序区的适当位置中,有序区间长度+1
<3> 重复第<2>步,直到无序区元素个数为0,则排序完成!

还是一些严格按照定义步骤进行编写的代码(依旧是默认为从小到大排序)........:

//直接插入排序基础版
	public void insertSort(int[] arr) {
		int j=-1;
		int k=-1;
		//循环默认从arr[1]开始排序,因为默认初始时arr[0]自成有序区
		for(int i=1;i<arr.length;i++) {
			//j控制循环层 为arr[i]在当前有序区为之寻找一个合适的插入位子
			for(j=i-1;j>=0;j--) {
				if(arr[j]<arr[i]) break ;
			}
			//如果找到了一个合适的位子,并且不是当前元素的正前方一个
			if(j!=i-1) {
				//将有序区中插入位子之后的所有元素向后移动,腾出空间
				int temp = arr[i] ;
				for(k=i-1;k>j;k--) {
					arr[k+1]=arr[k] ;
				}
				//最后将arr[i]放到正确的位子上即可
				arr[k+1] = temp ;
			}
		}
	}

不知道读者有没有注意到,前面的代码只是严格按照直接插入排序的定义来编写的,一步一步的实施,虽然次序井然有序。而且也明确的分工流水线。但是如此冗长的代码,依旧是不够清晰的!能够对其进行改写的方法有很多:
1)我们完全可以将搜索和后面的元素后移这两步进行同步操作(这里所说的同步和系统级别的线程级别的同步完全没有关系),h合并为一个步骤。
即,向前搜索一个,比之大的就直接后移一个位子。一边搜索,一边后移。这样之后,当找到合适的位子之后只需要直接插入就行了!!!

下面给出实现:

//合并搜索和移位的直接插入排序
	public void insertSort2(int[] arr) {
		int j= -1;
		for(int i=1;i<arr.length;i++) {
			if(arr[i]<arr[i-1]) {
				int temp = arr[i] ;
				//一边搜索+同时右移元素
				for(j=i-1;j>=0&&arr[j]>temp;j--) {
					arr[j+1] = arr[j] ;
				}
				//找到位子,直接插入元素
				arr[j+1] = temp ;
			}
		}
	}

可以看到,代码简单了许多。如果对于一些想要死记硬背的记住排序代码的屌来说,这可是难记了很多,但是对于通过原理摸索实现的猿们,这同样是轻松了许多。
所以还是不可不强调,通晓原理,才是学习的最好方法!!! 

 别再抱怨啦,,,,,啦啦啦   德玛西亚~~~

还有一种改写方法,是看别人的代码是想到的:
2)原理很简单,就是在前一种的基础上,用元素交换代替掉元素右移。
代码嘛? 小二在这里就不给了,读者们自己也该去敲敲代码了,每天敲敲代码,神清气爽,倍儿爽!   哈哈~~~@

下面想说的一点就是半个月前看到的别人问的一个问题,于是去网上看了一些资料。有个概念叫“不可变类”。

2、不可变类
java自带的如:String、还有其余包装类Integer、Double都是不可变类。所谓不可变,简单的说就是其在创建对象之后,其属性值将不能在对象层面上发生改变。
如果要改变它的值,那肯定就是另外一个对象了。不知道这样通俗的理解会不会引来 嘲讽 0.0
这也是一个面试时可能会接触的知识点,所以直接上代码掩演示了:

package net.mldream;

public final class NoChangeClass {
	/*
	 * 如何创建一个不可变类 四步骤
	 */
	//1、所有成员都是Private的
	private String userName ;
	private int[] myArray ;
	//2、不对外提供对成员进行改变的方法,如setUserName(..)、setMyArray(..)等
	
	//3、确保所有的类方法都不能被重载,有两种方法。
	//一:使用final Class(强不可变类)
	//二:将该类的所有方法加上final(弱不可变类)
	public String toString() { 
		StringBuffer sb = new StringBuffer("This is : ");
		sb.append(this.userName+" Number are:") ;
		for (int i = 0; i < myArray.length; i++) { 
			sb.append(myArray[i] + " ");
		}
		return sb.toString();
	}
	//4、如果类的某一个成员变量不是原始类型(primitive)或者不可变类,
	//则必须通过在成员初始化(in)或get方法(out)时通过深度复制(clone)方法,确保类的不可变
	public NoChangeClass(int[] myArray,String userName) {
		this.myArray = myArray.clone();
		this.userName = userName ;
	}

	public static void main(String[] args) {
	}
}

有兴趣的读者一定要自己去试试,并且能够很好的理解通透其中的原理实现。 如果有什么不理解的,也可以来和我交流。。
欢迎欢迎~~~~~   今天就到这里吧~  Good Good study,Day Day up!

抱歉!评论已关闭.