数据结构与算法2——数组

  数组是应用最广泛的数据存储结构。它被植入到大部分编程语言中。大部分数据结构都有最基本的四个操作:插入、删除、查找、修改。对于这四种操作每一种数据结构都有相应的算法。算法和数据结构因此就是非常紧密的相联系的。

1 数组例子                                                           

  数组的每一个元素必须是连续,也就是中间没有洞。就是说第一个元素和第三个元素有值,但不允许第二个元素是空的。

 1 package chapter2;
 2 
 3 public class Array {
 4     public static void main(String[] args){
 5         //创建一个数组
 6         long[] arr;
 7         arr = new long[100];
 8         int nElems = 0;
 9         int j;
10         long searchKey;
11         arr[0] = 99;
12         arr[1] = 11;
13         arr[2] = 22;
14         arr[3] = 33;
15         arr[4] = 55;
16         arr[5] = 66;
17         arr[6] = 44;
18         arr[7] = 77;
19         arr[8] = 23;
20         arr[9] = 88;
21         nElems = 10;
22         //输出前10位数组元素
23         for(j = 0; j < nElems; j++){
24             System.out.print(arr[j] + " ");
25         }
26         System.out.println();
27         //查找数组的一个元素值为55的元素
28         searchKey = 55;
29         for(j = 0; j < arr.length; j++){
30             if(arr[j] == searchKey){
31                 break;
32             }
33         }
34         if(j == nElems){
35             System.out.println("Can't find the element");
36         }else{
37             System.out.println("find the element " + searchKey + " at index " + (j + 1) );
38         }
39         //删除指定元素
40         searchKey = 66;
41         for(j = 0; j < arr.length; j++){
42             if(arr[j] == searchKey){
43                 break;
44             }
45         }
46         for(int k = j; k < nElems; k++){
47             arr[k] = arr[k+1];
48         }
49         nElems--;
50         //输出删除后的数组
51         for(j = 0; j < nElems; j++){
52             System.out.print(arr[j] + " ");
53         }
54     }
55 }
56 
57 输出结果:
58 99 11 22 33 55 66 44 77 23 88 
59 find the element 55 at index 5
60 99 11 22 33 55 44 77 23 88 

2 将程序划分成类                                           

上面的程序包含了一个很大的方法,通过将程序划分成类以后,并且将其中的方法模块化,这样程序看起来更加有条理。

 1 package chapter2;
 2 class ArrayMethod{
 3     private long[] arr;
 4     private int nElems;
 5     public ArrayMethod(int max){
 6         arr = new long[max];
 7         nElems = 0;
 8     }
 9     public void insert(long value){
10         arr[nElems] = value;
11         nElems++;
12     }
13     public boolean find(long searchKey){
14         //查找数组的一个元素值为searchKey的元素
15         int j;
16         for(j = 0; j < arr.length; j++){
17             if(arr[j] == searchKey){
18                 break;
19             }
20         }
21         if(j == nElems){
22             return false;
23         }else{    
24             return true;
25         }
26     }
27     //删除指定元素
28     public boolean delete(long searchKey){
29         int j;
30         for(j = 0; j < arr.length; j++){
31             if(arr[j] == searchKey){
32                 break;
33             }
34         }
35         for(int k = j; k < nElems; k++){
36             arr[k] = arr[k+1];
37         }
38         nElems--;
39         return true;
40     }
41     //输出数组
42     public void display(){
43         //输出前10位数组元素
44         for(int j = 0; j < nElems; j++){
45             System.out.print(arr[j] + " ");
46         }
47         System.out.println();
48     }
49 }
50 class HighArray {
51 
52     public static void main(String[] args){
53         int maxSize = 100;
54         ArrayMethod arr = new ArrayMethod(maxSize);
55         arr.insert(99);
56         arr.insert(11);
57         arr.insert(22);
58         arr.insert(33);
59         arr.insert(55);
60         arr.insert(66);
61         arr.insert(44);
62         arr.insert(77);
63         arr.insert(23);
64         arr.insert(88);
65         //输出数组
66         arr.display();
67         //查找值为55的元素
68         long searchKey = 55;
69         if(arr.find(searchKey)){
70             System.out.println("find the element ");
71         }else{
72             System.out.println("Can't find the element");
73         }
74         //删除指定元素
75         searchKey = 22;
76         if(arr.delete(searchKey)){
77             System.out.println("Delete the element successfully ");
78         }else{
79             System.out.println("Can't find the element");
80         }
81         //输出删除元素后的数组
82         arr.display();
83     }
84 }

3 有序数组                                                     

  假设一个数组,其中的数据项按关键字升序排列,即最小值在下标为0的单元上,每一个单元都比前一个单元的值大。这种数组被称为有序数组。

  当向这种数组中插入数据项时,需要为插入操作找到正确的位置:刚好在稍小值的后面,稍大值的前面。然后将所有比待茶数据项的值向后移以便腾出空间。
  将数据按顺序排列的好处之一就是可以通过二分法查找显著地提高查找速度。但缺点是降低了插入操作的速度。

4 线性查找                                                     

  默认情况下是线性查找,线性查找和未经排序的数组的查找操作相似。

5 二分查找                                                     

  当使用二分查找时就体现有序数组的好处,这种查找比线性查找快很多,尤其是对大数组来说更为显著。
  二分查找首先从要查找的范围确定一个中位数,然后比较要找的数和中位数的大小关系,确定更小的范围,依次递归,知道找到那个数。

 

 

 将数目进行放大,可以发现二分查找是极为优秀的

5.1 有序数组的二分搜索代码   

二分查找是将数组数据项范围不断对半分隔来查找特定的数据项。方法如下所示:

  1 package chapter2;
  2 class ArrayMethod{
  3     private long[] arr;
  4     private int nElems;
  5     public ArrayMethod(int max){
  6         arr = new long[max];
  7         nElems = 0;
  8     }
  9     public void insert(long value){
 10         arr[nElems] = value;
 11         nElems++;
 12     }
 13     //二分查找法
 14     public int halfFind (long searchKey){
 15         int lowerBound = 0;
 16         int upperBound = nElems - 1;
 17         int curIn;
 18         while(true){
 19             curIn = (lowerBound + upperBound)/2;
 20             if(arr[curIn] == searchKey){
 21                 return curIn;
 22             }else if(lowerBound >= upperBound){
 23                 return nElems;
 24             }else{
 25                 if(arr[curIn] > searchKey){
 26                     upperBound = curIn - 1;
 27                 }else{
 28                     lowerBound = curIn + 1;
 29                 }
 30             }    
 31         }
 32     }
 33     public int size(){
 34         return nElems;
 35     }
 36     public boolean find(long searchKey){
 37         //查找数组的一个元素值为searchKey的元素
 38         int j;
 39         for(j = 0; j < arr.length; j++){
 40             if(arr[j] == searchKey){
 41                 break;
 42             }
 43         }
 44         if(j == nElems){
 45             return false;
 46         }else{    
 47             return true;
 48         }
 49     }
 50     //删除指定元素
 51     public boolean delete(long searchKey){
 52         int j;
 53         for(j = 0; j < arr.length; j++){
 54             if(arr[j] == searchKey){
 55                 break;
 56             }
 57         }
 58         for(int k = j; k < nElems; k++){
 59             arr[k] = arr[k+1];
 60         }
 61         nElems--;
 62         return true;
 63     }
 64     //输出数组
 65     public void display(){
 66         //输出前10位数组元素
 67         for(int j = 0; j < nElems; j++){
 68             System.out.print(arr[j] + " ");
 69         }
 70         System.out.println();
 71     }
 72 }
 73 class HighArray {
 74 
 75     public static void main(String[] args){
 76         int maxSize = 100;
 77         ArrayMethod arr = new ArrayMethod(maxSize);
 78         arr.insert(99);
 79         arr.insert(11);
 80         arr.insert(22);
 81         arr.insert(33);
 82         arr.insert(55);
 83         arr.insert(66);
 84         arr.insert(44);
 85         arr.insert(77);
 86         arr.insert(23);
 87         arr.insert(88);
 88         //输出数组
 89         arr.display();
 90         //查找值为55的元素
 91         long searchKey = 35;
 92 //        if(arr.find(searchKey)){
 93 //            System.out.println("find the element ");
 94 //        }else{
 95 //            System.out.println("Can't find the element");
 96 //        }
 97         //二分法查找
 98         if(arr.halfFind(searchKey) != arr.size()){
 99             System.out.println("Find it");
100         }else{
101             System.out.println("Can't find it");
102         }
103 //        //删除指定元素
104 //        searchKey = 22;
105 //        if(arr.delete(searchKey)){
106 //            System.out.println("Delete the element successfully ");
107 //        }else{
108 //            System.out.println("Can't find the element");
109 //        }
110         //输出删除元素后的数组
111         arr.display();
112     }
113 }

5.2 有序数组的优点              

  使用有序数组最主要的好处是查找的速度比无序数组快多了。不好的方面是在插入操作中由于所有靠后的数据都需要移动以腾开空间,所以速度较慢。有序数组和无序数组中的删除操作都很慢,这是因为数据项必须向前移动来填补已删除数据项的洞。有序数组在查找频繁的情况下十分有用,但若是插入和删除较为频繁时,则无法高效工作。

6 大O表示法                     

  计算机科学中评价算法效率的方法称为大O表示法。比较算法时候通常会说"算法A比算法B快2倍",这种说法意义不大。因为数据项的变化会对排序造成一定很大影响。有可能数据项增加50%,算法A就比B快了3倍,或者可能只有一半的数据项,A和B的速度是相同的。

6.1 无序数组的插入:常数     

  无序数组的插入是我们到现在为止所见过的算法中唯一一个与数组项个数无关的算法。新数据项总被放在下一个有空的地方,a[nElems],然后nElems增加。无论数组中的数据项个数N有多大,一次插入总是用相同的时间。我们可以说向一个无序数组中插入一个数据项的时间T是一个常数K
T=K
在现实情况中,插入所需的实际时间与以下这些因素有关:微处理器,编译程序生成程序代码的效率,等等。

6.2 线性查找:与N成正比     

  在数组数据项的线性查找中,我们已经发现寻找特定数据项所需的比较平均次数为数据项总数的一半。因此设N为数据项总数,搜索时间T与N的一半成正比:
T=K*N/2
  同插入一样,若要得到方程中K的值,首先需要对某个N值的查找进行计时,然后用T来计算K。当得到K后,便可以对任意N的值来计算T。将2并入K可以得到更方便的公式,新K值等于原先的K除以2即
T=K*N
这个方程说明平均线性查找时间与数组的大小成正比。即如果一个数组增大两倍,则所花费的查找时间也会相应地增长两倍。

6.3 二分查找:与log(N)成正比

  同样,我们可以为二分查找指定出一个与T和N有关的公式:T=K*log2(N)
  实际上,由于所有的对数和其他对数成比例(比如从底数2转换到底数为10需乘以3.322),也可以将这个为常数的底数也并入K。由此不必指定底数:
T=K*log(N)
不要常数
  大O表示法同上面的公式比较类似,但它省去了常数K。当比较算法时,并不在乎具体的微处理器或编译器;真正需要比较的是对应不同的N值,T是如何变化的,而不是具体的数字,因此不需要常数。
  大O表示法使用大写字母O,可以认为其含义是order of(大约是)。我们可以使用大O表示法来描述线性查找使用了O(N)级时间,二分查找使用了O(logN)级时间。向一个无序数组中的插入使用了O(1),或常数级时间。

下表总结的是讨论过的算法的运行时间


  大O表示法的实质并不是对运行时间给出实际值,而是表达了运行时间是如何受数据项个数所影响的。除了实际安装后真正去测量一次算法的运行时间之外,这可能是对算法进行比较的最有意义的方法了。

6.4 几种算法时间复杂度的对比 

 

7 为什么不用数组表示一切?                               

  仅使用数组似乎就可以完成所有工作,为什么不用它们来进行所有数据存储呢?我们已经见到了许多关于数组的缺点。在一个无序数组中可以很快进行插入(O(1)),但是查找却要花费较慢的O(N)时间。在一个有序数组中可以查找得很快,用O(logN)的时间,但插入却花费了O(N)时间。对于这两种数组而言,由于平均半数的数据项为了填补"空洞"必须移动,所以删除操作平均需要O(N)时间。
  如果有一种数据结构进行任何如插入、删除和查找的操作都很快(理想的O(1)或是O(logN)时间),那就好了。后面我们会介绍类似的数组,但这是以程序的复杂度为代价的。
  另外数组被创建后,占用内存长度是确定的,无法进行修改,这样的话,如果创建的长度过大,但是实际需要的很少就会造成内存浪费,如果创建的长度过小,就会造成溢出,无法弹性使用。

转载于:https://www.cnblogs.com/people/p/3188437.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/378094.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 167. 两数之和 II - 输入有序数组 思考分析

目录1、暴力&#xff0c;超时2、双指针滑动窗口条件限制 AC3、观看题解&#xff08;吸取他人经验&#xff09;1、二分查找2、双指针3、双指针二分查找给定一个已按照升序排列 的有序数组&#xff0c;找到两个数使得它们相加之和等于目标数。 函数应该返回这两个下标值 index1 …

敏捷开发用户故事系列之七:用户故事与MVC

这是用户故事系列的第七篇。&#xff08;之一&#xff0c;之二&#xff0c;之三&#xff0c;之四&#xff0c;之五&#xff0c;之六&#xff0c;之七&#xff0c;之八&#xff0c;之九&#xff09;用户故事和MVC没有关系&#xff0c;因为MVC是实现方法&#xff0c;因此在思考用…

七、规则组织的衍生组织——菱形斜纹组织数学模型的建立

基础概念公式推到可参考该专栏下的前几篇博文。 菱形斜纹组织图&#xff1a; 分析&#xff1a;首先3上2下2上1下&#xff0c;飞数为1&#xff0c;右斜。kw8表示从左下角开始往上数8格为纬峰所在位置&#xff1b;kj8表示从左上角开始往右数8格为经峰所在位置。 这样就将菱形斜…

显卡测试软件毛毛虫,超龙超龙,与众不同,顶流配备,散热一流,3070Ti超龙旗舰版评测...

可能大家都没想到此次显卡荒会持续近一年&#xff0c;还是出现国家级干涉才将这股“歪风”刹住了。而且也仅仅算是刹住了大陆的速度&#xff0c;主要踩死刹车的应该就是黄大厨。他从5月初推出的新核心就采取了出厂即锁算力的做法&#xff0c;但是即便如此&#xff0c;那些看着高…

八、非规则组织分析及其数学模型——平纹变化组织

非规则组织顾名思义&#xff0c;无法通过一个数学模型来描述所有的非规则组织、对于每一个具体的非规则组织而言&#xff0c;其也有一定的规律性可循&#xff0c;即可通过分析每一个具体的非规则组织的组织点运动规律来建立相应的数学模型。 一、平纹变化组织 平纹变化组织即…

怎么看xp计算机是32位还是64位,教你查看XP系统的不同32位还是64位详细的步骤

电脑中使用的不同的版本如果安装一些大型的游戏的时候都是有技巧来实现的&#xff0c;那在XP电脑中想要知道的对于不同的32位还是64位的版本的文件操作的时候新手是怎么知道自己安装的软件的版本呢&#xff0c;今天小编就来跟大家分享一下教你查看XP系统的不同32位还是64位详细…

LeetCode 27.移除元素 思考分析

题目 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长…

九、非规则组织分析及其数学模型——曲线斜纹组织

曲线斜纹组织图&#xff1a; 因为其形状酷似抛物线&#xff0c;抛物线又是曲线中的一种&#xff0c;故称为曲线斜纹组织。 特点&#xff1a;1&#xff0c;每一根经纱上的组织点运动规律不变 2&#xff0c;飞数是变化的&#xff0c;故也称为变飞数组织 飞数满足的两个条件&…

计算机公式column,函数公式的左膀右臂:ROW、COLUMN函数知多少

一个公式生成乘法口诀表演示的公式中用到了两个函数&#xff1a;ROW和COLUMN&#xff0c;这两个函数的用途非常广泛&#xff0c;可以配合其他函数实现很多功能(尤其是和VLOOKUP函数)&#xff0c;另外和这两个函数相似的还有ROWS和COLUMNS函数&#xff0c;也顺便介绍下。函数说明…

apache2.4.x三种MPM介绍

三种MPM介绍 Apache 2.X 支持插入式并行处理模块&#xff0c;称为多路处理模块&#xff08;MPM&#xff09;。在编译apache时必须选择也只能选择一个MPM&#xff0c;对类UNIX系统&#xff0c;…

LeetCode 15. 三数之和 思考分析(双指针解)

目录初解&#xff1a;未考虑去重二解&#xff1a;未考虑去重位置三解&#xff1a;AC题目&#xff1a;给你一个包含 n 个整数的数组 nums&#xff0c;判断 nums 中是否存在三个元素 a&#xff0c;b&#xff0c;c &#xff0c;使得 a b c 0 &#xff1f;请你找出所有满足条件且…

十、非规则组织分析及其数学模型——锯齿形斜纹组织

锯齿形斜纹组织图&#xff1a; 分析&#xff1a; 前半齿长度k&#xff0c;表示山谷到山峰的列数&#xff0c;也就是锯齿的宽度&#xff1b; 锯齿飞数s&#xff0c;表示山峰到山峰的行数&#xff0c;也就是锯齿的高度。 起始点相差4格&#xff0c;也就是第一部分整体向上移动…

十一、非规则组织分析及其数学模型——芦席斜纹组织

芦席斜纹组织&#xff1a; 该组织是由左斜和右斜有机的结合在一块的&#xff0c;因为其外观酷似芦席故称之为芦席斜纹组织。 织物组织效果&#xff1a; 所需参数&#xff1a; 其基层组织采用双面加强型斜纹&#xff0c;即分子和分母是相同的组织点&#xff0c;例如2上2下(2个经…

LeetCode 18. 四数之和 思考分析(双指针解)

目录需要注意的几点1、去除剪枝操作2、去重操作的细节code以及效果&#xff1a;题目给定一个包含 n 个整数的数组 nums 和一个目标值 target&#xff0c;判断 nums 中是否存在四个元素 a&#xff0c;b&#xff0c;c 和 d &#xff0c;使得 a b c d 的值与 target 相等&#…

图解DotNet框架之一:编译与执行引擎(上)

众所周知,DotNet框架是非常庞大的,光项目创建时的种类就有WPF,WCF,WF这三种最新的技术,还有以前的Web,WinForm,Service,Mobile等等. 这么复杂和庞大的框架,用文字来描述是远远不够的,所以我准备写一系列图文并茂的文章,把我所知道的所有Net框架中的东西全部串联起来,希望可以给…

【Kissy WaterFall】实行手动加载数据

前言&#xff1a;由于Kissy WaterFall默认是监听滚动事件来实现数据动态加载的&#xff0c;但是有一些情况要用到手动加载数据。以下是使用Kissy WaterFall实现手动加载数据的方法。 最终实现效果&#xff1a;点击”逛更多的商店“会动态加载数据 步骤&#xff1a; 当一页数据加…

web服务器文档根目录在哪里,web服务器根目录在哪

web服务器根目录在哪 内容精选换一换SSL证书通过在客户端浏览器和Web服务器之间建立一条SSL安全通道(访问方式为HTTPS)&#xff0c;实现数据信息在客户端和服务器之间的加密传输&#xff0c;可以防止数据信息的泄露。SSL保证了双方传递信息的安全性&#xff0c;而且用户可以通过…

二、图片加载与保存

一、基本概念 1&#xff0c;什么是图片&#xff1f; 答&#xff1a;图像是结构化存储的数据信息 2&#xff0c;图像的属性 答&#xff1a;1、通道数目&#xff0c;2、宽与高&#xff0c;3、像素数据&#xff0c;4、图像类型 二、加载显示图像并保存 import cv2 import nump…

LeetCode 206. 反转链表 思考分析

题目 反转一个单链表。 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶: 你可以迭代或递归地反转链表。你能否用两种方法解决这道题&#xff1f; 迭代双指针 从某公众号&#xff08;代码随想录&#xff09;搬过来的gif图&…

怎样看虚拟主机的服务器,虚拟主机怎么查看服务器类型

虚拟主机怎么查看服务器类型 内容精选换一换使用华为云提供的公共镜像制作私有镜像时&#xff0c;您需先购买云主机等云资源时镜像选择公共镜像、云服务器类型建议统一选择“s3 (通用计算型)”&#xff0c;在云主机安装部署完商品&#xff0c;然后参照以下方式进行私有镜像制作…