Re0:Java编程系列-2 经典简单排序的结构

Re0:Java编程系列

作者参加校招,在复习Java的同时,决定开一打系列博客。复习的同时,作者希望能留下材料,方便也服务一些新入门的小伙伴。

本系列文章从基础入手,由简单的功能函数开始,再扩展为项目结构等等。进一步延伸至Java编程的核心思想,封装继承多态

文章从面向功能编程方法开始过渡,手写代码的同时,逐渐向小伙伴揭示Java的编程思想和面向对象编程方法


提示:Java写代码前,需要Java环境和IDE集成环境,作者不赘述,希望小伙伴们提前准备好。


前言

前些天,我细细思考了冒泡排序。
看着它安详的模样,我不禁想起了与它出生入死的兄弟们。
号称三大经典简单排序的它们,冒泡排序,直接插入排序,选择排序,如今也该团聚了。
我摸起手里的鼠标,决定,给它们写个家。


一、项目结构?包?类?

引导:Java是一门十分注重结构的语言,它的项目名称,包名和类名都具有属性分类的意义。

Java项目结构规范需要注意三点:

  • 一般结构 项目{包/包{}}。
  • 项目名称,单词首字母均需要大写。类名中,单词首字母均需要大写。
  • 包名中,单词字母均为小写,并且一般为一个单词。函数名中,第一个单词首字母小写,其余单词首字母大写。

首先在项目结构src下,我们新建几个包,分别为swapselectinsert,并且新建两个类SelectSortInsertSort

规划结构,使得项目结构如图所示。

2-项目结构

src目录是存放Java源代码的地方,我们通过包对不同的类进行区分整理。当然,包中有包也是非常常见,相当于对大概念进行细分。

例如:包名为高中,小包名有高一,高二,高三。

项目开始前,我们对概念抽象越好,包会越细,代码复用率会相当有保证。Java编程,力求一个类写完,它的结构也固定完毕。这是Java编程中一个小点,牵扯重要的原则——开闭原则

不过,很明显的是,我们并没有很好的执行这一原则。因为,我们才刚刚上路,要从实践中出真章。

二、开始敲码!

1.编程思路

这一次,我们需要写两个函数。一个选择排序,一个插入排序。

有了上次冒泡排序的经验,我们依葫芦画瓢,依次分析两个函数的特点。

选择排序:每一轮开始,选择一个元素,并将其移动到合适的位置。

比如,每轮选择出最小的元素,将其下标记下,然后移动到未排序好的首部。

编写函数注意数组元素下标,外循环0 -> length-1顺序执行。

代码如下(示例):

	public int[] selectSort1(int[] array) {
		int temp;
		total = 0;
		//外层循环,意味着排序次数
		for (int i = 0; i < array.length - 1; i++) {
			//假设array[i]元素最小,记录下标
			pos = i;
			//内层循环,意味着比较次数
			for (int j = i; j < array.length; j++) {
				//下标设置为最小
				if (array[j] < array[pos]) {
					pos = j;
				}
			}
			total++;
			//交换元素,将最小值移动到最前
			temp = array[i];
			array[i] = array[pos];
			array[pos] = temp;
		}
		return array;
	}

我们不难发现,每一次排序完成,数组中最小的元素到了数组的首端。而且每一次排序中,我们只交换一次数组元素。

仔细想想,选择排序为什么当下标不变时,不能确定排序完成?

插入排序:将首元素视为有序数组,顺序依次插入元素,最终原数组有序。

插入排序,相当于将新的元素插入到有序的数组中。每一次插入排序时,元素需要找到合适的位置。因此,有序数组元素在整个数组中会多次移动。

编写函数注意数组元素下标,外循环1 -> length顺序执行。

插入排序执行时,依旧每次排好一个元素。

代码如下(示例):

	public int[] insertSort1(int[] array) {
		total = 0;
		//外循环,排序次数,从第二个元素开始
		for (int i = 1; i < array.length; i++) {
			//选择合适位置
			int j = i;
			//记录选中元素值
			temp = array[j];
			//位置选择循环判断条件
			while(j > 0) {
				//判断合适位置的前一个元素值与选中元素值
				if (array[j-1] > temp) {
					//元素后移
					array[j] = array[j-1];
					//选择位置前移
					j--;
				} else {
					//当array[i-1]<temp时,意味着位置合适,跳出循环
					break;
				}
			}
			total++;
			//选中元素值放入合适位置
			array[j] = temp;	
		}
		return array;
	}

2.对比思路

函数编程完毕,我们发现与冒泡函数相比,选择排序和插入排序,都没有能判断数组有序的标志。

为什么冒泡有标志,而选择和插入没有呢?

我们花三分钟思考一下,问题的原因。

  1. 冒泡排序

代码如下(示例):

	public int[] bubbleSort1(int[] array) {
		int temp = 0;
		for (int i = 0; i < array.length - 1; i++) {
			for (int j = 0; j < array.length - i - 1; j++) {
				if(array[j] > array[j+1]) {
					temp = array[j];
					array[j] = array[j+1];
					array[j+1] = temp;
				}
			}
		}
		return array;
	}

冒泡排序中,数组元素的交换,是多次的。每一次排序时,都需要对元素依次进行两两对比。当条件符合时,元素进行交换。

那么,设数列S为a1,a2,a3,...,aN

a2 > a1a3 > a2 一直到aN > aN-1时,数组才不需要交换。同时,通过数学归纳法,我们很容易得出数列S为递增数列。

而对于,选择排序和插入排序,一次只交换一个元素,自然就缺失判断排序完成的标志。

3.验证思路

经过编码,我们有了三个不同的排序函数,是时候验证一下,我们的思路了。

我们在src下新建一个包test,在test包中新建一个SortTest类。

代码如下(示例):

package test;

import insert.InsertSort;
import select.SelectSort;
import swap.BubbleSort;

public class SortTest {
	
	public static void main(String[] args) {
		BubbleSort bubble = new BubbleSort();
		SelectSort select = new SelectSort();
		InsertSort insert = new InsertSort();
		//执行测试
		...
	}
}

鼠标右键,敲击Run,我们来跑程序。


总结

经过了我不懈的努力,终于建好了一个排序算法的家。
有些欣慰,也有些开心。
我们的Java,终于算是入门了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值