数据结构Java实现01----算法概述

简介:
【正文】 

 

 

一、数据结构涵盖的内容:

1b51b02a-9151-485c-8bf5-74868f49bf06

 

二、算法的基本概念:

1、算法的概念:

Algorithm,是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每一条指令表示一个或者多个操作。

2、算法的特性:

  • 有穷性:指令序列是有限的
  • 确定性:每条语句的含义明确,无二义性
  • 可行性:每条语句都应在有限的时间内完成
  • 输入:零个或者多个输入
  • 输出:一个或者多个输出

3、算法与程序的区别:

程序:

  (program)程序是软件开发人员根据用户需求开发的、用程序设计语言描述的适合计算机执行的指令(语句)序列。

程序包含的四个要素:

数据结构

算法

程序设计方法

编程语言

程序与算法不同。程序是算法用某种程序设计语言的具体实现。程序可以不满足算法的有穷性,比如操作系统也是一种程序,如果你愿意,你的电脑可以一直开着,保持操作系统的运行。

比如:

复制代码
while(true)

{

...

} //是一段程序,但不是一个算法
复制代码

 

4、程序、算法、软件之间的关系:

程序:算法的计算机实现。用某种编程语言实现。

算法:表示问题的解。

软件:程序+文档

如下图所示:

fe13a77a-f221-42ae-b8de-d8fa6ebedbc3

程序设计=数据结构+算 法

 

三、数据类型:

1、数据类型:

是指一个值的集合和定义在集合上的操作集合。例如:java的整数类型(Integer),就不仅仅表示整数数值的集合,还包括对整数类型进行的操作集合,加、减、乘、除、模等操作。

我们通常所指的数据类型是某种高级语言支持的基本数据类型。  比如java的基本数据类型:int、double、float、char等等。

Java中的数据类型:

37b7135d-9806-4305-be74-c2abb4ab5c23

2、抽象数据类型:

一个数学模型以及定义在这个模型上的一组操作(由用户定义,用以表示应用问题的数据模型)。

看起来抽象数据类型和数据类型的定义基本相同。不同点在于:数据类型通常是指某种高级语言的,而抽象数据类型用户重新设计,一种概念。这里的"抽象"的含义在于数学抽象。

  • 原子类型:比如整型
  • 固定聚合类型:比如复数,两个实数确定的次序构成
  • 可变聚合类型:比如汽车类型,构成的成分是不确定的。(因为小轿车、大卡车的构成是不同的)

抽象数据类型抽象的层次越高,那么可复用性也越高。比如:java中的Object是对所有对象的抽象,那么就可以作为所有类的父类。

 

四、抽象数据类型的表示(代码举例):

  • C语言使用结构体
  • Java语言使用类

下面分别用C语言与java语言,来定义学生抽象数据类型。已知学生的信息如下:

复制代码
学号:111222

姓名:生命壹号

性别:男

出生日期:1991-11

专业:电子与通信工程(计算机方向)

电子邮箱:smyhvae@163.com
复制代码

 

1、用C代码定义一个学生类:

test1.c:

复制代码
#include <stdio.h>

//日期结构体
typedef struct 
{
  int year;//
  int month;//
  int day;//
}Date; 

//学生结构体 
typedef struct
{
  char sid[20];//学号
  char name[20];//姓名
  char gender;//性别
  Date birthday;//出生日期 
  char contact[50];//联系方式         
}Students;

void PrintStudentsInfo(Students s)
{
   printf("学号:%s\n",s.sid); 
   printf("姓名:%s\n",s.name);
   printf("性别:%c\n",s.gender);
   printf("出生日期:%d-%d-%d\n",s.birthday.year,s.birthday.month,s.birthday.day);
   printf("联系方式:%s\n",s.contact);      
}

int main()
{
  Students s1;//生成一个学生对象
  Date d1;
  d1.year = 1995;
  d1.month = 6;
  d1.day =30;
  strcpy(s1.sid,"S0001");
  strcpy(s1.name,"张三丰");
  strcpy(s1.contact,"西安市高新四路50号");
  s1.gender = 'M'; 
  s1.birthday = d1;
  PrintStudentsInfo(s1);
  getch();
  return 0;    
}
复制代码

 运行效果:

2468cae2-d71a-4ad9-9f4b-4953f12bdf95

 

 2、用Java代码定义一个学生类:

(1)Student.java:

复制代码
 1 package test1;
 2 
 3 import java.text.SimpleDateFormat;
 4 import java.util.Date;
 5 
 6 /**
 7  * Created by smyhvae on 2015/8/12.
 8  */
 9 public class Student {
10     String num; //学号
11     String name; //姓名
12     char sex; //性别
13     Date birthday; //出生日期
14     String contact; //联系方式
15 
16     public String getNum() {
17         return num;
18     }
19 
20     public void setNum(String num) {
21         this.num = num;
22     }
23 
24     public String getName() {
25         return name;
26     }
27 
28     public void setName(String name) {
29         this.name = name;
30     }
31 
32     public char getSex() {
33         return sex;
34     }
35 
36     public void setSex(char sex) {
37         this.sex = sex;
38     }
39 
40     public Date getBirthday() {
41         return birthday;
42     }
43 
44     public void setBirthday(Date birthday) {
45         this.birthday = birthday;
46     }
47 
48     public String getContact() {
49         return contact;
50     }
51 
52     public void setContact(String contact) {
53         this.contact = contact;
54     }
55 
56     @Override
57     public String toString() {
58 
59         SimpleDateFormat sdf = new SimpleDateFormat("YYYY-mm-dd"); //将Date日期转化为String字符串打印出来
60 
61         return "Student{" +
62                 "num='" + num + '\'' +
63                 ", name='" + name + '\'' +
64                 ", sex=" + sex +
65                 ", birthday=" + sdf.format(birthday) +
66                 ", contact='" + contact + '\'' +
67                 '}';
68     }
69 
70 }
复制代码

 

(2)JavaTest.java:(给学生类赋值并打印出来)

复制代码
 1 package test1;
 2 
 3 import java.text.ParseException;
 4 import java.util.Calendar;
 5 import java.util.Date;
 6 
 7 /**
 8  * Created by smyhvae on 2015/8/12.
 9  */
10 public class JavaTest {
11 
12     public static void main(String[] args) throws ParseException {
13 
14         Student s = new Student();
15         s.setNum("111222");
16         s.setName("生命壹号");
17         s.setSex('男');  //这里面赋值可以用中文
18         s.setContact("smyhvae@163.com");
19 
20         Calendar calendar = Calendar.getInstance();
21         calendar.set(1991, 11, 28);
22         Date date = calendar.getTime();
23         s.setBirthday(date);
24 
25         System.out.println(s.toString());
26 
27     }
28 
29 } 
复制代码

运行效果如下:

5379ace9-02fc-4aa3-84c0-fc3c16269257

  

五、算法的设计目标:

1、算法的设计目标:

(1)正确性:满足具体问题的解,基本目标。

(2)可读性:有利于人去理解算法。

(3)健壮性:输入非法数据,能适当做出处理,不产生莫名其妙的输出。

(4)高效性:包括时间的高效性(时间复杂度)和空间的高效性(空间复杂度)。

2、算法性能指标:

(1)算法的时间效率也称为时间复杂度。

(2)算法的空间效率也称为空间复杂度。

(3)同一问题可用不同算法解决,而一个算法的质量优劣将影响到算法乃至程序的效率。算法分析的目的在于选择合适算法和改进算法。一个算法的评价主要从时间复杂度和空间复杂度来考虑

(4)算法时间的高效性和空间的高效性通常是矛盾的。所有一般只会取一个平衡点。(这里体现的是一种哲学思想,研究计算机,不就是研究时间和空间的概念嘛,鱼与熊掌不可兼得哦)

(5)通常我们假设程序运行在内存中,且内存容量足够使用,所以更多的是讨论时间复杂度

 

六、算法的时间复杂度:

算法的时间复杂度反映了算法执行的时间长短。度量一个算法在计算机上执行的时间通常有两种方式:

  1.事后统计法:

  2.事前分析法:(常用)

    编写算法使用的高级语言

    编程产生的机器语言代码质量

    机器指令执行速度

    问题规模

注:算法的时间复杂度是由最深层嵌套语句的频度决定的。

 

2、O()函数:

  表示算法的时间效率与算法所处理的数据元素个数n函数关系的最常用函数,即O()函数。

定义:

  一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。看下图便知:

6c7a2288-b1a2-4b1a-9858-6c8103b3712d

25edf293-2825-401e-bda1-a6449cea6eca

情况一:T(n)与问题规模n无关

当算法的时间复杂度T(n)与问题规模n无关时,此时算法的时间复杂度T(n)=O(1)。

 

情况二:T(n)与问题规模n有关

例1:设数组a和b在前面部分已经赋值,求如下两个n阶矩阵相乘算法的时间复杂度:

复制代码
for(i=0;i<n;i++)
 {
   for(j=0;j<n;j++)
   {
     c[i][j]=0;  //基本语句1
     for(k=0;k<n;k++)
     {
        c[i][j]=c[i][j]+a[i][k]*b[k][j];//基本语句2
     }
   }
 }
复制代码

 上方代码中:

557f59fb-97fd-4098-afa0-82dfcb2cf250

  

例2:设n为如下算法处理的数据元素个数,求算法时间复杂度。代码如下:

for(i=1;i<=n;i=i*2)
{
   System.out.println(i);
}

 分析:

01e98af6-e6c6-47f2-ab2d-d285baf389de

  

例3:分析冒泡排序算法的时间复杂度。代码如下:

复制代码
//冒泡排序算法
    public static void bubbleSort(int[] data) {

        if (data == null) {
            return;
        }

        for (int i = 0; i < data.length - 1; i++) {
            boolean flag = false;
for (int j = 0; j < data.length - 1 - i; j++) { if (data[j] > data[j + 1]) { int temp = data[j]; data[j] = data[j + 1]; data[j + 1] = temp; flag = true; } }
if (!flag) { return; } } }
复制代码

 时间复杂度分析:

(1)最佳情况下,冒泡排序算法只需要遍历一次就能确定数组已经排序好了,此时的时间复杂度为O(n);

(2)最差情况下,需要进行n-1次遍历,则需进行n(n-1)/2次比较和记录移动,此时冒泡排序算法的时间复杂度T(n)=O(n2)。

 

3、时间复杂度的大小关系:

以下六种计算算法时间的多项式是最常用的。其关系为:

5defd8ca-9d0d-45f7-a85f-5b1aed4d8e04

指数时间的关系为:

ba087e1f-ca41-498a-8b68-be21acc22dca

当n取很大的值时,指数时间算法和多项式时间算法在所需时间上非常悬殊。

小知识:

NP(nondeterministic polynomial)问题:是指算法复杂度难以用多项式表示的问题,算法复杂度通常是n的指数级,常规算法很难求解。

 

七、算法的空间复杂度:

空间复杂度是指算法在运行期间所需要的内存空间的数量级。记作:S(n)=O(f(n)),其中n为问题的规模(或大小)。            

注:由于大部分算法的空间复杂度问题并不严重,并且算法的空间复杂度分析方法和算法的时间复杂度分析方法基本相同,所以一般数据结构只讨论算法的时间复杂度,不讨论算法的空间复杂度。

代码举例:分析如下算法的空间复杂度

复制代码
static void reserse(int[] a,int[] b)
{
   int n= a.length;
   for(int i=0;i<n;i++)
   {
      b[i]=a[n-1-i];
   }
} 
复制代码

上方代码中,当程序调用reserse(a,b)函数时,要分配的内存空间包括:引用a,引用b,局部变量n和局部变量i;

因此f(n)=c;其中c为常量。所以该算法的空间复杂度S(n)=O(1)。

 

八、总结:

算法的时间复杂度和两个因素有关:算法中的最大嵌套循环层数;最大嵌套循环结构中每次循环的次数。

一般来说,具有多项式时间复杂度的算法是可以接受的;具有指数(不是对数)时间复杂度的算法,只有当n足够小时才可以使用。一般效率较好的算法要控制在O(N)或者O(log2 N)

 

相关文章
|
2月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
79 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
2月前
|
存储 Java
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
44 1
|
2月前
|
存储 Java
告别混乱!用Java Map优雅管理你的数据结构
【10月更文挑战第17天】在软件开发中,随着项目复杂度增加,数据结构的组织和管理至关重要。Java中的Map接口提供了一种优雅的解决方案,帮助我们高效、清晰地管理数据。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,有效提升了代码质量和维护性。
83 2
|
2月前
|
存储 Java 开发者
Java Map实战:用HashMap和TreeMap轻松解决复杂数据结构问题!
【10月更文挑战第17天】本文深入探讨了Java中HashMap和TreeMap两种Map类型的特性和应用场景。HashMap基于哈希表实现,支持高效的数据操作且允许键值为null;TreeMap基于红黑树实现,支持自然排序或自定义排序,确保元素有序。文章通过具体示例展示了两者的实战应用,帮助开发者根据实际需求选择合适的数据结构,提高开发效率。
63 2
|
18天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
36 6
|
24天前
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
|
2月前
|
存储 算法 Java
Java 中常用的数据结构
【10月更文挑战第20天】这些数据结构在 Java 编程中都有着广泛的应用,掌握它们的特点和用法对于提高编程能力和解决实际问题非常重要。
30 6
|
2月前
|
存储 Java 开发者
Java中的Map接口提供了一种优雅的方式来管理数据结构,使代码更加清晰、高效
【10月更文挑战第19天】在软件开发中,随着项目复杂度的增加,数据结构的组织和管理变得至关重要。Java中的Map接口提供了一种优雅的方式来管理数据结构,使代码更加清晰、高效。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,帮助开发者告别混乱,提升代码质量。
30 1
|
2月前
|
存储 算法 Java
Java常用的数据结构
【10月更文挑战第3天】 在 Java 中,常用的数据结构包括数组、链表、栈、队列、树、图、哈希表和集合。每种数据结构都有其特点和适用场景,如数组适用于快速访问,链表适合频繁插入和删除,栈用于实现后进先出,队列用于先进先出,树和图用于复杂关系的表示和查找,哈希表提供高效的查找性能,集合用于存储不重复的元素。合理选择和组合使用这些数据结构,可以显著提升程序的性能和效率。
|
2月前
|
存储 Java
数据结构第二篇【关于java线性表(顺序表)的基本操作】
数据结构第二篇【关于java线性表(顺序表)的基本操作】
31 6
下一篇
无影云桌面