02-Java 数组和排序算法
一、Java 数组
1、数组定义:数组是有序数据的集合,数组中的每个元素具有相同的数组名和下标来做唯一标识。
2、数组的分类:一维、二维、三维。
3、数组声明及内存分配:
为数组分配内存空间:如果不分配内存,将不能访问它的任何元素。我们使用new关键字来为数组分配内存空间。
int arrayDemo[]; //数组的声明形式1
int[] score; //数组的声明形式2
score=new int[3]; //为数组开辟内存空间,实例化
for(int i=0;i<score.length;i++){
score[i]=i*2+1;
} for(int i=0;i<score.length;i++){
System.out.println(score[i]);
} System.out.println(score.length);
4、数组静态初始化:
(1)数组初始化分为两种方式:
a.动态初始化
b.静态初始化
(2)之前我们所创建的数组,所采用的方式都是动态初始化,也就是所有的内容不会具体指定,都是默认值。
(3)静态初始化是指:在数组创建之初直接指定其内容。
//静态初始化
int score[]={2,5,6,4,6,7}; //声明
for(int i=0;i<score.length;i++){
System.out.println(score[i]); }
5、数组的使用
(1)求最大值、最小值:
int score[]={43,34,5,66,12};
int max,min;
max=min=score[0];
for (int i = 0; i < score.length; i++) {
if(score[i]>max){
max=score[i];
}
if(score[i]<min){ min=score[i];
}
}
System.out.println("最大值:"+max);
System.out.println("最小值:"+min);
(2)冒泡排序
int score[]={12,45,23,10,300};
for (int i = 0; i < score.length-1; i++) {
for (int j = i+1; j < score.length; j++) {
if(score[i]<score[j]){
int temp =score[i];
score[i]=score[j];
score[j]=temp;
}
}
System.out.print("第"+(i+1)+"排序:");
for (int j = 0; j < score.length; j++) {
System.out.print(score[j]+",");
}
System.out.println("");
}
for (int i = 0; i < score.length; i++) {
System.out.println(score[i]);
}
第1排序:300,12,23,10,45,
第2排序:300,45,12,10,23,
第3排序:300,45,23,10,12,
第4排序:300,45,23,12,10,
300
45
23
12
10
6、Java二维数组声明内存分配介绍及使用:
二维数组的声明和一维数组类似,内存分配也是使用new关键字。
声明:type arrayName[][];
初始化:arrayName[][] = new type[行][列];
二、排序算法
(一)冒泡排序
冒泡排序是一种简单的排序算法。冒泡排序将一个列表中的两个元素进行比较,并将最小的元素交换到顶部。从最底部的元素开始比较,两个元素中较小的会冒到顶部,而较大的会沉到底部,该过程将被重复执行,直到所有元素都被排序。
以如上图所示的冒泡排序为例,每次比较相邻的两个数值,值小的交换到前面,每轮结束后值最大的数交换到了最后。第一轮需要比较4次;第二轮需要比较3次;第三轮需要比较2次;第四轮只需要比较1次。
那么如何用二重循环将5个数排序呢?5个数存放在一维数组中,外层循环控制比较多少轮,循环变量为i;内层循环控制每轮比较多少次,循环变量为j,如下图所示。
下面是通过二重循环来实现的冒泡排序,实现代码如下:
public class BubbleSort {
/** * @param args */
public static void main(String[] args) {
// TODO Auto-generated method stub
int a[]={16,25,9,90,23};
System.out.println("排序之前的数组是:");
printArray(a);
for (int i = 0; i < a.length-1; i++) {
for (int j = 0; j < a.length-1-i; j++) {
//判断两个数的大小
if (a[j]>a[j+1]) {
int temp=a[j+1];
a[j+1]=a[j];
a[j]=temp;
}
}
}
System.out.println("\n排序后的数组是: ");
printArray(a);
}
public static void printArray(int[] array){
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]+" ");
}
}
}
结果截图为:
稳定性分析:
如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个元素相邻起来,最终也不会交换它俩的位置,所以相同元素经过排序后顺序并没有改变。所以冒泡排序是一种稳定排序算法。
(二)插入排序
假设有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候,就要用到一种新的排序方法——插入排序法。
插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据。
插入排序算法类似于玩扑克时抓牌的过程,玩家每拿到一张牌,都要插入到手中已有的牌里(这些手牌已经排好序),使之从小到大排好序,如下图所示(该图出自《算法导论》)。
对一个数组进行插入排序的编程也是基于这个道理,但与插入扑克牌有一点不同,不可能在两个相邻的存储单元之间再插入一个单元,因此要将插入点之后的数据依次往后移动一个单元。如对一个数组{15, 3, 56, 1, 78, 12, 7, 99, 123, 90, 63}运用插入排序进行操作,操作的步骤解析如图4.24所示。
从上图可了解插入算法的过程:比较a[0]和a[1]的值,然后再比较a[2]与a[1]的大小。小的在前,大的在后。
代码实现如下:
package com.sort.insert; public class InsertSort { /** * @param args */
public static void main(String[] args) {
int[] a={15, 3, 56, 1, 78, 12, 7, 99, 123, 90, 63};
System.out.println("排序之前:");
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+" ");
}
//从数组的第二个元素开始循环将数组中的元素插入
for (int i = 1; i < a.length; i++) {
//设置数组中的第2个元素为第一次循环待插入元素
int temp = a[i];
int j;
for (j = i-1; j>=0 && a[j]>temp; j--) {
//如果要插入的元素小于第j个元素,就将第j个元素向后移动。将大于temp的往后移动一位
a[j+1] = a[j];
}
//直到要插入的元素不小于第j个元素,将temp插入到数组中
a[j+1] = temp;
}
System.out.println("\n排序之后:");
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+" ");
}
}
public static void printArray(int[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]+" ");
}
}
private static void swap(int x[],int a,int b) {
int t=x[a];
x[a]=x[b];
x[b]=t;
}
public static int[] insertSort(int[] a) {
for (int i = 0; i < a.length; i++) {
for (int j = 0; j>0 && a[j-1]>a[j]; j++) {
swap(a, j, j-1);
}
}
return a;
}
}
结果截图:
稳定性分析:
如果遇见一个与插入元素相等的,那么把待插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序仍是排好序后的顺序,所以插入排序是稳定的。
(三)快速排序(冒泡的改进)
快速排序是一种分而治之的算法。它的基本思想是:将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据要小,然后再按这方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此实现整个数据变成有序序列。
假设要排序的数组是a[0] ... a[n],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。一趟快速排序的算法如下。
(1) 设置两个变量i、j,排序开始的时候i=1,j=n。
(2) 以第一个数组元素作为关键数据,赋值给x,即x=a[0]。
(3) 从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于x的值,两者交换。
(4) 从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于x的值,两者交换。
(5) 重复第3、4步,直到i=j。
上例中的数组a用快速排序进行操作的情况如下图所示:
代码实现如下:
package com.sort.quick;
public class QuickSort {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("排序之前的数组:");
int [] a={15, 3, 56, 1, 78, 12, 7, 99, 123, 90, 63};
printArray(a);
System.out.println("\n排序后的数组是:");
quickSort(a);
printArray(a);
}
/*把整个序列看做一个数组,把第零个位置看做中轴,和最后一个比,如果比它小交换,比它大不做任何处理;
交换了以后再和小的那端比,比它小不交换,比他大交换。
这样循环往复,一趟排序完成,左边就是比中轴小的,右边就是比中轴大的,然后再用分治法,分别对这两个独立的数组进行排序。*/ //先取得中轴的位置
public static int getMiddle (int[] list,int low,int high) {
int temp=list[low];//数组的第一个作为中轴
while (low<high) {
while (low<high&&list[high]>temp) {
high--;
}
list[low]=list[high]; //比中轴小的记录移到低端
while (low<high&&list[low]<temp) {
low++;
}
list[high]=list[low]; //比中轴大的记录移到高端
}
list[low]=temp; //中轴记录到尾
return low; //返回中轴的位置
} //以递归的形式进行分治排序算法
public static void recursionQuick(int[] list,int low,int high) {
if (low<high) {
int middle=getMiddle(list, low, high); //将list数组进行一分为二
recursionQuick(list, low, middle-1); //对低字表进行递归排序
recursionQuick(list, middle+1, high); //对高字表进行递归排序
}
}
//快速排序实现
public static void quickSort(int[] list){
if (list.length>0) {
recursionQuick(list, 0, list.length-1);
}
}
//打印出数组
public static void printArray(int[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i]+" ");
}
}
}
结果截图:
稳定性分析:
快速排序有两个方向,左边的i下标一直往右走(当条件a[i] <= a[center_index]时),其中center_index是中枢元素的数组下标,一般取为数组第0个元素。而右边的j下标一直往左走(当a[j] > a[center_index]时)。如果i和j都走不动了,i <= j, 交换a[i]和a[j],重复上面的过程,直到i>j。交换a[j]和a[center_index],完成一趟快速排序。在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为 5 3 3 4 3 8 9 10 11 。现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱。所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j]交换的时刻。
(四)选择排序
其指导思想是先并不急于调换位置,先从a[0]开始逐个检查,看哪个数最小,就记下该数所在的位置p,等一躺扫描完毕,再把a[p]和a[1]对调,这时a[0]~a[9]最小的数据就换到了最前面的位置。算法的步骤如下:
(1) 先假设a[0]的数最小,记下此时的位置p。
(2) 依次把a[p]和a[i](i从2变化到9)进行比较,每次比较时,若a[i]的数比a[p]中的数小,则把i的值赋给p,使p总是指向当前所扫描过的最小数的位置,也就是说a[p]总是等于所有扫描过的数中最小的那个数。在依次一一比较后,p就指向10个数中最小的数所在位置,即a[p]就是10个数中最小的那个数。
(3) 把a[p]和a[0]的数对调,那么最小的数就在a[0]中了,也就是在最前面了。
如果现在重复此算法,但每重复一次,进行比较的数列范围就向后移动一个位置,即第二遍比较时范围就从第2个数一直到第n个数,在此范围内找最小的数的位置p,然后把a[p]与a[2]对调,这样从第2个数开始到第n个数中,最小数就在a[2]中了,第三遍就从第3个数到第n个数中去找最小的数,再把a[p]与a[3]对调……此过程重复n-1次后,就把a数组中n个数按从小到大的顺序排好了。这种排序的方法就是选择排序法。如果用图形来描述选择排序的过程,如下图所示:
代码实现如下:
package com.sort.select; public class SelectSort {
public static void printArray(int[] c) {
for (int i = 0; i < c.length; i++) {
System.out.print(" "+c[i]);
}
}
/*** @param args*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("选择排序之前的数组:");
int [] a={15, 3, 56, 1, 78, 12, 7, 99, 123, 90, 63};
printArray(a);
System.out.println("\n选择排序后的数组是:");
selectSort(a);
printArray(a);
}
public static void selectSort(int[] list) {
if (list==null || list.length<=0) {
return;
}
for (int i = 0; i < list.length; i++) {
int min=i; //将当前下标定义为最小值的下标
for (int j = i+1; j < list.length; j++) {
if (list[min]>list[j]) { //如果有小于当前最小值的关键字
min=j; //将此关键字的下标值赋值给min
}
}
if (i!=min) { //若min不等于i,说明找到最小值,交换
int temp=list[min];
list[min]=list[i];
list[i]=temp;
}
}
}
}
结果截图:
稳定性分析:
举个例子:序列5 8 5 2 9, 我们知道第一趟选择第1个元素5会与2进行交换,那么原序列中两个5的相对先后顺序也就被破坏了。所以选择排序不是一个稳定的排序算法。
所有排序算法的比较:
三、增强for 循环
1.在Java SE 5.0之前,输出一列数据可以用如下方法:
int[] arr = {1, 2, 3, 4, 5};
for(int i=0; i<arr.length; i++)
System.out.println(arr[i]);
2.但在Java SE 5.0之后,提出了一个增强for循环的语句,语法为:
for(type 变量名 : 集合变量名) {...}
用这个增强for循迭代arr数组的代码如下:
for(int temp : arr)
System.out.println(temp);
其中,temp是一个迭代变量,它必须在()中定义,arr是集合变量,它可以是数组或实现了Iterable接口的集合类。
02-Java 数组和排序算法的更多相关文章
- Java数组的排序算法
在Java中,实现数组的排序算法有很多,如冒泡排序法.选择排序法.直接插入法和快速排序法等.下面介绍几种排序算法的具体 实现. 本文引用文献:Java必须知道的300个问题. 1.冒泡排序法 1.1 ...
- Java中的排序算法(2)
Java中的排序算法(2) * 快速排序 * 快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists). * 步骤为: * 1. 从数 ...
- java实现各种排序算法
java实现各种排序算法 import java.util.Arrays; public class SomeSort { public static void main(String[] args) ...
- Shell数组以及排序算法(冒泡、直接选择、反转)
Shell数组以及排序算法(冒泡.直接选择.反转) 目录 Shell数组以及排序算法(冒泡.直接选择.反转) 一.数组概述 1. 数组的定义 2. 下标的定义 3. 数组的特点 4. 数组定义的方法 ...
- java基础---数组的排序算法(3)
一.排序的基本概念 排序:将一个数据元素集合或序列重新排列成按一个数据元素某个数据项值有序的序列 稳定排序:排序前和排序后相同元素的位置关系与初始序列位置一致(针对重复元素来说,相对位置不变) 不稳定 ...
- java se系列(四) 函数、数组、排序算法、二分法、二维数组
1 函数 1.1 数的概述 发现不断进行加法运算,为了提高代码的复用性,就把该功能独立封装成一段独立的小程序,当下次需要执行加法运算的时候,就可以直接调用这个段小程序即可,那么这种封装形形式的具体表 ...
- Java实现常见排序算法
常见的排序算法有冒泡排序.选择排序.插入排序.堆排序.归并排序.快速排序.希尔排序.基数排序.计数排序,下面通过Java实现这些排序 1.冒泡排序 package com.buaa; import j ...
- java实现八大排序算法
Arrays.sort() 采用了2种排序算法 -- 基本类型数据使用快速排序法,对象数组使用归并排序. java的Collections.sort算法调用的是归并排序,它是稳定排序 方法一:直接插入 ...
- Java常用的排序算法三
Merge Sort :归并排序:用递归的思想,分解成单个元素的排序,在归并 代码: import java.util.*; public class MergeSort { public stati ...
随机推荐
- .NET快速开发平台(DevExpress)免费下载
Express开发的eXpressApp Framework为简单快速实现商业应用的提供了有效的手段.强大的模块化结构支持跨平台的特定域扩展.典型应用实例包括:商业/销售/客户关系管理系统,项目,文档 ...
- Http请求与响应格式
原文:http://www.cnblogs.com/z941030/p/4699779.html Http协议对浏览器发出的Request格式以及对Web服务器发出的Response格式有具体的规定. ...
- linux命令:rmdir
1.命令介绍: rmdir只能用来删除空目录,删除某目录时必须对其父目录有读权限. 2.命令选项: rmdir [选项] 目录 3.命令参数: -p --parent 递归删除目录dirname,当子 ...
- 神奇彩带KMP
描述 有两条彩带A,B,如果能制作出一条彩带,这条彩带既是彩带A的前缀,又是彩带B的后缀,称之为神奇彩带 草滩小王子想送一条最长的神奇彩带给拉面女神 给你两条彩带,你能找到最大的神奇彩带的长度是多少吗 ...
- java作业7
(1)阅读以下代码(CatchWho.java),写出程序运行结果: (2)写出CatchWho2.java程序运行的结果 (3)请先阅读 EmbedFinally.java示例,再运行它,观察其输出 ...
- 关于oracle出现ORA-06143:连接未打开 解决方案
原因:程序所在的路径中含有()和中文 用plsql连接正常,连接字符串也检查不出毛病,换到另一个程序照样使用,折腾了半天,最后才发现程序所在的路径中含有()和中文,所以可能导致出现这种很难排查的问题出 ...
- c#使用正则表达式替换html标签
/// <summary> /// 去除HTML标记(用正则彻底去除HTML\CSS\script代码 ) /// </summary> /// <param name= ...
- Selenium Waits
Selenium高级功能包含查找等待, Selenium的查找等待有两种方式, 隐式等待(Implicit Waits)和显示等待(Explicit Waits): 这里写下我对两者的理解, 1. 隐 ...
- c++学习笔记4:如何写好注释
1.单行注释一般放在语句的上方: // cout and endl live in the iostream library std::cout << "Hello world! ...
- mysql样例数据库employees
Oracle和sqlserver都有基于员工信息的样例数据库,同样mysql上也是有的. 给出一个连接地址https://github.com/datacharmer/test_db. 下载后直接调用 ...