javascript依照,javascript中!

java script学习方法

先学习语法基础 跟vb语言有点类似 学习步骤可以按下面来:

成都创新互联公司是专业的善右网站建设公司,善右接单;提供成都网站设计、成都网站建设,网页设计,网站设计,建网站,PHP网站建设等专业做网站服务;采用PHP框架,可快速的进行善右网站开发网页制作和功能扩展;专业做搜索引擎喜爱的网站,专业的做网站团队,希望更多企业前来合作!

一、在页面中怎么添加javascript

script language=”javascript” //这行是javascript脚本标记,斜杠后面的就是注释了

document.write(”在页面显示的javascript”) //在页面显示一句话

/script

/*这也是注释*/

二、javascript的数据类型

1、字符串(string):字符串就是由一连串的字符组成的序列。包括字母、数字以及标点符号。当然还可以是汉字等。简单一点就是表示文本信息。

2、数字(number):数字又分为两类:整型数字和浮点型数字。

整数包括正整数,零和负整数。

javascript中的数字可以使用十进制、八进制和十六进制来书写。方法如下:

十进制:15(直接写数字即可)

八进制:017(要以零做为引导数字)

十六进制:0xf(要以0x做为引导数字)

浮点型数字也叫实数,为了方便,也可以使用科学记数法来表示:

1.13e1、1.5e3(等价于1.5乘10的3次方)

javascript的数字范围大约为10的负308次方到10的308次方之间。

javascript中还有一个特殊的数字值NaN(not a number),javascript 用nan表示这个无意义的结果。

3、布尔值(boolean):true和false,在计算机中一般用1表示true,用0表示false。

三、alert()方法的使用:

script language=”javascript”

alert(”在页面上显示警告对话框”);

/script

alert()是javascript产生一个带确认按钮的对话框,上面显示括号内的信息。

四、confirm()方法的使用:

script language=”javascript”

confirm(”在页面上显示确认对话框”);

/script

confirm()和alert()差不多,不同的就是多了个取消按钮。按确定返回true,按取消返回false。

script language=”javascript”

var con;

con=confirm(”你们喜欢这样的教程吗?”);

if (con==true) alert(”喜欢”);

else alert(”不喜欢”);

/script

五、prompt()方法的使用:

script language=”javascript”

var name,age;

name=prompt(”请问您的名字?”);

alert(name);

age=prompt(”多大?”);

alert(age);

/script

它不但可以显示信息,而且可以输入信息。

六、javascript变量

用var加上为变量指定的名称来声明变量,变量类型可以通过给变量赋值来确定。由于javascript采用的是弱类型的样式,对数据类型要求不太严格,在程序执行的过程中,会根据需要自动转换。

字符串变量,可以通过“变量名.length”来获得该变量中字符串的长度,如

var name;

name=”javascript”;

那么name.length的值就是10。

若在一行中创建多个变量时,记住用逗号来隔开变量名。各语句用分号隔开。(使用分号是个好习惯, 大家在学习的时候尽量养成加分号的习惯)

类型转换:javascript允许在程序中改变变量的类型,最常见的两个类型转换符Number和String。

Number(x)是字符型值——〉数字值型。String与之相反。相对于javascript的自动类型转换,可以将这种转换成为强制类型转换。(强制类型转换需要在javascript1.2及以上版本才可以使用)

变量的命名:

1.必须以字母或下划线开头,中间可以有字母数字和或下划线。不能使用空格、+、-等其他符号。

作为连字符外,变量名称不能有空格、(+)、(-)、(,)或其它符号。

2.不能使用JavaScript中的关键字作为变量。

(javascript变量名是区分大小写的,name和Name是不一样的。)

对于变量还有一个重要性──那就是变量的作用域。在JavaScript中同样有全局变量和局部变量。全局变量是定义在所有函数体之外,其作用范围是整个函数;而局部变量是定义在函数体之内,只对其该函数是可见的,而对其它函数则是不可见的。

如果局部变量和全局变量重名,则局部变量优先。js没有块级作用域。函数中声明的所有的变量,作用域是相同的。

变量的类型规则

javascript是无类型的,他的变量可以放任何数据类型的值。

变量的声明

在javascript程序中,在使用变量之前,必须先声明它。变量是使用关键字var声明的。而实际上,不一定要先声明变量,在某些情况下,变量声明是可选的。

var i;

var sum;

也可以使用一个var关键字声明多个变量;

var i,sum;

而且还可以将变量声明和变量初始化绑定在一起:

var message = ‘hello’;

var i = 0,j=0,k=0;

由var声明的变量是永久的,因为各浏览器对是否可以删除全局性的变量的态度是不同的,(都可以删除局部变量)为了安全,最好假设全局变量不可删除。

可以使用var多次声明同一个变量,当你给一个没有声明的变量赋值时,js会自动用哪个变量为你创建一个全局变量。如果你想在函数内部创建一个局部变量。那就必须用var在函数内部声明。

七、javascript表达式和运算符

表达式:在定义完变量后,就可以对它们进行赋值、改变、计算等一系列操作,这一过程通常由表达式来完成,可以说它是变量、常量、布尔及运算符的集合,因此表达式可以分为算术表述式、字串表达式、赋值表达式以及布尔表达式等。

1.算术运算符:+(加) 、-(减)、 *(乘)、 /(除)、 %(取模) -(取反)、++(递加1)、–(递减1)。

例:11%2=1 ; 如果x=2 ++x+4=7 x+++4=6(++x是先执行加1,x++是执行完语句之后x在自加1)

例子:

script

var i=0, j=0;

alert(i++ + ” ” + ++j + ” ” + i);

// 输出 “0 1 1”,可见i++是先输出了i,然后进行运算,而++j是先对j进行了自加运算,然后输出j的值

/script

2.比较运算符:(小于)、(大于)、=(小于等于)、=(大于等于)、==(等于)、!=(不等于)

(基本操作过程是,首先对它的操作数进行比较,然后再返回一个true或False值。)

3.逻辑运算符:!(取反)、=(与之后赋值)、 (逻辑与)、 |=(或之后赋值)、 |(逻辑或)、^=(异或之后赋值)、 ^(逻辑异或)、 ?:(三目操作符)、||(或)、 (与)==(等于)、|=(不等于)。

4.字符串运算符:只有+ (”my“+”javascript“结果等于”my javascript“)

5.赋值运算符:即=,将右边的值赋给左边的变量。

6.条件运算符:(?:)例:status=(age=18)?”adult”:”child”;如果大于18,则表达式的值为adult。

7.typeof()运算符:用来返回变量或数据的类型。

八、IF语句。

if (条件)

语句段1

else

语句段2

功能:若表达式为true,则执行语句段1;否则执行语句段2。

说明:

if -else 语句是JavaScript中最基本的控制语句,通过它可以改变语句的执行顺序。

表达式中必须使用关系语句,来实现判断,它是作为一个布尔值来估算的。

它将零和非零的数分别转化成false和true。

若if后的语句有多行,则必须使用花括号将其括起来。

九、window.com()的用法

1、基本语法

window.open(pageURL,name,parameters)

其中:

pageURL 为子窗口路径

name 为子窗口句柄

parameters 为窗口参数(各参数用逗号分隔)

2. 窗口参数

其中yes/no也可使用1/0; value为具体的数值,单位象素。

toolbar=yes,no 是否显示工具条

location=yes,no 是否显示网址栏

directories=yes,no 是否显示导航条

status=yes,no 是否显示状态条

menubar=yes,no 是否显示菜单

scrollbars=yes,no 是否显示滚动条

resizable=yes,no 是否可以改变公告窗口大小

copyhistory=yes,no 是否显示历史按钮

width=value 公告窗口的宽

height=value 公告窗口的高

left=value 公告窗口的左上顶点距屏幕左边100像素

top=value 公告窗口的左上顶点距屏幕顶端100像素

例:

script language=”javascript”

!–

window.open(”00000.html”,”newwindow”,”toolbar=no,location=no,directories=no,status=no,menubar=no,

scrollbars=no,resizable=no,copyhistory=no,width=500,height=500,left=100,top=100″) //–

/script

十、for循环。另外就是数据类型。既for in

将字符串转换为数值:

javascript语言提供两个内置函数将表示数值的字符串转换为真实的数值:parseInt()和parseFloat()。

为了使用这些函数,需要将进行转换的字符串作为参数传入函数,例:

parseInt(”42″) //result=42

parseInt(”42.33″) //result=42

不过是浮点数还是整数,函数返回的值都是整数。不存在四舍五入,小数点和它后面的数字将被舍弃。

而parseFloat()则返回浮点数(如果是整数就返回整数),例:

parseFloat(”42″) //result=42

parseFloat(”42.33″) //result=42.33

如果在某处需要进行字符串的转换,只需将函数插入该初即可。如:

3+3+parseInt(”3″) //result=9

将数值转换为字符串:

虽然当遇到表达式中含有混合数据类型时,js会倾向于字符串。但为了防止潜在的问题发生,最好先转换以下。在数值中加入空字符串就可以把数值转换为字符串了:

(”"+2500) //result=”2500″

(”"+2500).length //result=4

For循环:

javascript中最常用的循环结构称之为for循环,关键词放在循环结构的开始位置。正式语法结构如下:

for ([initial expression];[condition];[update expression]){

statement[s] inside loop

}

例:

for(var i=0;i9;i++)

{

n+=i

myfunc(n)

}

for…in循环:

这个语句完全依照变量var所设定的值决定运行次数。你可以用for…in语句在一个对象或一个数组上建立循环

for(var in [obj | array])

{

statements

}

例:

script language=”javascript”

document.write(”The properties of the document object”)

for(var element in document){

document.write(element+”=”+document[element])

}

/script

十一、鼠标事件

主要内容就是基于鼠标的事件,有如下几种:

1.mouseover(鼠标移至)

2.mouseout(鼠标移出)

3.mousemove(鼠标移动)

4.mousedown(鼠标按下)

5.mouseup(鼠标弹起)

6.click(单击)

7.dblclick(双击)

例子:

html

head

titletest/title

script language=”javascript”

function text_onmouseover(){

mytext.style.fontSize=”30pt”;

mytext.style.color=”red”;

mytext.style.fontStyle=”italic”;

}

function text_onmouseout(){

mytext.style.fontSize=”20pt”;

mytext.style.color=”blue”;

mytext.style.fontStyle=”normal”;

}

/script

/head

body

p id=mytext onmouseover=”text_onmouseover()” onmouseout=”text_onmouseout()”;/p

p看看字体样式有什么变化/p

/body

/html

8.mouseDown事件和mouseUp事件

大家知道,mouseDown事件和mouseUp事件的组合就是click事件,但是如果在链接上按下鼠标,并移到链接之外在放开鼠标,那么就只有mouseDown事件了。这两个事件可以增加图标按钮的图像效果,

至于mouseDown和mouseUp的属性,它们是伴随着Click事件发生的,这和keyPress事件是keyDown事件和keyUp事件组合而成的机制是一样的,这3个鼠标事件也有modifier属性。

(注意:如果在onClick事件处理中使用return语句,它可以接收任何数值。只要这个值不是False,浏览器就可以完成提交。但如果浏览器得到的是False值,表单提交操作就会被取消。)

9.Click事件和dbClick事件

onClick是单击事件,onDblClick是双击事件,而实际上很难分清连续的单击和双击。它们会互相干扰。而且在ie和其他浏览器的情况还有不同。有的浏览器是双击事件的每一次单击都会触发单击事件,而在ie中,只有双击事件的第一次单击会触发单击事件。不管怎么样,单击事件都不会自动的取消或被忽略。因此,如果想使用单击和双击一个链接时触发两个完全不同的过程,则必须通过编程来延迟单击的动作知道双击。

script

var timer=null;

document.onclick=new Function(”timer=setTimeout(click,500)”)

document.ondblclick=new Function(”clearTimeout(timer);dblclick()”)

function click(){

alert(”click”)

}

function dblclick(){

alert(”dblclick”)

}

/script

十二、javascript函数.

函数是有function加函数名和一对带有参数括号,以及大括号组成的,其中大括号里是主体javascript语句.

例:

function hanshuname(js) //hanshuname是函数名.

{

document.write(js,”br”); //是函数的主体语句.

}

函数可以嵌套,如下:

function qiantao(a,b){

function lqiantao(x){return x*x;}

return Math.sqrt(lqiantao(a)+lqiantao(b));

}

函数还可以作为数据来应用,因此可以象处理其他数据那样来处理函数,如:赋值,存储,传递等.

例:

function zhi(x){return x*x;}

实际上,函数名没有什么意义,不过是保存函数的变量名而已.

a=zhi(6);//a存放的是数字36;

b=zhi;//现在b和zhi引用同一个函数.

c=b(5);//c存放的是数字25.

在一个函数体内,标识符arguments总是具有特殊含义,它是调用对象的一个特殊属性,用来引用实际参数对象.这个实际参数对象具有大量有用的属性.除此之外,它还兼有数组的角色.

尽管定义javascript函数时都有固定的参数,但调用这个函数时,传递给它的参数数目却可以是任意的,数组arguments[]允许完全存取那些实际参数值.另外,arguments有一个length属性,看如下例子:

function zhi(x,y,z)

{

if(arguments.length !=3){

alert(”function zhi called with”+arguments.length+”arguments,but it expects 3 arguments.”);

return null;

}

}

数组arguments[ ]还为javascript函数开发了一项重要的可能性,既可以将函数编写为能够接受任意数目的实际参数.

function zhi()

{

var m=Number.NEGATIVE_INFINITY;

//遍历所有参数

//检索并记忆最大的一个.

for(var i=0;iarguments.length;i++)

if(argumentsm)m=arguments;

//返回最大的参数值.

return m;

}

var lazgest=zhi(1,10,100,2,3,1000,4,5,10000,6);

也可以使用arguments[]数组来编写一个函数.

调用js函数

a href=”#” onClick=”functionName()”Link text/a

a href=”javascript:functionName()”Link text/a

50分!急急急!JavaScript画表格,怎样使其中一列分行显示?及时、高效帮忙解决还会追加分数。

td style="word-break:break-all"就搞定了。

其中可能对英文换行可能会分开一个单词问题:解决如下:

语法:

word-break : normal | break-all | keep-all

参数:

normal :  依照亚洲语言和非亚洲语言的文本规则,允许在字内换行

break-all :  该行为与亚洲语言的normal相同。也允许非亚洲语言文本行的任意字内断开。该值适合包含一些非亚洲文本的亚洲文本

keep-all :  与所有非亚洲语言的normal相同。对于中文,韩文,日文,不允许字断开。适合包含少量亚洲文本的非亚洲文本

br是软回车,就是换行后还是紧接着上一行,没有/br

p是段落标签,由于例如居中、缩进等标签都是以段落为单位的,所以它可比br有更多作用,但每次换行都会多空一行,有/p

除此之外,例如表格、表单、水平线等都是强制换行,就是紧接着的标签前无论有没有换行标签,都强制换行。

javascript里setTimeout(send(), 3000); 与 setTimeout(send,3000)的区别

这是setTimeout定义:

定义和用法

setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式。

语法

setTimeout(code,millisec)

参数

描述

code    必需。要调用的函数后要执行的 JavaScript 代码串。  

millisec    必需。在执行代码前需等待的毫秒数。  

//-------------------------

code调用运行机制:

当code为字符串时,会执行里面的字符串

当为函数名称时,会执行函数,但是不会再执行函数的字符串返回值

当为函数名称+括号时,会执行函数,并且也执行函数的返回值。

下面的例子可以帮助理解这种机制:

div id="d1"/div

div id="d2"/div

script

setTimeout(send1,1000);//传入函数名称

setTimeout(send2(),1000);//传入带括号的函数

setTimeout("alert('执行完毕')",1000);//直接传入字符串

function send1(){

document.getElementById("d1").innerHTML=(new Date());

return 'document.getElementById("d1").innerHTML="1现在时间是"+document.getElementById("d1").innerHTML;';

}

function send2(){

document.getElementById("d2").innerHTML=(new Date());

return 'document.getElementById("d2").innerHTML="2现在时间是"+document.getElementById("d2").innerHTML;';

}

/script

运行之后会发现,第一种调用只执行了函数,而没有执行函数的返回值,第二种除了执行了函数,还执行了函数以字符串形式的返回值.

由此可以归纳:

1. 需要连函数的返回值都要执行的话才用带括号的形式.这个前提是函数的返回值是字符串形式.这样的形式相当于调用了一个动态函数.

Javascript中Number,parseIn和parseFloat的区别

Number():

概述:Number 对象由 Number() 构造器创建,是经过封装的能让你处理数字值的对象。在非构造器上下文中 (如:没有 new 操作符),Number 能被用来执行类型转换。

语法:Number(value);

特点:

1、如果是Boolean值,true和false值将分别被转换为1和0。

2、如果是数字值,只是简单的传入和返回。

3、如果是null值,返回0。

4、如果是undefined,返回NaN。

5、如果是字符串:

a. 如果字符串中只包含数字时,将其转换为十进制数值,忽略前导0

b. 如果字符串中包含有效浮点格式,如“1.1”,将其转换为对应的浮点数字,忽略前导0

c. 如果字符串中包含有效的十六进制格式,如“0xf”,将其转换为相同大小的十进制数值

d. 如果字符串为空,将其转换为0

e. 如果字符串中包含除上述格式之外的字符,则将其转换为NaN

如果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用对象的toString()方法,然后再依照前面的规则转换返回的字符串值。

实例:

var num1 = Number("Hello world"); ·//NaN

var num2 = Number("");//0

var num3 = Number("0000011");  //11

var num4 = Number(3.14fasdasf); //Uncaught SyntaxError: Invalid or unexpected token

var num5 = Number("3.14fasdasf"); //NaN

parseInt():

概述:parseInt() 函数将给定的字符串以指定基数(radix/base)解析成为整数。

语法:parseInt(string, radix);

参数:string:要被解析的值。如果参数不是一个字符串,则将其转换为字符串。字符串开头的空白符将会被忽略。

radix:一个2到36之间的整数值,用于指定转换中采用的基数。比如参数"10"表示使用我们通常使用的十进制数值系统。总是指定该参数可以消除阅读该代码时的困惑并且保证转换结果可预测。当忽略该参数时,不同的实现环境可能产生不同的结果。

特点:

1、如果被解析参数的第一个字符无法被转化成数值类型,则返回 NaN。转换空字符串也会返回NaN。

2、开头和结尾的空白符允许存在,会被忽略,直到找到第一个非空格字符。

3、如果第一个字符是数字字符,parseInt() 会继续解析第二个字符,直到解析完所有后续字符串或者遇到了一个非数字字符。遇到不能解析的字符和其后的字符都将被忽略。接着返回已经解析的整数部分。

4、parseInt()方法还有基模式,可以把二进制、八进制、十六进制或其他任何进制的字符串转换成整数。

5、基是由parseInt()方法的第二个参数指定的,所以要解析十六进制的值,当然,对二进制、八进制,甚至十进制(默认模式),都可以这样调用parseInt()方法。

实例:

var num1 = parseInt("AF",16); //175

var num2 = parseInt("AF"); //NaN

var num3 = parseInt("10",2);//2(按照二进制解析)

var num4 = parseInt("sdasdad");//NaN

parseFloat():

概述:parseFloat()方法将参数中指定的字符串解析成为一个浮点数字并返回.

语法:parseFloat(string)

特点:

1、parseFloat是个全局函数,不属于任何对象。

2、如果在解析过程中遇到了正负号(+或-),数字(0-9),小数点,或者科学记数法中的指数(e或E)以外的字符,则它会忽略该字符以及之后的所有字符,返回当前已经解析到的浮点数.

3、字符串首位的空白符会被忽略.如果参数字符串的第一个字符不能被解析成为数字,则parseFloat返回NaN.

4、字符串中第一个小数点是有效的,而第二个小数点就是无效的了,它后面的字符串将被忽略。

5、parseFloat() 只解析十进制,因此它没有第二个参数指定基数的用法

6、如果字符串中包含的是一个可解析为正数的数(没有小数点,或者小数点后都是零),parseFloat() 会返回整数。

实例:

var num1 = parseFloat("123AF"); //123

var num2 = parseFloat("0xA");//0

var num3 = parseFloat("22.5");    //22.5

var num4 = parseFloat("22.3.56"); //22.3

var num5 = parseFloat("0908.5");  //908.5

Number()、parseInt() 和parseFloat() 的区别:

Number()的强制类型转换与parseInt()和parseFloat()方法的处理方式相似,只是它转换的是整个值,而不是部分值。如“3.4.5”,用Number()进行强制类型转换将返回NAN, 如果确定字符串值能被完整地转换,Number()将判断是调用parseInt()还是parseFloat()。

parseFloat() 所解析的字符串中第一个小数点是有效的,而parseInt() 遇到小数点会停止解析,因为小数点并不是有效的数字字符。

parseFloat() 始终会忽略前导的零,十六进制格式的字符串始终会被转换成0,而parseInt() 第二个参数可以设置基数,按照这个基数的进制来转换。

应用javascript做输入年月日,计算出星期几。

J2EE Java2平台企业版

string是引用数据类型

如何取得年月日,小时分秒

public static void main(String[] args)

{

ActionListener time = new ActionListener() { // 监听事件,不然实现不了动态改变时间

public void actionPerformed(ActionEvent e) {

//date对象代表当前的系统时间(毫秒)

Date date = new Date();

//format对象是用来以指定的时间格式格式化时间的

SimpleDateFormat from = new SimpleDateFormat(

"yyyy-MM-dd HH:mm:ss"); //这里的格式可以自己设置

//format()方法是用来格式化时间的方法

String times = from.format(date);

System.out.println(times); }

};

Timer tim = new Timer(1000, time); //这里表示1000毫秒更新一下时间

tim.start(); //启动

}

我这个答案肯定正确啊

下面帮你解释你的答案吧

Date //是在java.util.Date;里面

SimpleDateForma //这个是java.text.SimpleDateFormat;用来输出问本格式的

DateFormat //应该是在java.util.*;里面吧..应该是的

你那个错误是编译就没通过啊

public class Test

那你那个编译写的因该是

javac Test.java 编译的应该是类啊而不是javac time.java 请问你的time什么意思呢,所以你报的异常是找不到time类啊

呵呵...你是初学java吧该答的我都答完了拉!还特地帮你每句都写

如何读写文件

StringBuffer sb = new StringBuffer();

//File file = new FileWindow().load();

File file;

file = new File("F:/jtest/from.txt");

TextReader tr = new TextReader(file);

sb.append(tr.readAll());

Out.println(sb.toString());

String [] tags = ;

String str;

str = sb.toString();

for(String reg: tags) {

Out.println(reg);

str = str.replaceAll(reg, "");

}

Out.println(str);

抽象类和接口的区别

声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。

接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口。

主键是确定数据库中的表的记录的唯一标识字段,可以是表中的一个字段,也可以是表中的多个字段组成的。一旦确定为主键,则该字段不可为空也不可以重复。比如学生表中的学号就可以定义成该表的字段

外键的定义是相对于主键而言的,比如另有一张成绩表,表中也出现了学生表中的对应学号字段,则相对于学生表,学号就是成绩表的外键

String和StringBuffer的区别

STRING的长度是不可变的,STRINGBUFFER的长度是可变的。如果你对字符串中的内容经常进行操作,特别是内容要修改时,那么使用StringBuffer,如果最后需要String,那么使用StringBuffer的toString()方法

tryfinally内出现异常,try内的代码呢?finally{}后面的代码呢

执行 finally{}内的代码最后执行

排序算法

所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。

分类

在计算机科学所使用的排序算法通常被分类为:

计算的复杂度(最差、平均、和最好表现),依据串列(list)的大小(n)。一般而言,好的表现是O。(n log n),且坏的行为是Ω(n2)。对於一个排序理想的表现是O(n)。仅使用一个抽象关键比较运算的排序算法总平均上总是至少需要Ω(n log n)。

记忆体使用量(以及其他电脑资源的使用)

稳定度:稳定排序算法会依照相等的关键(换言之就是值)维持纪录的相对次序。也就是一个排序算法是稳定的,就是当有两个有相等关键的纪录R和S,且在原本的串列中R出现在S之前,在排序过的串列中R也将会是在S之前。

一般的方法:插入、交换、选择、合并等等。交换排序包含冒泡排序(bubble sort)和快速排序(quicksort)。选择排序包含shaker排序和堆排序(heapsort)。

当相等的元素是无法分辨的,比如像是整数,稳定度并不是一个问题。然而,假设以下的数对将要以他们的第一个数字来排序。

(4, 1) (3, 1) (3, 7) (5, 6)

在这个状况下,有可能产生两种不同的结果,一个是依照相等的键值维持相对的次序,而另外一个则没有:

(3, 1) (3, 7) (4, 1) (5, 6) (维持次序)

(3, 7) (3, 1) (4, 1) (5, 6) (次序被改变)

不稳定排序算法可能会在相等的键值中改变纪录的相对次序,但是稳定排序算法从来不会如此。不稳定排序算法可以被特别地时作为稳定。作这件事情的一个方式是人工扩充键值的比较,如此在其他方面相同键值的两个物件间之比较,就会被决定使用在原先资料次序中的条目,当作一个同分决赛。然而,要记住这种次序通常牵涉到额外的空间负担。

排列算法列表

在这个表格中,n是要被排序的纪录数量以及k是不同键值的数量。

稳定的

冒泡排序(bubble sort) — O(n2)

鸡尾酒排序 (Cocktail sort, 双向的冒泡排序) — O(n2)

插入排序 (insertion sort)— O(n2)

桶排序 (bucket sort)— O(n); 需要 O(k) 额外 记忆体

计数排序 (counting sort) — O(n+k); 需要 O(n+k) 额外 记忆体

归并排序 (merge sort)— O(n log n); 需要 O(n) 额外记忆体

原地归并排序 — O(n2)

二叉树排序 (Binary tree sort) — O(n log n); 需要 O(n) 额外记忆体

鸽巢排序 (Pigeonhole sort) — O(n+k); 需要 O(k) 额外记忆体

基数排序 (radix sort)— O(n·k); 需要 O(n) 额外记忆体

Gnome sort — O(n2)

Library sort — O(n log n) with high probability, 需要 (1+ε)n 额外记忆体

不稳定

选择排序 (selection sort)— O(n2)

希尔排序 (shell sort)— O(n log n) 如果使用最佳的现在版本

Comb sort — O(n log n)

堆排序 (heapsort)— O(n log n)

Smoothsort — O(n log n)

快速排序 (quicksort)— O(n log n) 期望时间, O(n2) 最坏情况; 对於大的、乱数串列一般相信是最快的已知排序

Introsort — O(n log n)

Patience sorting — O(n log n + k) 最外情况时间, 需要 额外的 O(n + k) 空间, 也需要找到最长的递增子序列(longest increasing subsequence)

不实用的排序算法

Bogo排序 — O(n × n!) 期望时间, 无穷的最坏情况。

Stupid sort — O(n3); 递回版本需要 O(n2) 额外记忆体

Bead sort — O(n) or O(√n), 但需要特别的硬体

Pancake sorting — O(n), 但需要特别的硬体

排序的算法

排序的算法有很多,对空间的要求及其时间效率也不尽相同。下面列出了一些常见的排序算法。这里面插入排序和冒泡排序又被称作简单排序,他们对空间的要求不高,但是时间效率却不稳定;而后面三种排序相对于简单排序对空间的要求稍高一点,但时间效率却能稳定在很高的水平。基数排序是针对关键字在一个较小范围内的排序算法。

插入排序

冒泡排序

选择排序

快速排序

堆排序

归并排序

基数排序

希尔排序

插入排序

插入排序是这样实现的:

首先新建一个空列表,用于保存已排序的有序数列(我们称之为"有序列表")。

从原数列中取出一个数,将其插入"有序列表"中,使其仍旧保持有序状态。

重复2号步骤,直至原数列为空。

插入排序的平均时间复杂度为平方级的,效率不高,但是容易实现。它借助了"逐步扩大成果"的思想,使有序列表的长度逐渐增加,直至其长度等于原列表的长度。

冒泡排序

冒泡排序是这样实现的:

首先将所有待排序的数字放入工作列表中。

从列表的第一个数字到倒数第二个数字,逐个检查:若某一位上的数字大于他的下一位,则将它与它的下一位交换。

重复2号步骤,直至再也不能交换。

冒泡排序的平均时间复杂度与插入排序相同,也是平方级的,但也是非常容易实现的算法。

选择排序

选择排序是这样实现的:

设数组内存放了n个待排数字,数组下标从1开始,到n结束。

i=1

从数组的第i个元素开始到第n个元素,寻找最小的元素。

将上一步找到的最小元素和第i位元素交换。

如果i=n-1算法结束,否则回到第3步

选择排序的平均时间复杂度也是O(n²)的。

快速排序

现在开始,我们要接触高效排序算法了。实践证明,快速排序是所有排序算法中最高效的一种。它采用了分治的思想:先保证列表的前半部分都小于后半部分,然后分别对前半部分和后半部分排序,这样整个列表就有序了。这是一种先进的思想,也是它高效的原因。因为在排序算法中,算法的高效与否与列表中数字间的比较次数有直接的关系,而"保证列表的前半部分都小于后半部分"就使得前半部分的任何一个数从此以后都不再跟后半部分的数进行比较了,大大减少了数字间不必要的比较。但查找数据得另当别论了。

堆排序

堆排序与前面的算法都不同,它是这样的:

首先新建一个空列表,作用与插入排序中的"有序列表"相同。

找到数列中最大的数字,将其加在"有序列表"的末尾,并将其从原数列中删除。

重复2号步骤,直至原数列为空。

堆排序的平均时间复杂度为nlogn,效率高(因为有堆这种数据结构以及它奇妙的特征,使得"找到数列中最大的数字"这样的操作只需要O(1)的时间复杂度,维护需要logn的时间复杂度),但是实现相对复杂(可以说是这里7种算法中比较难实现的)。

看起来似乎堆排序与插入排序有些相像,但他们其实是本质不同的算法。至少,他们的时间复杂度差了一个数量级,一个是平方级的,一个是对数级的。

平均时间复杂度

插入排序 O(n2)

冒泡排序 O(n2)

选择排序 O(n2)

快速排序 O(n log n)

堆排序 O(n log n)

归并排序 O(n log n)

基数排序 O(n)

希尔排序 O(n1.25)

一、术语session

在我的经验里,session这个词被滥用的程度大概仅次于transaction,更加有趣的是transaction与session在某些语境下的含义是相同的。

session,中文经常翻译为会话,其本来的含义是指有始有终的一系列动作/消息,比如打电话时从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。有时候我们可以看到这样的话“在一个浏览器会话期间,...”,这里的会话一词用的就是其本义,是指从一个浏览器窗口打开到关闭这个期间①。最混乱的是“用户(客户端)在一次会话期间”这样一句话,它可能指用户的一系列动作(一般情况下是同某个具体目的相关的一系列动作,比如从登录到选购商品到结账登出这样一个网上购物的过程,有时候也被称为一个transaction),然而有时候也可能仅仅是指一次连接,也有可能是指含义①,其中的差别只能靠上下文来推断②。

然而当session一词与网络协议相关联时,它又往往隐含了“面向连接”和/或“保持状态”这样两个含义,“面向连接”指的是在通信双方在通信之前要先建立一个通信的渠道,比如打电话,直到对方接了电话通信才能开始,与此相对的是写信,在你把信发出去的时候你并不能确认对方的地址是否正确,通信渠道不一定能建立,但对发信人来说,通信已经开始了。“保持状态”则是指通信的一方能够把一系列的消息关联起来,使得消息之间可以互相依赖,比如一个服务员能够认出再次光临的老顾客并且记得上次这个顾客还欠店里一块钱。这一类的例子有“一个TCP session”或者“一个POP3 session”③。

而到了web服务器蓬勃发展的时代,session在web开发语境下的语义又有了新的扩展,它的含义是指一类用来在客户端与服务器之间保持状态的解决方案④。有时候session也用来指这种解决方案的存储结构,如“把xxx保存在session里”⑤。由于各种用于web开发的语言在一定程度上都提供了对这种解决方案的支持,所以在某种特定语言的语境下,session也被用来指代该语言的解决方案,比如经常把Java里提供的javax.servlet.http.HttpSession简称为session⑥。

鉴于这种混乱已不可改变,本文中session一词的运用也会根据上下文有不同的含义,请大家注意分辨。

在本文中,使用中文“浏览器会话期间”来表达含义①,使用“session机制”来表达含义④,使用“session”表达含义⑤,使用具体的“HttpSession”来表达含义⑥

二、HTTP协议与状态保持

HTTP协议本身是无状态的,这与HTTP协议本来的目的是相符的,客户端只需要简单的向服务器请求下载某些文件,无论是客户端还是服务器都没有必要纪录彼此过去的行为,每一次请求之间都是独立的,好比一个顾客和一个自动售货机或者一个普通的(非会员制)大卖场之间的关系一样。

然而聪明(或者贪心?)的人们很快发现如果能够提供一些按需生成的动态信息会使web变得更加有用,就像给有线电视加上点播功能一样。这种需求一方面迫使HTML逐步添加了表单、脚本、DOM等客户端行为,另一方面在服务器端则出现了CGI规范以响应客户端的动态请求,作为传输载体的HTTP协议也添加了文件上载、cookie这些特性。其中cookie的作用就是为了解决HTTP协议无状态的缺陷所作出的努力。至于后来出现的session机制则是又一种在客户端与服务器之间保持状态的解决方案。

让我们用几个例子来描述一下cookie和session机制之间的区别与联系。笔者曾经常去的一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠,然而一次性消费5杯咖啡的机会微乎其微,这时就需要某种方式来纪录某位顾客的消费数量。想象一下其实也无外乎下面的几种方案:

1、该店的店员很厉害,能记住每位顾客的消费数量,只要顾客一走进咖啡店,店员就知道该怎么对待了。这种做法就是协议本身支持状态。

2、发给顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每次消费时,如果顾客出示这张卡片,则此次消费就会与以前或以后的消费相联系起来。这种做法就是在客户端保持状态。

3、发给顾客一张会员卡,除了卡号之外什么信息也不纪录,每次消费时,如果顾客出示该卡片,则店员在店里的纪录本上找到这个卡号对应的纪录添加一些消费信息。这种做法就是在服务器端保持状态。

由于HTTP协议是无状态的,而出于种种考虑也不希望使之成为有状态的,因此,后面两种方案就成为现实的选择。具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的,但实际上它还有其他选择。

三、理解cookie机制

cookie机制的基本原理就如上面的例子一样简单,但是还有几个问题需要解决:“会员卡”如何分发;“会员卡”的内容;以及客户如何使用“会员卡”。

正统的cookie分发是通过扩展HTTP协议来实现的,服务器通过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的cookie。然而纯粹的客户端脚本如JavaScript或者VBScript也可以生成cookie。

而cookie的使用是由浏览器按照一定的原则在后台自动发送给服务器的。浏览器检查所有存储的cookie,如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置,则把该cookie附在请求资源的HTTP请求头上发送给服务器。意思是麦当劳的会员卡只能在麦当劳的店里出示,如果某家分店还发行了自己的会员卡,那么进这家店的时候除了要出示麦当劳的会员卡,还要出示这家店的会员卡。

cookie的内容主要包括:名字,值,过期时间,路径和域。

其中域可以指定某一个域比如.google.com,相当于总店招牌,比如宝洁公司,也可以指定一个域下的具体某台机器比如或者froogle.google.com,可以用飘柔来做比。

路径就是跟在域名后面的URL路径,比如/或者/foo等等,可以用某飘柔专柜做比。

路径与域合在一起就构成了cookie的作用范围。

如果不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不存储在硬盘上而是保存在内存里,当然这种行为并不是规范规定的。如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie仍然有效直到超过设定的过期时间。

存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存里的cookie,不同的浏览器有不同的处理方式。对于IE,在一个打开的窗口上按Ctrl-N(或者从文件菜单)打开的窗口可以与原窗口共享,而使用其他方式新开的IE进程则不能共享已经打开的窗口的内存cookie;对于Mozilla Firefox0.8,所有的进程和标签页都可以共享同样的cookie。一般来说是用javascript的window.open打开的窗口会与原窗口共享内存cookie。浏览器对于会话cookie的这种只认cookie不认人的处理方式经常给采用session机制的web应用程序开发者造成很大的困扰。

下面就是一个goolge设置cookie的响应头的例子

HTTP/1.1 302 Found

Location:

Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com

Content-Type: text/html

这是使用HTTPLook这个HTTP Sniffer软件来俘获的HTTP通讯纪录的一部分

浏览器在再次访问goolge的资源时自动向外发送cookie

使用Firefox可以很容易的观察现有的cookie的值

使用HTTPLook配合Firefox可以很容易的理解cookie的工作原理。

IE也可以设置在接受cookie前询问

这是一个询问接受cookie的对话框。

四、理解session机制

session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。

当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。

保存这个session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发挥给服务器。一般这个cookie的名字都是类似于SEEESIONID,而。比如weblogic对于web应用程序生成的cookie,JSESSIONID=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是JSESSIONID。

由于cookie可以被人为的禁止,必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器。经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面,附加方式也有两种,一种是作为URL路径的附加信息,表现形式为;jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764

另一种是作为查询字符串附加在URL后面,表现形式为!-145788764

这两种方式对于用户来说是没有区别的,只是服务器在解析的时候处理的方式不同,采用第一种方式也有利于把session id的信息和正常程序参数区分开来。

为了在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id。

另一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。比如下面的表单

form name="testform" action="/xxx"

input type="text"

/form

在被传递给客户端之前将被改写成

form name="testform" action="/xxx"

input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764"

input type="text"

/form

这种技术现在已较少应用,笔者接触过的很古老的iPlanet6(SunONE应用服务器的前身)就使用了这种技术。

实际上这种技术可以简单的用对action应用URL重写来代替。

在谈论session机制的时候,常常听到这样一种误解“只要关闭浏览器,session就消失了”。其实可以想象一下会员卡的例子,除非顾客主动对店家提出销卡,否则店家绝对不会轻易删除顾客的资料。对session来说也是一样的,除非程序通知服务器删除一个session,否则服务器会一直保留,程序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根本不会有机会知道浏览器已经关闭,之所以会有这种错觉,是大部分session机制都使用会话cookie来保存session id,而关闭浏览器后这个session id就消失了,再次连接服务器时也就无法找到原来的session。如果服务器设置的cookie被保存到硬盘上,或者使用某种手段改写浏览器发出的HTTP请求头,把原来的session id发送给服务器,则再次打开浏览器仍然能够找到原来的session。

恰恰是由于关闭浏览器不会导致session被删除,迫使服务器为seesion设置了一个失效时间,当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间。

五、理解javax.servlet.http.HttpSession

HttpSession是Java平台对session机制的实现规范,因为它仅仅是个接口,具体到每个web应用服务器的提供商,除了对规范支持之外,仍然会有一些规范里没有规定的细微差异。这里我们以BEA的Weblogic Server8.1作为例子来演示。

首先,Weblogic Server提供了一系列的参数来控制它的HttpSession的实现,包括使用cookie的开关选项,使用URL重写的开关选项,session持久化的设置,session失效时间的设置,以及针对cookie的各种设置,比如设置cookie的名字、路径、域,cookie的生存时间等。

一般情况下,session都是存储在内存里,当服务器进程被停止或者重启的时候,内存里的session也会被清空,如果设置了session的持久化特性,服务器就会把session保存到硬盘上,当服务器进程重新启动或这些信息将能够被再次使用,Weblogic Server支持的持久性方式包括文件、数据库、客户端cookie保存和复制。

复制严格说来不算持久化保存,因为session实际上还是保存在内存里,不过同样的信息被复制到各个cluster内的服务器进程中,这样即使某个服务器进程停止工作也仍然可以从其他进程中取得session。

cookie生存时间的设置则会影响浏览器生成的cookie是否是一个会话cookie。默认是使用会话cookie。有兴趣的可以用它来试验我们在第四节里提到的那个误解。

cookie的路径对于web应用程序来说是一个非常重要的选项,Weblogic Server对这个选项的默认处理方式使得它与其他服务器有明显的区别。后面我们会专题讨论。

关于session的设置参考[5]

~~我要200分~~


网页名称:javascript依照,javascript中!
本文路径:http://hbruida.cn/article/dsdoedp.html