Ⅰ 数据结构
何谓数据结构
?
数据结构是在整个计算机科学与技术领域上广泛被使用的术语。它用来反映一个数据的内部构成,即一个数据由那些成分数据构成,以什么方式构成,呈什么结构。数据结构有逻辑上的数据结构和物理上的数据结构之分。逻辑上的数据结构反映成分数据之间的逻辑关系,而物理上的数据结构反映成分数据在计算机内部的存储安排。数据结构是数据存在的形式。 数据结构是信息的一种组织方式,其目的是为了提高算法的效率,它通常与一组算法的集合相对应,通过这组算法集合可以对数据结构中的数据进行某种操作。
?
数据结构主要研究什么?
?
数据结构作为一门学科主要研究数据的各种逻辑结构和存储结构,以及对数据的各种操作。因此,主要有三个方面的内容:数据的逻辑结构;数据的物理存储结构;对数据的操作(或算法)。通常,算法的
?
设计取决于数据的逻辑结构,算法的实现取决于数据的物理存储结构。
?
什么是数据结构?什么是逻辑结构和物理结构?
?
数据是指由有限的符号(比如,"0"和"1",具有其自己的结构、操作、和相应的语义)组成的元素的集合。结构是元素之间的关系的集合。通常来说,一个数据结构DS 可以表示为一个二元组:
?
DS=(D,S), //i.e., data-structure=(data-part,logic-structure-part) 这里D是数据元素的集合(或者是“结点”,可能还含有“数据项”或“数据域”),S是定义在D(或其他集合)上的关系的集合,S = { R | R : D×D×...},称之为元素的逻辑结构。 逻辑结构有四种基本类型:集合结构、线性结构、树状结构和网络结构。表和树是最常用的两种高效数据结构,许多高效的算法可以用这两种数据结构来设计实现。表是线性结构的(全序关系),树(偏序或层次关系)和图(局部有序(weak/local orders))是非线性结构。
?
数据结构的物理结构是指逻辑结构的存储镜像(image)。数据结构 DS 的物理结构 P对应于从 DS 的数据元素到存储区M(维护着逻辑结构S)的一个映射:
?
(PD,S) -- > M 存储器模型:一个存储器 M 是一系列固定大小的存储单元,每个单元 U 有一个唯一的地址 A(U),该地址被连续地编码。每个单元 U 有一个唯一的后继单元 U'=succ(U)。 P 的四种基本映射模型:顺序(sequential)、链接(linked)、索引(indexed)和散列(hashing)映射。
?
因此,我们至少可以得到4×4种可能的物理数据结构:
?
sequential (sets)
linked lists
indexed trees
hash graphs
?
(并不是所有的可能组合都合理)
?
??? 数据结构DS上的操作:所有的定义在DS上的操作在改变数据元素(节点)或节点的域时必须保持DS的逻辑和物理结构。
?
DS上的基本操作:任何其他对DS的高级操作都可以用这些基本操作来实现。最好将DS和他的所有基本操作看作一个整体——称之为模块。我们可以进一步将该模块抽象为数据类型(其中DS的存储结构被表示为私有成员,基本操作被表示为公共方法),称之为ADT。作为ADT,堆栈和队列都是一种特殊的表,他们拥有表的操作的子集。 对于DATs的高级操作可以被设计为(不封装的)算法,利用基本操作对DS进行处理。
?
好的和坏的DS:如果一个DS可以通过某种“线性规则”被转化为线性的DS(例如线性表),则称它为好的DS。好的DS通常对应于好的(高效的)算法。这是由计算机的计算能力决定的,因为计算机本质上只能存取逻辑连续的内存单元,因此如何没有线性化的结构逻辑上是不可计算的。比如对一个图进行操作,要访问图的所有结点,则必须按照某种顺序来依次访问所有节点(要形成一个偏序),必须通过某种方式将图固有的非线性结构转化为线性结构才能对图进行操作。
?
树是好的DS——它有非常简单而高效的线性化规则,因此可以利用树设计出许多非常高效的算法。树的实现和使用都很简单,但可以解决大量特殊的复杂问题,因此树是实际编程中最重要和最有用的一种数据结构。树的结构本质上有递归的性质——每一个叶节点可以被一棵子树所替代,反之亦然。实际上,每一种递归的结构都可以被转化为(或等价于)树形结构。
?
从机器语言到高级语言的抽象
?
我们知道,算法被定义为一个运算序列。这个运算序列中的所有运算定义在一类特定的数据模型上,并以解决一类特定问题为目标。这个运算序列应该具备下列四个特征。 有限性,即序列的项数有限,且每一运算项都可在有限的时间内完成;确定性,即序列的每一项运算都有明确的定义,无二义性;可以没有输入运算项,但一定要有输出运算项;可行性,即对于任意给定的合法的输入都能得到相应的正确的输出。这些特征可以用来判别一个确定的运算序列是否称得上是一个算法。 但是,我们现在的问题不是要判别一个确定的运算序列是否称得上是一个算法,而是要对一个己经称得上是算法的运算序列,回顾我们曾经如何用程序设计语言去表达它。
?
算法的程序表达,归根到底是算法要素的程序表达,因为一旦算法的每一项要素都用程序清楚地表达,整个算法的程序表达也就不成问题。
?
作为运算序列的算法,有三个要素。 作为运算序列中各种运算的运算对象和运算结果的数据;运算序列中的各种运算;运算序列中的控制转移。这三种要素依序分别简称为数据、运算和控制。 由于算法层出不穷,变化万千,其中的运算所作用的对象数据和所得到的结果数据名目繁多,不胜枚举。最简单最基本的有布尔值数据、字符数据、整数和实数数据等;稍复杂的有向量、矩阵、记录等数据;更复杂的有集合、树和图,还有声音、图形、图像等数据。 同样由于算法层出不穷,变化万千,其中运算的种类五花八门、多姿多彩。最基本最初等的有赋值运算、算术运算、逻辑运算和关系运算等;稍复杂的有算术表达式和逻辑表达式等;更复杂的有函数值计算、向量运算、矩阵运算、集合运算,以及表、栈、队列、树和图上的运算等:此外,还可能有以上列举的运算的复合和嵌套。 关于控制转移,相对单纯。在串行计算中,它只有顺序、分支、循环、递归和无条件转移等几种。
?
我们来回顾一下,自从计算机问世以来,算法的上述三要素的程序表达,经历过一个怎样的过程。
?
最早的程序设计语言是机器语言,即具体的计算机上的一个指令集。当时,要在计算机上运行的所有算法都必须直接用机器语言来表达,计算机才能接受。算法的运算序列包括运算对象和运算结果都必须转换为指令序列。其中的每一条指令都以编码(指令码和地址码)的形式出现。与算法语言表达的算法,相差十万八千里。对于没受过程序设计专门训练的人来说,一份程序恰似一份"天书",让人看了不知所云,可读性
?
极差。
?
用机器语言表达算法的运算、数据和控制十分繁杂琐碎,因为机器语言所提供的指令太初等、原始。机器语言只接受算术运算、按位逻辑运算和数的大小比较运算等。对于稍复杂的运算,都必须一一分解,直到到达最初等的运算才能用相应的指令替代之。机器语言能直接表达的数据只有最原始的位、字节、和字三种。算法中即使是最简单的数据如布尔值、字符、整数、和实数,也必须一一地映射到位、字节和字
中,还得一一分配它们的存储单元。对于算法中有结构的数据的表达则要麻烦得多。机器语言所提供的控制转移指令也只有无条件转移、条件转移、进入子程序和从子程序返回等最基本的几种。用它们来构造循环、形成分支、调用函数和过程得事先做许多的准备,还得靠许多的技巧。 直接用机器语言表达算法有许多缺点。
?
大量繁杂琐碎的细节牵制着程序员,使他们不可能有更多的时间和精力去从事创造性的劳动,执行对他们来说更为重要的任务。如确保程序的正确性、高效性。程序员既要驾驭程序设计的全局又要深入每一个局部直到实现的细节,即使智力超群的程序员也常常会顾此失彼,屡出差错,因而所编出的程序可靠性差,且开发周期长。 由于用机器语言进行程序设计的思维和表达方式与人们的习惯大相径庭,只有经过
较长时间职业训练的程序员才能胜任,使得程序设计曲高和寡。因为它的书面形式全是"密"码,所以可读性差,不便于交流与合作。因为它严重地依赖于具体的计算机,所以可移植性差,重用性差。这些弊端造成当时的计算机应用未能迅速得到推广。
?
克服上述缺点的出路在于程序设计语言的抽象,让它尽可能地接近于算法语言。 为此,人们首先注意到的是可读性和可移植性,因为它们相对地容易通过抽象而得到改善。于是,很快就出现汇编语言。这种语言对机器语言的抽象,首先表现在将机器语言的每一条指令符号化:指令码代之以记忆符号,地址码代之以符号地址,使得其含义显现在符号上而不再隐藏在编码中,可让人望"文"生义。其次表现在这种语言摆脱了具体计算机的限制,可在不同指令集的计算机上运行,只要该计算机配上汇编语言的一个汇编程序。这无疑是机器语言朝算法语言靠拢迈出的一步。但是,它离算法语言还太远,以致程序员还不能从分解算法的数据、运算和控制到汇编才能直接表达的指令等繁杂琐碎的事务中解脱出来。 到了50年代中期,出现程序设计的高级语言如Fortran,Algol60,以及后来的PL/l, Pascal等,算法的程序表达才产生一次大的飞跃。
?
诚然,算法最终要表达为具体计算机上的机器语言才能在该计算机上运行,得到所需要的结果。但汇编语言的实践启发人们,表达成机器语言不必一步到位,可以分两步走或者可以筑桥过河。即先表达成一种中介语言,然后转成机器语言。汇编语言作为一种中介语言,并没有获得很大成功,原因是它离算法语
?
言还太远。这便指引人们去设计一种尽量接近算法语言的规范语言,即所谓的高级语言,让程序员可以用它方便地表达算法,然后借助于规范的高级语言到规范的机器语言的"翻译",最终将算法表达为机器语言。而且,由于高级语言和机器语言都具有规范性,这里的"翻译"完全可以机械化地由计算机来完成,就像汇编语言被翻译成机器语言一样,只要计算机配上一个编译程序。 上述两步,前一步由程序员去完成,后一步可以由编译程序去完成。在规定清楚它们各自该做什么之后,这两步是完全独立的。它们各自该如何做互不相干。前一步要做的只是用高级语言正确地表达给定的算法,产生一个高级语言程序;后一步要做的只是将第一步得到的高级语言程序翻译成机器语言程序。至于程序员如何用高级语言表达算法和编译程序如何将高级语言表达的算法翻译成机器语言表达的算法,显然毫不相干。
?
处理从算法语言最终表达成机器语言这一复杂过程的上述思想方法就是一种抽象。汇编语言和高级语言的出现都是这种抽象的范例。 与汇编语言相比,高级语言的巨大成功在于它在数据、运算和控制三方
?
面的表达中引入许多接近算法语言的概念和工具,大大地提高抽象地表达算法的能力。 在运算方面,高级语言如Pascal,除允许原封不动地运用算法语言的四则运算、逻辑运算、关系运算、算术表达式、逻辑表达式外,还引入强有力的函数与过程的工具,并让用户自定义。这一工具的重要性不仅在于它精简了重复的程序文本段,而且在于它反映出程序的两级抽象。
?
在函数与过程调用级,人们只关心它能做什么,不必关心它如何做。只是到函数与过程的定义时,人们才给出如何做的细节。用过高级语言的读者都知道,一旦函数与过程的名称、参数和功能被规定清楚,那么,在程序中调用它们便与在程序的头部说明它们完全分开。你可以修改甚至更换函数体与过程体,而不影响它们的被调用。如果把函数与过程名看成是运算名,把参数看成是运算的对象或运算的结果,那么
?
,函数与过程的调用和初等运算的引用没有两样。利用函数和过程以及它们的复合或嵌套可以很自然地表达算法语言中任何复杂的运算。
?
在数据方面,高级语言如Pascal引人了数据类型的概念,即把所有的数据加以分类。每一个数据(包括表达式)或每一个数据变量都属于其中确定的一类。称这一类数据为一个数据类型。 因此,数据类型是数据或数据变量类属的说明,它指示该数据或数据变量可能取的值的全体。对于无结构的数据,高级语言如Pascal,除提供标准的基本数据类型--布尔型、字符型、整型和实型外,还提供用户可自定义的枚举类、子界类型和指针类型。这些类型(除指针外),其使用方式都顺应人们在算法语言中使用的习惯。对于有结构的数据,高级语言如Pascal,提供了数组、记录、有限制的集合和文件等四种标准的结构数据类型。其中,数组是科学计算中的向量、矩阵的抽象;记录是商业和管理中的记录的抽象;有限制的集合是数学中足够小的集合的势集的抽象;文件是诸如磁盘等外存储数据的抽象。
?
人们可以利用所提供的基本数据类型(包括标准的和自定义的),按数组、记录、有限制的集合和文件的构造规则构造有结构的数据。 此外,还允许用户利用标准的结构数据类型,通过复合或嵌套构造更复杂更高层的结构数据。这使得高级语言中的数据类型呈明显的分层。 高级语言中数据类型的分层是没有穷尽的,因而用它们可以表达算法语言中任何复杂层次的数据。 在控制方面,高级语言如Pascal,提供了表达算法控制转移的六种方式。
?
(1)缺省的顺序控制";"。
?
(2)条件(分支)控制:"if表达式(为真)then S1 else S2;" 。
?
(3)选择(情况)控制:
?
"Case 表达式 of
?
值1: S1
值2: S2
...
值n: Sn
end"
?
(4)循环控制:
?
"while 表达式(为真) do S;" 或
"repeat S until 表达式(为真);" 或
"for变量名:=初值 to/downto 终值do S;"
?
(5)函数和过程的调用,包括递归函数和递归过程的调用。
?
(6)无条件转移goto。
这六种表达方式不仅覆盖了算法语言中所有控制表达的要求,而且不再像机器语言或汇编语言那样原始、那样繁琐、那样隐晦,而是如上面所看到的,与自然语言的表达相差无几。 程序设计语言从机器语言到高级语言的抽象,带来的主要好处是: 高级语言接近算法语言,易学、易掌握,一般工程技术人员只要几周时间的培训就可以胜任程序员的工作;高级语言为程序员提供了结构化程序设计的环境和工具,使得设计出来的程序可读性好,可维护性强,可靠性高;高级语言远离机器语言,与具体的计算机硬件关系不大,因而所写出来的程序可移植性好,重用率高; 由于把繁杂琐碎的事务交给了编译程序去做,所以自动化程度高,开发周期短,且程、序员得到解脱,可以集中时间和精力去从事对于他们来说更为重要的创造性劳动,以提高、程序的质量。
?
数据结构、数据类型和抽象数据类型
?
数据结构、数据类型和抽象数据类型,这三个术语在字面上既不同又相近,反映出它们在含义上既有区别又有联系。
?
数据结构是在整个计算机科学与技术领域上广泛被使用的术语。它用来反映一个数据的内部构成,即一个数据由哪些成分数据构成,以什么方式构成,呈什么结构。数据结构有逻辑上的数据结构和物理上的数据结构之分。逻辑上的数据结构反映成分数据之间的逻辑关系,物理上的数据结构反映成分数据在计算机内的存储安排。数据结构是数据存在的形式。
?
数据是按照数据结构分类的,具有相同数据结构的数据属同一类。同一类数据的全体称为一个数据类型。在程序设计高级语言中,数据类型用来说明一个数据在数据分类中的归属。它是数据的一种属性。这个属性限定了该数据的变化范围。为了解题的需要,根据数据结构的种类,高级语言定义了一系列的数据类型。不同的高级语言所定义的数据类型不尽相同。Pascal语言所定义的数据类型的种类。
?
其中,简单数据类型对应于简单的数据结构;构造数据类型对应于复杂的数据结构;在复杂的数据结构里,允许成分数据本身具有复杂的数据结构,因而,构造数据类型允许复合嵌套;指针类型对应于数据结构中成分数据之间的关系,表面上属简单数据类型,实际上都指向复杂的成分数据即构造数据类型中的数据,因此这里没有把它划入简单数据类型,也没有划入构造数据类型,而单独划出一类。
?
数据结构反映数据内部的构成方式,它常常用一个结构图来描述:数据中的每一项成分数据被看作一个结点,并用方框或圆圈表示,成分数据之间的关系用相应的结点之间带箭号的连线表示。如果成分数据本身又有它自身的结构,则结构出现嵌套。这里嵌套还允许是递归的嵌套。
?
由于指针数据的引入,使构造各种复杂的数据结构成为可能。按数据结构中的成分数据之间的关系,数据结构有线性与非线性之分。在非线性数据结构中又有层次与网状之分。 由于数据类型是按照数据结构划分的,因此,一类数据结构对应着一种数据类型。数据类型按照该类型中的数据所呈现的结构也有线性与非线性之分,层次与网状之分。一个数据变量,在高级语言中的类型说明必须是读变量所具有的数据结构所对应的数据类型。最常用的数据结构是数组结构和记录结构。数组结构的特点是:
?
成分数据的个数固定,它们之间的逻辑关系由成分数据的序号(或叫数组的下标)来体现。这些成分数据按照序号的先后顺序一个挨一个地排列起来。每一个成分数据具有相同的结构(可以是简单结构,也可以是复杂结构),因而属于同一个数据类型(相应地是简单数据类型或构造数据类型)。这种同一的数据类型称为基类型。所有的成分数据被依序安排在一片连续的存储单元中。 概括起来,数组结构是一个线性的、均匀的、其成分数据可随机访问的结构。
?
由于这、种结构有这些良好的特性,所以最常被人们所采用。在高级语言中,与数组结构相对应的、数据类型是数组类型,即数组结构的数据变量必须说明为array [i] of T0 ,其中i是数组、结构的下标类型,而T0是数组结构的基类型。 记录结构是另一种常用的数据结构。它的特点是:与数组结构一样,成分数据的个数固定。但成分数据之间没有自然序,它们处于平等地位。每一个成分数据被称为一个域并赋予域名。不同的域有不同的域名。不同的域允许有不同的结构,因而允许属于不同的数据类型。与数组结构一样,它们可以随机访问,但访问的途径靠的是域名。在高级语言中记录结构对应的数据类型是记录类型。记录结构的数据的变量必须说明为记录类型。
?
抽象数据类型的含义在上一段已作了专门叙述。它可理解为数据类型的进一步抽象。即把数据类型和数据类型上的运算捆在一起,进行封装。引入抽象数据类型的目的是把数据类型的表示和数据类型上运算的实现与这些数据类型和运算在程序中的引用隔开,使它们相互独立。对于抽象数据类型的描述,除了必须描述它的数据结构外,还必须描述定义在它上面的运算(过程或函数)。抽象数据类型上定义的过程和函
数以该抽象数据类型的数据所应具有的数据结构为基础。
?
泛型设计和数据结构与算法
?
下面我想再说说关于泛型程序设计模型对于数据结构和算法方面的最新推动,泛型思想已经把数据结
?
构和算法方面的基本思想抽象到了一个前所未有的高度,现在有多种程序设计语言支持泛型设计,比如
ADA,C++,而且据说在JAVA的下一版本和C#中也将对泛型设计进行全面的支持。
?
先说说泛型设计的基本思想:泛型编程(generic programming,以下直接以GP称呼)是一种全新的程序设计思想,和OO,OB,PO这些为人所熟知的程序设计想法不同的是GP抽象度更高,基于GP设计的组件之间偶合度底,没有继承关系,所以其组件间的互交性和扩展性都非常高。我们都知道,任何算法都是作用在一种特定的数据结构上的,最简单的例子就是快速排序算法最根本的实现条件就是所排序的对象是存
贮在数组里面,因为快速排序就是因为要用到数组的随机存储特性,即可以在单位时间内交换远距离的对象,而不只是相临的两个对象,而如果用联表去存储对象,由于在联表中取得对象的时间是线性的既O[n],这样将使快速排序失去其快速的特点。也就是说,我们在设计一种算法的时候,我们总是先要考虑其应用的数据结构,比如数组查找,联表查找,树查找,图查找其核心都是查找,但因为作用的数据结构不同
?
将有多种不同的表现形式。数据结构和算法之间这样密切的关系一直是我们以前的认识。泛型设计的根本思想就是想把算法和其作用的数据结构分离,也就是说,我们设计算法的时候并不去考虑我们设计的算法将作用于何种数据结构之上。泛型设计的理想状态是一个查找算法将可以作用于数组,联表,树,图等各种数据结构之上,变成一个通用的,泛型的算法。这样的理想是不是很诱惑人?
?
泛型编程带来的是前所未有的弹性以及不会损失效率的抽象性,GP和OO不同,它不要求你通过额外的间接层来调用函数:它让你撰写完全一般化并可重复使用的算法,其效率与针对特定数据结构而设计的算法旗鼓相当。我们大家都知道数据结构在C++中可以用用户定义类型来表示,而C++中的模板技术就是以类型作为参数,那么我可以想象利用模板技术可以实现我们开始的GP思想,即一个模板函数可以对于各种传递进来的类型起作用,而这些类型就可以是我们定义的各种数据结构。
?
泛型算法抽离于特定类型和特定数据结构之外,使得其适应与尽可能的一般化类型,算法本身只是为了实现算法其需要表达的逻辑本质而不去被为各种数据结构的实现细节所干扰。这意味着一个泛型算法实际具有两部分。1,用来描叙算法本质逻辑的实际指令;2,正确指定其参数类型必须满足的性质的一组需求条件。到此,相信有不少人已经开始糊涂了,呵呵,不要紧。毕竟GP是一种抽象度非常高的程序设计思想,里面的核心就是抽象条件成为成为程序设计过程中的核心,从而取代了类型这在OO里面的核心地位,正是因为类型不在是我们考虑的重点,类型成为了抽象条件的外衣,所以我们称这样的程序思想为泛型思想------把类型泛化。
这样可以么?
Ⅱ 那位大大能详细的讲解一下JAVA中的快速排序
快速排序是对冒泡排序的一种改进。它的基本思想是:通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按次方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。最坏情况的时间复杂度为O(n2),最好情况时间复杂度为O(nlog2n)。
另外 java没指针概念 可以认为是句柄
假设要排序的数组是A[1]……A[N],首先任意选取一个数据(通常选用第一个数据)作为关键数据,然后将所有比它的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一躺快速排序。一趟快速排序的算法是:
1)、设置两个变量I、J,排序开始的时候I:=1,J:=N;
2)以第一个数组元素作为关键数据,赋值给X,即X:=A[1];
3)、从J开始向前搜索,即由后开始向前搜索(J:=J-1),找到第一个小于X的值,两者交换;
4)、从I开始向后搜索,即由前开始向后搜索(I:=I+1),找到第一个大于X的值,两者交换;
5)、重复第3、4步,直到I=J;
例如:待排序的数组A的值分别是:(初始关键数据X:=49)
A[1] A[2] A[3] A[4] A[5] A[6] A[7]:
49 38 65 97 76 13 27
进行第一次交换后: 27 38 65 97 76 13 49
( 按照算法的第三步从后面开始找)
进行第二次交换后: 27 38 49 97 76 13 65
( 按照算法的第四步从前面开始找>X的值,65>49,两者交换,此时I:=3 )
进行第三次交换后: 27 38 13 97 76 49 65
( 按照算法的第五步将又一次执行算法的第三步从后开始找)
进行第四次交换后: 27 38 13 49 76 97 65
( 按照算法的第四步从前面开始找大于X的值,97>49,两者交换,此时J:=4 )
此时再执行第三步的时候就发现I=J,从而结束一躺快速排序,那么经过一躺快速排序之后的结果是:27 38 13 49 76 97 65,即所以大于49的数全部在49的后面,所以小于49的数全部在49的前面。
快速排序就是递归调用此过程——在以49为中点分割这个数据序列,分别对前面一部分和后面一部分进行类似的快速排序,从而完成全部数据序列的快速排序,最后把此数据序列变成一个有序的序列,根据这种思想对于上述数组A的快速排序的全过程如图6所示:
初始状态 {49 38 65 97 76 13 27}
进行一次快速排序之后划分为 {27 38 13} 49 {76 97 65}
分别对前后两部分进行快速排序 {13} 27 {38}
结束 结束 {49 65} 76 {97}
49 {65} 结束
结束//下面是一个示例,哪位给说说快速排序法的原理,下面的示例中指针和上下标移动我看不太懂,
public class QuickSort {
/**主方法*/
public static void main(String[] args) {
//声明数组
int[] nums = {27, 8, 57, 9, 23, 41, 65, 19, 0, 1, 2, 4, 5};
//应用快速排序方法
quickSort(nums, 0, nums.length-1);
//显示排序后的数组
for(int i = 0; i < nums.length; ++i) {
System.out.print(nums[i] + ",");
}
System.out.println("");
}
/**快速排序方法*/
public static void quickSort(int[] a, int lo0, int hi0) {
int lo = lo0;
int hi = hi0;
if (lo >= hi)
return;
//确定指针方向的逻辑变量
boolean transfer=true;
while (lo != hi) {
if (a[lo] > a[hi]) {
//交换数字
int temp = a[lo];
a[lo] = a[hi];
a[hi] = temp;
//决定下标移动,还是上标移动
transfer = (transfer == true) ? false : true;
}
//将指针向前或者向后移动
if(transfer)
hi--;
else
lo++;
//显示每一次指针移动的数组数字的变化
/*for(int i = 0; i < a.length; ++i) {
System.out.print(a[i] + ",");
}
System.out.print(" (lo,hi) = " + "(" + lo + "," + hi + ")");
System.out.println("");*/
}
//将数组分开两半,确定每个数字的正确位置
lo--;
hi++;
quickSort(a, lo0, lo);
quickSort(a, hi, hi0);
}
}
Ⅲ excel快速排序技巧,如何使用SORTBY函数对数据进行排序
SORTBY 函数基于相应范围或数组中的值对范围或数组的内容进行排序。
Ⅳ 压缩文件
详细看第14
作为压缩软件中的佼佼者WinZip日前已推出了全新的WinZip 7.0版本,其主要功能包括:(1)与Windows 95/98/NT高度整合。WinZip支持长文件名并与Windows 95/98/NT shell紧密整合,可直接从/向资源管理器中拖出/入,无需离开资源管理器即可完成文件的压缩与解压缩。(2)支持Internet。WinZip内建支持最流行的Internet文件格式,如TAR、gzip、Unix compress、UUEncode、Xxencode、BinHex和MIME,安装相应的外部程序后,WinZip也可以支持ARJ、LZH和ARC压缩文件,总之,使用WinZip您几乎可以访问所有的从Internet下载的文件格式。另外,其可免费下载的WinZip Internet Browser Support Add-On,让您在Microsoft Internet Explorer或Netscape Navigator中只需单击就能够下载并打开压缩文件。(3)内建压缩和解压缩。WinZip内建与PKZIP完全兼容的ZIP和UNZIP,并支持多磁盘Zip压缩文件。(4)自动安装Zip文件中的大多数软件。如果一个Zip文件包括一个Setup或Install程序,WinZip的Install功能将解压缩该文件,运行安装程序并最后清除临时文件。(5)WinZip向导(WinZip Wizard)。该功能使用标准的、为大家所熟悉的用户界面处理解压缩和Zip文件内部的安装软件。它不是为有经验的用户而设置,但却是那些数以万计的Computer Fan快速掌握WinZip,以进行压缩和解压缩操作所不可或缺的东西。(6)Favorite Zip Folders功能。WinZip能够将所有的Zip文件都列入该窗口,在这里您能够按照日期进行排序,使得定位所有Zip文件变得非常简单,而不管它们来自哪里或保存在什么地方。与普通的File->Open Archive对话框不同,Favorite Zip Folders 对话框将多个文件夹视为一个目录就好像他们是一个文件夹一样。一个搜索工具会发现丢失在您硬盘上的所有Zip文件。(7)建立自解压文件。WinZip Self-Extractor Personal Edition包含于WinZip之中,当你将某个文件发送给那些您知道或不知道其使用何种压缩软件的人时,自解压文件(Self-extracting file)无疑是一个非常不坏的主意。(8)多卷压缩。利用WinZip可将一个或若干大的文件压缩至若干可移动磁盘之中,如果需要,可将该多卷压缩文件制作为自解压文件形式。(9)病毒扫描。WinZip能够设置并运行绝大多数的病毒扫描程序,用以在压缩或解压缩之前对文件进行安全性检查。下面我们为大家详细介绍一下该软件的使用方法和技巧。
1.快速压缩与解压缩。
(1)若欲快速压缩或解压缩文件,只需在资源管理器中以鼠标右击该文件(使用Shift和Ctrl键可以选中若干文件),并在弹出的快捷菜单中选择“Add to Zip”或“Extract To”命令即可。若选中“Add to xxxxx.Zip”(只压缩一个文件时有效)或“Extract to folder xxxxxxx”,则可直接将文件压缩/解压缩至WinZip默认的文件/目录中。
(2)从Zip压缩文件中解压缩所有的文件。在资源管理器窗口中,使用鼠标右键将欲解压缩文件从一个资源管理器窗口拖放至任意文件夹,然后在弹出的快捷菜单中选中“Extract To”命令即可。注意:必须使用鼠标右键拖拽欲解压文件,若以鼠标左键拖放则同盘间是移动,异盘间是复制,而不是解压缩。
(3)从Zip压缩文件中解压缩若干文件。在资源管理器窗口中双击欲解压缩的文件弹出WinZip窗口,选中欲解压缩的文件,右击鼠标并在弹出的快捷菜单中选中“Extract To”命令即可。
2.将若干文件添加至压缩文件中。在资源管理器窗口文件栏中,使用鼠标左键或右键将欲添加文件(包括压缩文件)拖放至目标压缩文件即可。
3.从压缩包中删除文件。在WinZip主窗口中打开欲进行编辑的压缩包,右击欲删除的文件(可同时选中多个文件),然后在弹出的快捷菜单中选中Delete命令即可。
4.制作自解压文件。如果您欲将一个压缩文件发送给某人,而您并不能确定他是否安装有解压缩软件,那么您应当将其制作为自解压文件。WinZip内置的Zip Self-Extractor Personal Edition程序,可方便地实现该操作。首先,将该文件制作为压缩文件,然后在资源管理器中右击该文件或者在WinZip中打开该文件并右击其中任一文件,然后在弹出的快捷菜单中选中Make .Exe File命令即可。
5.建立多卷压缩文件。
(1)建立单文件多卷压缩文件。资源管理器中以鼠标右击欲压缩文件,并在弹出的快捷菜单中选择“Add to Zip”命令,在弹出的Add对话框“Add to Archive”框中键入一可移动磁盘的盘符,WinZip将首先对文件进行压缩,然后将压缩后的文件写到磁盘中,第一张磁盘写满后,根据提示再插入下一张磁盘即可。
(2)建立多文件多卷压缩文件。在一张可移动的磁盘上建立一个Zip压缩文件,然后将您中意的文件添加到该压缩文件,当磁盘写满以后,根据提示再插入下一张磁盘即可。
6.制作多卷自解压文件。WinZip内建的WinZip Self-Extractor Personal Edition可将大型文件制作为自解压文件并将其放置于多张可移动磁盘中。一种较为简单地启动WinZip Self-Extractor Personal Edition的方法是:先利用WinZip建立一个普通的Zip文件,然后再在工具栏中单击Make.Exe快捷图标或从Actions菜单中选中Make .Exe File图标后,该程序即可被激活,除非你在Options\Configuration\Program Locations对话框“Program to create self-extracting Zip files Make EXE”框中指定了其他自解压文件制作程序。如果在安装WinZip时您选择了建立WinZip Self-Extractor Personal Edition图标,那么也可以双击该图标以开始该程序。
自解压文件制作时可采用三种不同的模式,一是No Spanning,该模式将不在磁盘中建立a.exe文件,因此也不能跨磁盘操作。二是Safe spanning method,该模式下WinZip Self-Extractor同时将两个文件放置在第一张磁盘,即包括第一部分压缩数据的a .ZIP文件和包含提取数据包必须的执行代码的small .EXE文件,第二张及其后的磁盘内则容纳包含其它压缩数据的.ZIP文件。三是Old spanning method,老式的多卷压缩方法将包含用于提取压缩数据的执行代码和第一部分数据的a .EXE放置在第一张磁盘之中,第二张及其后的磁盘容纳剩余的数据,在这些文件之中(甚至事实上它们并不包含任何可执行代码)都包含有一个.exe的可执行文件。这可能非常危险,因为如果用户不小心而运行了第二或其后磁盘上的EXE文件,将出现不可预见的错误信息,甚至会导致系统挂起。因此,如果您欲制作安全的多卷自解压文件,最好采取Safe spanning method方式。
WinZip Self-Extractor制作的多卷自解压文件,在解压缩时非常简单,插入第一张磁盘并双击EXE文件,然后只需根据提示插入相应的磁盘即可。
7.压缩包注释。在Actions菜单中单击Comment命令,弹出Comment编辑窗口,在此可显示、建立、编辑、删除有关该压缩包的描述性文本信息,Windows下复制(Ctrl+C)、粘贴(Ctrl+V)和剪切(Ctrl+X)等快捷键完全适用于该编辑窗口。
8.软件安装。对于包含有Install或Setup安装文件的压缩包,WinZip无需执行解压缩过程,即可完成软件的安装。单击“Open”快捷图标或者在“File”菜单中选中“Open Archive”命令,打开欲进行安装的包含有Install或Setup程序的压缩包,然后单击工具栏中的“Install”快捷图标或在“Actions”菜单中选中“Install”命令,弹出“Install”对话框。如果Install按钮没有显示在工具栏中,但是您能够确认该文件是一个安装文件,那么,可以使用CheckOut功能来尝试在压缩文件包中直接安装该软件。在WinZip主页http://www.winzip.com处您可以找到并下载以前发布的Install/Try/Uninstall Windows 95/98/NT版本,它能够同WinZip的Install功能一起建立安装程序的反安装程序。WinZip独一无二的Install/Try/Uninstall功能,通过保存应用程序在安装过程时系统内部所作的一切改变,而让您在从压缩包内部直接安装和删除安装软件时变得非常简单。在反安装时,您能够选择删除安装程序形成的文件、图标或程序组,并且能够恢复任何已经改变了的INI文件,总之您能够完全控制反安装的全过程,并将系统完全恢复到其原始状态。
9.从Microsoft's CAB (cabinet)格式压缩包(包括大多数自解压CAB文件)中提取文件。打开Microsoft CAB压缩包格式文件,就像打开一个普通的压缩文件包一样简单,在WinZip中打开并浏览CAB压缩包内的所有文件,选中需要的一个、几个或全部文件,单击Extract按钮或右击鼠标并在弹出的快捷菜单中选中Extract to命令即可。除Zip、CAB格式之外,WinZip还能够处理许多种压缩文件格式,如TAR、Z、GZ、TGZ、Uuencode、BinHex和MIME等。
10.快速排序。WinZip在主窗口的文件列表中采用了栏目按钮,该按钮类似于Windows 95OSR2/98资源管理器右栏文件列表中的栏目按钮,并具有与其基本相同的功能和特点,其一,单击任一栏目按钮即可以此为标准对选中的文件进行排序,再次单击该栏目按钮时,再以反向排序;其二,栏目按钮的宽度可用鼠标随意左右拖动,用以显示因空间不够而隐藏起来的部分信息;其三,栏目按钮可通过拖曳以改变其相对位置。在Options\Configuration\View对话框中可任意选择欲显示/关闭的栏目按钮(Name栏除外),它们分别是Name(主文件名+扩展名)、Type(文件类型)、Modified(修改时间)、Size(压缩前文件大小)、Ratio(压缩率)、Packed(压缩后文件大小)、CRC(循环冗余码校验)、Attributes(文件属性)和Path(路径)。在View对话框中单击Defaults按钮,可将栏目按钮恢复为Winzip默认的状态。
11.快速查找Zip文件。如果你记不得将自己的Zip 文件放在了何处,可以用Favorite Zip Folders功能来进行查找,只需在WinZip的File菜单中单击Favorite Zip Folders命令,则所有Zip文件将立即尽收眼底。
12.快速浏览修改应用文档。将WinZip窗口文件列表中的Zip文件拖曳到其应用程序或应用程序的快捷方式,即可打开查看该文件并进行编辑和修改。
13.快速查看。Quick View(快速查看)是Windows中一个非常有用的小工具,利用它不必调用原应用程序就可以直接浏览文件内容。如果您在安装Windows时选择了该组件,那么您在WinZip中也可以使用它来快速查看文档。如果您是在安装WinZip之后才又添加安装了Quick View,则必须在Options\Configuration\Program Locations选项卡的Viewer框中键入Quick View所在的文件夹及其和文件名,才可实现快速查看。
14.E-mail Zip文件。如果你使用的是与MAPI兼容的E-mail系统,则简单地利用WinZip File菜单中的Mail Archive命令,或者单击WinZip状态行,然后将其拖放至电子邮件程序。
15.以命令行方式批操作。命令行的方式可通过wzzip.exe和wzunzip.exe实现文件的压缩和解压缩。当有特殊的工作需要或者欲将工作完成的更快、自动化程度更高,使用普通的WinZip图形界面不能满足需要时,WinZip命令行界面可以让您使用其内置的强力批处理和宏来实现这一愿望。
16.打印在WinZip主窗口中的可见的压缩文件的信息。若欲改变打印的内容,唯一的方法就是必须更改显示在窗口的内容,或者通过拖曳的方式改变栏宽,或者在Options\Configuration\View 中改变显示的栏目。
17.快速打印文件。将WinZip窗口文件列表中的Zip文件拖曳到打印机或其快捷方式即可实现文件的打印。注意:在File菜单中选中Print命令并非是打印文件内容,而是打印WinZip文件列表中显示的内容。
18.快速打开最近访问的Zip文件。用WinZip 打开的Zip 文件会添加到“开始”按钮的“文档”列表中,因此,若欲访问最近打开的文档可直接在该处完成。
19.调用其它压缩软件。由于不同压缩程序制作的压缩文档格式不同,所以当您使用非ZIP格式文件时,则需要另外安装其它压缩软件。客观地讲,其它压缩软件总不如WinZip简单易用,因此,您可以让WinZip来调用其它压缩程序实现文件的解压缩。目前,WinZip支持的压缩软件为ARJ、LHA和ARC,如果您安装有该软件,应当在Options\Configuration\Program Locations选项卡中分别指明其所在的文件夹和程序文件名。
20.病毒扫描。在WinZip中打开欲扫描病毒的压缩文件,右击选中的欲扫描的若干文件,在弹出的快捷菜单中选中“Virus Scan”命令,WinZip即可使用在Options\Configuration\Program Locations选项卡Optional virus scanner Scan Program框中指定的查杀病毒程序直接病毒的扫描。
21.中止WinZip操作。在WinZip对文件进行操作时(打开、压缩、解压缩、制作自解压文件等),单击WinZip窗口中的任意位置,都可中止目前所作的操作,并弹出“Archive Operation Interrupted”提示窗口,选中Continue按钮继续进行处理,选中Stop按钮则中断对文件的处理。
22.向/从工具菜单添加/删除快捷按钮。在Options\Configuration\Toolbar对话框中单击Select Bottons按钮,弹出自定义工具栏对话框,然后即可根据自己的需要在工具栏中添加或删除快捷按钮,最多可增添至21个。单击重启按钮,则可将工具栏中的按钮恢复为WinZip 7.0缺省状态。注意:工具栏的设置需有Windows Common Control library 4.71或更高版本的支持才能够实现,当然,如果您的操作系统已经升级为Windows 98或者安装了IE 4.0也同样能够满足需要,否则,您即应当从http://www.winzip.com/common_control_library.cgi下载该文件。另外,当将颜色设置为16位增强色或24位真彩色时,快捷按钮看起来会更漂亮、更迷人。
23.默认文件夹设定。如果您在打开、解压缩或添加压缩文件时经常使用同一个文件夹,则应在Options\Configuration\Folders对话框中各项分别进行指定,以减少繁琐的文件夹选定操作,加快工作速度。
24.保存当前窗口的大小。使用鼠标您当然可以改变WinZip窗口的大小,但如果您想保留已经改变了的窗口尺寸使其成为默认值,应当在Options菜单中单击Save Settings Now命令。
25.显示WinZip多重窗口。默认状态下,WinZip只能显示一个窗口,若欲显示多个WinZip窗口, 则应当取消对Options菜单中Reuse WinZip Windows选项的选择。在同时打开的多个WinZip窗口中以鼠标拖曳的方式即可实现文件在不同压缩包间的复制和移动。当用鼠标将某个文件从一个窗口拖曳到另一个时将弹出“Drag and Drop”对话框,在Action下拉列表框中选中“Add (and replace) files”选项则将该文件添加到(即复制到)目标压缩包中,若目标压缩包中包含有同名文件则以该文件取而代之,选中“Move files”选项则将该文件移动到目标压缩包之中。
26.使用类似于Internet Explorer 4.0风格的用户界面。如果在Internet Explorer 4.0 中选中了Active Desktop(活动桌面)选项,那么在WinZip中它将自动生效,否则,您可以在Options\Configuration\View对话框中对其进行设置。操作如下:首先取消对“Use current system folder settings”复选框的选择,然后选中“Single-click to open an item(point to select)”复选框,文件列表中的条目将改变成为一个个超级链接,指向该条目时即为选中,只需单击鼠标左键即可应声打开。若选中“Underline file names”选项按钮,则条目显示为普通文字格式不带有作为超级链接标志的下划线;若选中“Underline file names only when I point at them”选项按钮,则每个条目下方均显示一线下划线,呈典型的超级链接。
27.重新显示每日提示。如果你关闭了WinZip每日提示信息后又想恢复显示它的话,可在WinZip主窗口的Help下拉菜单中选中“Tip of the Day”命令,然后再在“WinZip Tip of the Day”窗口底部的下拉列表框中根据需要选择中意的显示方式,Always show tips at startup每次运行WinZip时均显示提示窗口,Show tips at startup if not opening a Zip file如果在运行WinZip时没有打开Zip文件则显示窗口。
Ⅳ 巧用excel排序和筛选功能制作学生
一张含有大量数据的Excel表格,里面难免会有重复的数据,我们如何快速删除大量重复的数据呢?这里面会用到Excel筛选的小技巧,今天柯鸣就教给大家如何巧用Excel排序和筛选功能。
快速删除重复数据
首先我们选中整个表格,单击数据选项卡,选择“排序和筛选”栏目下的高级,并单击,弹出高级筛选对话框,在里面分别选择列表区域和条件区域,并勾选下面的“选择不重复记录”的复选框,最后确定,具体操作如下图
快速排序
首先我们选中需要排序的列表,然后单击数据选项卡,在里面单击排序功能,弹出排序对话框,选择需要排序的关键字,然后选择按升序或者降序排列,如下图
快速筛选对比数据
假如我们想在大量的销售数据里面对比查看张三和王五的销售数据,我们可以先选中姓名这一列表,然后单击数据选项卡下的筛选功能,这个时候在姓名标题下就会显示一个下拉的三角符号,我们单击它,弹出一个筛选下拉菜单,我们在里面只选择张三和王五即可,具体操作如下图
Ⅵ 有一组数组{25、50、70、21、4、18、100、43、7、12}用快速排序,求快速排序的做题方法技巧,和原理。
12、7、18、21、4、25、100、43、70、50
你好,首先很愿意帮助你。我回答过同一类型的题。我把我回答的记录复制给你,如果还是没有帮助的话,我再详细的做一下你给的题目。先提示一句:一般来说快速排序,哨兵是第一个元素,放在0地址里。原始位置空下。 还有 快速排序也是两种有序的,我的例子是非递减。
eg:
对集合(19,14,23,01,68,84,27)以19为枢轴元素,画出一趟快速排序的过程。求数据结构的答案...
我的回答:
[19] ___ 14 23 01 68 84 27 哨兵同27对比
[19] ___ 14 23 01 68 84 27 同84比
[19] ___ 14 23 01 68 84 27 同68比
[19] 01 14 23 __ 68 84 27 同01比 前置
[19] 01 14 23 — 68 84 27 同14比
[19] 01 14 — 23 68 84 27 同23比较 后置
(01 14 ) 19 ( 23 68 84 27 ) 哨兵恢复 第一趟快速排序完成
希望对你有帮助。
Ⅶ pascal语言中,快速排序和冒泡排序有没有什么技巧啊
冒泡法的时间复杂度为O(n2),快速排序的时间复杂度为O(nlog2n),当排序数的数量n比较少时用冒泡法,当n比较大时用快速排序。
Ⅷ 为什么快速排序不能用尾递归来实现
递归过程中需要子过程计算返回结果的过程才必须要入栈。快速排序是先比较换位之后再把结果分发给两个子过程,在执行完最后一个子过程之后程序自动结束,所以是尾递归的。而归并排序需要最后一个子过程先排序,再逐级返回,继续归并,所以不是尾递归。写程序的时候能看出来,快速排序的递归调用都是在函数尾部,归并排序的递归调用都在函数头部。这才是尾递归和非尾递归的区别。
所有递归都可以写成迭代,但是尾递归可以写成真正的迭代,非尾递归依旧需要一个辅助结构来模拟或者说代替递归所用的栈结构。不过根据问题的不同和栈结构的实现技巧,很多非尾递归问题都是可以通过改写成迭代来提高性能(节约空间或者时间)的。最明显的例子就是斐波那契数列。斐波那契数列递归过程中一定要先入栈,直到压入f(0)和f(1)时才能开始出栈,所以不是尾递归的,但是通过一块内存暂存上一步的结果就可以直接从f(0)和f(1)开始计算得到f(n)的值,这样就省去了递归消耗的栈空间以及入栈出栈的时间开销,所以时间和内存占用都小得多。
另外虽然通常编译器自带的尾递归优化的效果我并没有测试过。不过从网上一些人的测试来看,一般C编译器的尾递归优化应该是和迭代效果相近,甚至我看到有人说测试结果中尾递归优化更快的。所以按理说只要编译器带有尾递归优化,写法满足优化要求,编译器应该会自动完成优化的。
Ⅸ excel怎么做排序,RANK函数快速排序技巧
本文介绍 Microsoft Excel 中 RANK 函数的公式语法和用法。
说明
返回一列数字的数字排位。 数字的排位是相对于列表中的其他值的大小。 (如果要对列表进行排序,则数字的秩将是其位置。)
重要:此函数已被替换为一个或多个新函数,这些函数可提供更高的精确度,其名称更好地反映其用法。 虽然此函数仍可向后兼容,但您应该考虑从现在开始使用新函数,因为此函数在 Excel 的将来版本中可能不再可用。
语法
RANK(number,ref,[order])
RANK 函数语法具有下列参数:
Number 必需。 要找到其排位的数字。
Ref 必需。 数字列表的数组,对数字列表的引用。 Ref 中的非数字值会被忽略。
Order 可选。 一个指定数字排位方式的数字。
如果 order 为 0(零)或省略,Microsoft Excel 对数字的排位是基于 ref 为按照降序排列的列表。
如果 order 不为零,Microsoft Excel 对数字的排位是基于 ref 为按照升序排列的列表。
说明
Rank 赋予重复数相同的排位。 但重复数的存在将影响后续数值的排位。 例如,在按升序排序的整数列表中,如果数字 10 出现两次,且其排位为 5,则 11 的排位为 7(没有排位为 6 的数值)。