[转载]Tab切换类Lix Tabs 0.1发布

mikel阅读(916)

[转载]Tab切换类Lix Tabs 0.1发布 – 十年灯 – 博客园.

近期正在做的这个网站中,有的页面同时会出现好几个tab切换效果。在没有写这个类之前,每碰到多一个TAB我就得复制一遍tab函数,关键是这函数其实功能与前几个没什么两样。但不复制又不行,因为那tab函数是没法重用的。每当做到这里,都让我苦不堪言。

在博客园上参观了几位牛人的JavaScript实例后,我就开始琢磨着写这么一个类。这是否能叫类呢,我也不确定,不过确定能用就行了。修修改改 用了两周+的时间,发现好像没什么bug了,于是发布出来,斗胆加上个自己的代号吧。顺便放出源码供新人参考,高手看了也不要批我,我真的是新手。

功能与示例:

可以实现同一页面N个tab切换(n>0),效果可参考网易首页的那一整篇tab菜单,或点击查看示例页

Lix Tabs的源码:

var $id=function(id){
return (typeof id == "Object") ? id : document.getElementById(id);
};
var $$=function(tag,elm){
return elm.getElementsByTagName(tag);
};
var $C=function(cn,tag,elm){
if(!tag) tag='*';
var ts = $$(tag,elm);
var classArr = [];
var filter = new RegExp("(^|\\s)"+cn+"(\\s|$)");
for(var i=0,l=ts.length;i 			if(filter.test(ts[i].className)){
classArr.push(ts[i]);
}
}
return classArr;
}
var cutover=function(arr,cur,c1,c0){
for(var i=0,l=arr.length;i 			arr[i].className = (i ==cur) ? c1 : c0;
}
}

var Tabs = function (elm){
if(elm == null){return false;}
var t=this;
/*开始缓存传入参数*/
t.hdtag =arguments[1].hdtag || t.items.hdtag;
t.hdcn =arguments[1].hdcn || t.items.hdcn;
t.hdtagcur =arguments[1].hdtagcur || t.items.hdtagcur;
t.hdtagno =arguments[1].hdtagno || t.items.hdtagno;
t.bdtag =arguments[1].bdtag || t.items.bdtag;
t.bdcn =arguments[1].bdcn || t.items.bdcn;
t.bdtagcur =arguments[1].bdtagcur || t.items.bdtagcur;
t.bdtagno =arguments[1].bdtagno || t.items.bdtagno;
/*缓存参数完成*/

t.tabhd = $C(t.hdcn,t.hdtag,elm)[0];
t.tabtag = t.tabhd.children;
t.tabbd = $C(t.bdcn,t.bdtag,elm)[0];
t.tabcon = t.tabbd.children;

t.now = 0;
t.time =arguments[1].auto;
t.sum = t.tabtag.length;
if(t.sum != t.tabcon.length) {
alert('Tab标签个数与内容个数不匹配');
return true;
}
(function(){

for(var i=0;i 				t.tabtag[i].to = i;
t.tabtag[i].onmouseover = function(){
t.now = this.to;
t.change();
}
}
})();

if(t.time) {
function go(){
t.change();
t.now = (t.now == t.sum-1) ? 0 : t.now+1;
t.run =setTimeout(arguments.callee,t.time);
};
go();
elm.onmouseover = function(){clearTimeout(t.run);}
elm.onmouseout = function(){t.run =setTimeout(go,t.time);}
}

}

Tabs.prototype = {
items:{
hdtag:'DIV',
hdcn:'tabhd',
hdtagcur:'cur',
hdtagno:'',
bdtag:'DIV',
bdcn:'tabbd',
bdtagcur:'cur',
bdtagno:''
},
change:function(){
cutover(this.tabtag,this.now,this.hdtagcur,this.hdtagno);
cutover(this.tabcon,this.now,this.bdtagcur,this.bdtagno);
}
};

Lix Tabs的说明:

1,基本说明:

有默认参数如下:

items:{
hdtag:'DIV',//tab头的标签
hdcn:'tabhd',//tab头的className
hdtagcur:'cur',//tab头中当前标签的className
hdtagno:'',//tab头中非当前标签的className
bdtag:'DIV',//tab内容区的标签
bdcn:'tabbd',//tab内容区的className
bdtagcur:'cur',//tab内容区中当前标签的className
bdtagno:''//tab内容区中非当前标签的className
}

绕晕了?实例对照:

<div id="tabLite" class="inner">
<div class="tabhd"><a class="cur" href="#">城市指数</a><a href="#">名牌指数</a><a href="#">网上百货</a></div>
<div class="tabbd">
<div class="cur">
<ul>
	<li>·<a href="#">0上海起火楼工程多萨斯附属卡</a></li>
	<li>·<a href="#">损失达5亿 忠犬不吃了快速扩大解放</a></li>
</ul>
</div>
<div>
<ul>
	<li>·<a href="#">1上海起火楼工程多</a></li>
	<li>·<a href="#">损失达5亿 忠犬不吃</a></li>
</ul>
</div>
<div>
<ul>
	<li>·<a href="#">2上海起火楼工程多</a></li>
	<li>·<a href="#">损失达5亿 忠犬不吃</a></li>
</ul>
</div>
</div>
</div>

2,使用指南:

Lix Tabs有三个重要的外置函数,即$id=>getElementById,$$=>getElementsByTagName,$C=>getElementsByClassName…具体请看源码

有一个必需参数,就是到底是哪个HTML对象要切换(注:参数是html对象而不是字符串!)

调用

参数默认时:var t1 = new Tabs($id(‘t1’));(划线位置即是一个通过$id得到的HTML元素)

自传参数:

var t1=new Tabs($id('blog'),{hdcn:'tab-hd',hdtagcur:'tab-u current',hdtagno:'tab-u',bdcn:'tab-bd',bdtagcur:'current',bdtagno:'tab-con',auto:4000});

注:auto的值就是自动切换的间隔时间,如果不想自动切换,不传auto即可.

如果tab太多,那像上面那样一个一个new无疑太麻烦了。这时也可批量定义,给需要tab的地方都加上一个共同的class吧:

/* 批量定义 */<br> var as = $C('as','DIV',document);
for(var i=0,l=as.length;i<l;i++){
as[i].tab = new Tabs(as[i],{hdtag:'UL',hdcn:'sn',hdtagcur:'now',bdcn:'imgs',bdtagcur:'cur',auto:2000});
}

:批量定义适于类似网易首页的多tab结构甚至CSS都相同的情况.

容错能力:

只对最常见的错误–Tabs(elm)的elm拼错了而导致找不到HTML对象–有容错能力,Tabs会忽略这个错误,所以不会影响后续调用.

Lix Tabs的优缺点:

优点:代码少,纯代码大概2.3K;可批量应用;可设置是否自动切换;自动识别tab标签个数…貌似没了

缺点:切换无过渡特效,一点也不炫;也许有暂未发现的效率问题;也许源代码不够优化;参数也许有点多…

已知问题:在得到tab元素时使用的是children而非childNodes,所以不符合W3C标准。。。有w3c强迫症的人群慎用

完整实例下载:点击下载

———————————————————————————-

结语:Lix Tabs是个功能非常简单的JS类,所以尽量精简.这次发布的是0.1版,如果以后我的JS水平提高了,肯定会改进+优化,但应该不会添加过渡特效…

[转载]ASP.NET MVC 3 RTM 更新(2)

mikel阅读(939)

[转载]ASP.NET MVC 3 RTM 更新(2) – Catcher In The Rye – 博客园.

三、IResolver<TService>和 SingleServiceResolver<TService>:IResolver<TService>、 MultiServiceResolver<TService>:IResolver<IEnumerable<TService>>

IResolver<TService>接口只有一个TService型的Current只读属性,返回相应类型的一个对象。这是一个有Lazy意味的轻量接口。
一个简单的IResolver<TService>接口的实现类中,Current可以返回Activator.CreateInstance创建的实例——在面向接口编程方面讲,完全是有意义的。

SingleServiceResolver 类是IResolver<TService>的实现,它用于获取单个对象,其实现原理是:在构造对象时,方法内部或作为参数指定一种默认的对 象创建(获取)”方式”——方式1,作为参数传入另一种创建(获取)”方式”——方式2和当
当两种创建(获取)对象都不成功的情况下(两种方式都成功,则会抛出异常)提供一个默认对象。

具体来说,在它公共的构造方法中,指定的方式1为DependencyResolver.Current(IDependencyResolver)。
当 调用SingleServiceResolver类的Current属性时,首先判断如果方式1不为null,则通过 DependencyResolver.Current.GetService(typeof(TService))获取一个TService对象,如果 创建(获取)成功,则尝试方式2创建(获取),如果也成功则抛出异常。
返回值的时候,先判方式1如果为null,则获取方式2的执行结果,如果结果不为null,则返回该结果,否则返回默认对象。

在 它的internal构造方法中,还允许传入默认创建(获取)方式以赋给方式1。在两个构造方法中还允许传入一个字符串标明是哪个方法在创建 SingleServiceResolver对象(或者说Current返回的对象)。在有异常发生时,可以将该字符串传入异常对象。

MultiServiceResolver 类也是IResolver<TService>的实现,它用于获取一个集合对象,其实现原理是:在构造对象时,方法内部或作为参数指定一种默 认的对象创建(获取)”方式”——方式1,作为参数传入另一种创建(获取)”方式”——方式2。
返回两种方式创建(获取)的集合的合集。

具体来说,在它公共的构造方法中,指定的方式1为DependencyResolver.Current(IDependencyResolver)。
当 调用MultiServiceResolver类的Current属性时,首先判断如果方式1不为null,则通过 DependencyResolver.Current.GetServices(typeof(TService))获取一个 IEnumerable<TService>对象,该集合对象可以没有元素但不能为null,
然后将方式2创建的集合与方式1创建(获取)的集合合并返回。

四、ControllerBuilder

我 们知道在MVC2中,Controller通过ControllerFactory创建,而ControllerFactory通过 ControllerBuilder的单例ControllerBuilder.Current的GetControllerFactory()方法获 取。类的默认构造方法中会初始化一个DefaultControllerFactory对象,并通过SetControllerFactory方法将其包 装成一个Func<IControllerFactory>实例,并赋值给_factoryThunk私有委托,当调用 GetControllerFactory方法时,返回的是该委托的执行结果。

在MVC3中,ControllerBuilder类的构造方法和GetControllerFactory方法的实现又有所不同。
ControllerBuilder 有一个IResolver<IControllerFactory>型的私有变量_serviceResolver。从上面的分析我们知 道,IResolver<IControllerFactory>有唯一的只读属性T Current,调用_serviceResolver.Current将返回一个IControllerFactory对象。
默认构造不再直接创建DefaultControllerFactory对象,只是简单的调用新增的接受一个IResolver<IControllerFactory>接口参数的构造方法。该方法目前是internal的。
internal ControllerBuilder(IResolver<IControllerFactory> serviceResolver) {
_serviceResolver = serviceResolver ?? new SingleServiceResolver<IControllerFactory>(
() => _factoryThunk(),
new DefaultControllerFactory { ControllerBuilder = this },
“ControllerBuilder.GetControllerFactory”
);
}
在 有参构造方法内部,如果传入的参数serviceResolver为null则创建一个实现了 IResolver<IControllerFactory>接口的 SingleServiceResolver<TService>类的对象赋给私有变量_serviceResolver。 ControllerBuilder.Current是一个通过默认构造函数创建的对象,用到了单例模式。所以这里serviceResolver参数是 为null的。

深入SingleServiceResolver类内部我们知道,它首先会尝试从 DependencyResolver.Current.GetService(typeof(IControllerFactory))获取 IControllerFactory对象,在默认情况会调用 Activator.CreateInstance(typeof(IControllerFactory)),当然会是null。所以最终会创建 DefaultControllerFactory作为我们的默认ControllerFactory。

假设定义了一个UnityControllerFactory:IControllerFactory。
首先,我们可以像MVC2中那样使用SetControllerFactory设置IControllerFactory
假设我们又实现了一个UnityDependencyResolver:IDenpendencyResovler,并将其设置为当前的IDenpendencyResovler。
在UnityContainer中将UnityControllerFactory映射到IControllerFactory接口,同样可以达到设置ControllerFactory的目的。

另外,GetControllerFactory方法返回的不再是像MVC2中的_factoryThunk的执行结果,而是_serviceResolver的Current属性。

[转载]Bing Maps Android SDK Released

mikel阅读(973)

[转载]Bing Maps Android SDK Released – Bēniaǒ成长笔记 – 博客园.

Bing Maps Android SDK是一套使用JAVA语言基于微软Bing Maps AJAX v7 Control之上开发的一套GIS开发API,并开源发布于Codeplex,以帮助Android开发人员创建基于微软Bing Maps AJAX V7 Control的地图应用程序。

项目地址http://bingmapsandroidsdk.codeplex.com/

功能列表

– Built on top of Bing Maps AJAX V7
– Touch controls added to support pinch to zoom, and double tap to zoom
– Majority of map functionalities are wrapped with Java code so that there is no need to write JavaScript code. This should make things easier for Android developers.
– Requires Bing Maps Key
– Supports Pushpins, Polylines, Polygons, EntityCollections, and TileLayers.
– Libraries for accessing Bing Maps REST service supports Geocoding (Address and query searches), Reverse Geocoding, Routing with support for all route options.
– Libraries for accessing Bing Spatial Data service supports FindByArea, FindByID, and FindByProperty.
– All service calls have an Asynchronous task which make requests to Bing Servers and parses the response on a background tread.
– Works in any orientation.
– Infobox support.
– Support for GeoRSS files.

未来计划

– Support for localization.
– Documentation of code, and articles on how to use the SDK to create an application.
– UI controls for rotating Birdseye view.
– Clustering.
– Best Map View support for data.
– Location Details view.

参考资料

[1]、http://rbrundritt.wordpress.com/2011/03/21/bing-maps-android-sdk-released/

[转载]Bing Maps Android SDK Released

mikel阅读(896)

[转载]Bing Maps Android SDK Released – Bēniaǒ成长笔记 – 博客园.

Bing Maps Android SDK是一套使用JAVA语言基于微软Bing Maps AJAX v7 Control之上开发的一套GIS开发API,并开源发布于Codeplex,以帮助Android开发人员创建基于微软Bing Maps AJAX V7 Control的地图应用程序。

项目地址http://bingmapsandroidsdk.codeplex.com/

功能列表

– Built on top of Bing Maps AJAX V7
– Touch controls added to support pinch to zoom, and double tap to zoom
– Majority of map functionalities are wrapped with Java code so that there is no need to write JavaScript code. This should make things easier for Android developers.
– Requires Bing Maps Key
– Supports Pushpins, Polylines, Polygons, EntityCollections, and TileLayers.
– Libraries for accessing Bing Maps REST service supports Geocoding (Address and query searches), Reverse Geocoding, Routing with support for all route options.
– Libraries for accessing Bing Spatial Data service supports FindByArea, FindByID, and FindByProperty.
– All service calls have an Asynchronous task which make requests to Bing Servers and parses the response on a background tread.
– Works in any orientation.
– Infobox support.
– Support for GeoRSS files.

未来计划

– Support for localization.
– Documentation of code, and articles on how to use the SDK to create an application.
– UI controls for rotating Birdseye view.
– Clustering.
– Best Map View support for data.
– Location Details view.

参考资料

[1]、http://rbrundritt.wordpress.com/2011/03/21/bing-maps-android-sdk-released/

[转载]ASP.NET MVC 3 RTM 更新(1)

mikel阅读(928)

[转载]ASP.NET MVC 3 RTM 更新(1) – Catcher In The Rye – 博客园.

一、路由(Routing)

路由功能最初整合在ASP.NET MVC(以下简称MVC)中,后来被独立出来形成了System.Web.Routing 3.5程序集。ASP.NET 4已经把Routing功能已经转移到了System.Web 4 程序集下作为基础服务的一部分。在使用Routing功能时,您已不再需要在web.config中注册Module,因为 UrlRoutingModule已经集成进ASP.NET 4中了,就像FormsAuthenticationModule等Module一样。而ASP.NET MVC 3(以下简称MVC3)是基于ASP.NET 4的。

在System.Web.Routing 3.5中,UrlRoutingModule通过处理PostResolveRequestCache和PostMapRequestHandler事件 来配合设置请求处理程序(IHttpHandler),而在System.Web.Routing 4中,只处理了PostResolveRequestCache事件(PostMapRequestHandler事件也处理了,但什么都不做,但已标明 过期)。

值得一提的是ASP.NET 4的HttpContext新增加了一个RequestContext属性,其类型正是System.Web.Routing.RequestContext。该类封装了当前请求上下文以及RouteData。

增加了PageRouteHandler类以支持WebForm的路由功能,该类实现IRouteHandler接口。而在ASP.NET 2.0中,得自己实现类似的IRouteHandler。
为了更方便的添加该类型的路由规则,RouteCollection类中还新增加了四个MapPageRoute的重载方法。

简单演示一下:
1、新建一个基于.Net 4的Web Application。
2、新建Global.asa并修改Global.asa.cs的Application_Start方法
void Application_Start(object sender, EventArgs e)
{
// 以下两种方式都可以添加路由规则,显然MapPageRoute更方便、清晰一些
//RouteTable.Routes.Add(“newRoute”,new Route(“TestRouting”,new PageRouteHandler(“~/TestRouting.aspx”)));
RouteTable.Routes.MapPageRoute(“newRoute”
, “RoutingTest”
, “~/RoutingTest.aspx”);

}
3、新建Web窗体,命名为RoutingTest.aspx。在里面随便输入一些内容。
4、启动调试(F5),输入类似的网址:http://localhost:3232/RoutingTest

一切正常的话应该显示出您输入的内容。

二、IDependencyResolver和DependencyResolver

Ioc/DI(Inversion of Control / the Dependency Injection,控制反转/依赖注入)是实现系统解耦的一大利器。.Net平台可用的DI容器有Castle Windsor、StructureMap、Autofac 、Unity等。在MVC2中我们就可以很容易的使用这些容器,MVC3在DI方面又为我们做了什么呢?

需要清楚一点,MVC3对DI的 支持并不是说它内置了类似于Autofac之类的DI容器。它只是内置了一种创建(获取)对象的默认“方式” (DefaultDependencyResolver),这种“方式”内部其中一个途径是通过 Activator.CreateInstance(Type serviceType)来创建对象。更重要的是,它提供了一种API让我们可以改变这种方式。这使得我们可以使用Autofac之类的DI方式来替换。

下面我们从源码角度分析一下MVC3是如何实现这种机制的。

首先看看IDependencyResolver接口,该接口正是上面所说的创建(获取)对象的“方式”。接口有两个方法,GetService根据Type获取一个简单对象,GetServices根据Type获取一个集合对象。
public interface IDependencyResolver
{
object GetService(Type serviceType);
IEnumerable<object> GetServices(Type serviceType);
}
DependencyResolver并不是IDependencyResolver接口的实现。
它有两个私有内联类DefaultDependencyResolver和DelegateBasedDependencyResolver,都是现实的IDependencyResolver接口;
一个DependencyResover型的私有变量_instance;
一个IDependencyResolver型的私有变量_current;
一个静态构造方法,方法内部创建一个DependencyResolver赋给_instance变量;
一个默认构造方法,方法内部创建一个DefaultDependencyResolver赋给_current变量;
两个只读的类型为IDependencyResolver的属性Current和InnerCurrent,这两个属性的get方法最终返回的是_instance变量——典型的单例模式;
三 个InnerSetResolver重载方法和三个SetResolver重载方法。每个SetResolver只是简单的调用对应的 InnerSetResolver方法。这些方法用于设置当前的IDependencyResolver对象,并将对象赋给_current变量。

当我们需要根据某种类型比如SomeClass创建相应的对象时,我们这样调用:DependencyResolver.Current.GetService(typeof(SomeType))。
当然,返回结合对象就这样调用DependencyResolver.Current.GetServices(typeof(SomeType))。
默 认情况下我们使用的是DefaultDependencyResolver对象,在该对象的GetService方法内部,通过调用 Activator.CreateInstance(typeof(SomeType))来创建对象,而GetServices方法返回的是 numerable.Empty<object>()生成的对象。

IDependencyResolver接口是创建(获取)对象的“方式”,而SetResolver方法等则是改变这种方式的API。下面简单分析一下这几个方法。
1、InnerSetResolver(IDependencyResolver resolver)
该方法接受一个IDependencyResolver型参数,方法内部直接将值赋给_current变量。
2、InnerSetResolver(Func<Type, object> getService, Func<Type, IEnumerable<object>> getServices)
该方法接受两个委托,第一个接受一个Type型参数返回object型对象,而第二个返回IEnumerable<object>型集合对象。
方法内部创建一个DelegateBasedDependencyResolver对象。调用DelegateBasedDependencyResolver.GetService(Type type)返回的
是getService(type)的执行结果。相应的,调用GetServices(Type type)返回的是getServices(type)的执行结果。
3、InnerSetResolver(object commonServiceLocator)
该方法接受一个object型参数,方法内部会通过反射的方式尝试获取方法名为”GetInstance”和”GetAllInstances”,参数为Type型的两个方法;
接着检查方法的返回值是否分别是object型和IEnumeralbe<object>型,如果是创建一个DelegateBasedDependencyResolver对象,两个方法作为构造方法
参数传入,并将对象赋给_current变量。返回值的不匹配则抛出异常。

您可能需要CommonServiceLocator的资料:http://commonservicelocator.codeplex.com

另外,DependencyResolverExtensions类是IDependencyResolver接口的扩展方法,分别是相应方法的泛型实现。
public static class DependencyResolverExtensions
{
public static TService GetService<TService>(this IDependencyResolver resolver)
{
return (TService) resolver.GetService(typeof(TService));
}

public static IEnumerable<TService> GetServices<TService>(this IDependencyResolver resolver)
{
return resolver.GetServices(typeof(TService)).Cast<TService>();
}
}

IDependencyResolver接口的实现类中,通常采用外观模式。内部包含一个DI容器,当调用GetService或GetServices方法时,调用DI容器相应的方法。

[转载]编程基本算法(三)

mikel阅读(1123)

[转载]编程基本算法(三) – 清风飘过 – 博客园.

编程基本算法(一)

编程基本算法(二)

编程基本算法(三)

选择排序

使用条件:可对比大小的集合。

算法思想:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。

举例编程:int b[10]={77,1,65,13,81,93,10,5,23,17}

//简单选择排序 void SimpleSelect(int b[10]) { int temp; int i; for(i=0;i<9;i++) { for(int j=i+1;j<9;j++) { if(b[i]>b[j]) { temp=b[i]; b[i]=b[j]; b[j]=temp; } } } cout<<"the sort is:"; for(int i=0;i<10;i++) { cout<<b[i]<<" "; } cout<<endl; }

性能分析:时间复杂度为On^2

堆排序

使用条件:可对比大小的集合。

算法思想:其实堆排序是简单选择排序的一种进化,它最主要是减少比较的次数。什么是堆?若将序列对应看成一个完全二叉树,完全二叉树中所有非终端节点的值均不大于(或者不小于)其左右孩子节点的值,可以称作为堆。由堆的性质可以知道堆顶是一个最大关键字(或者最小关键字)。在输出堆顶后,使剩下的元素又建成一个堆,然后在输出对顶。如此反复执行,便能得到一个有序序列,这个过程成便是堆排序。

堆排序主要分为两个步骤:

1)从无序序列建堆。(2)输出对顶元素,在调成一个新堆。

举例编程:int b[10]={77,1,65,13,81,93,10,5,23,17}

//堆排序 void HeapSort(int b[10]) { void HeapAdjuest(int b[10],int min,int max); void Sawp(int *a,int *b); int i; //因为是完成二叉树,所以从最后一个非叶子节点开始堆转换 for(i=9/2;i>=0;i--) { HeapAdjuest(b,i,9); } //拿出堆顶数据在从新堆排序 for(i=9;i>0;i--) { Sawp(&b[i],&b[0]); HeapAdjuest(b,0,i-1); } } //堆调整(大顶堆) //min 数据需要调整在数组中的开始位置 //max 数据需要调整在数据中的结束位置 void HeapAdjuest(int b[10],int min,int max) { if(max<=min)return ; int temp; temp=b[min]; int j; //延它的孩子节点循环 for(j=2*min;j<=max;j*=2) { //选择它的大孩子 if(j<max&&b[j]<b[j+1]) { j++; } //堆顶小于它的孩子不做处理 if(temp>b[j]) { break; } //将大的数替换成小的数 b[min]=b[j]; min=j; } b[min]=temp; } //交换函数 void Sawp(int *a,int *b) { int temp; temp=*a; *a=*b; *b=temp; }

性能分析:时间复杂度时间复杂度O(nlogn)

归并算法

又称2路归并算法

使用条件:可对比大小的集合。

算法思想:假设初始序列含有n个记录,则可看成n个有序的子序列,每个子序列长度为1,然后两两归并,得到[n/2]个长度为2或者为1(这里长度为1可能这里序列长度是奇数,那么最后一个序列就落单了,所以长度为1);在两两归并,如此重复,直至得到一个长度为n的有序序列为止。

举例编程:int b[10]={77,1,65,13,81,93,10,5,23,17}

//归并排序 void MergeSort(int b[10],int d[10],int min,int max) { //用与存放中间分区域得到的序列 int c[10]; void Merge(int c[10],int d[10],int min,int mid,int max); if(min==max)d[min]=b[min]; else { //平分成两个区域 int mid=(min+max)/2; //将这个区域进行归并排序 MergeSort(b,c,min,mid); //将这个区域进行归并排序 MergeSort(b,c,mid+1,max); //两个区域归并 Merge(c,d,min,mid,max); } } //将有序序列d[min-mid]与d[mid+1-max]归并成有序序列c[min-max] void Merge(int c[10],int d[10],int min,int mid,int max) { int i,j,k; for(i=j=min,k=mid+1;j<=mid&&k<=max;i++) { if(c[j]>c[k]) { d[i]=c[k]; k++; } else { d[i]=c[j]; j++; } } if(j<=mid) { for(;j<=mid;j++,i++) { d[i]=c[j]; } } if(k<=max) { for(;k<=max;k++,i++) { d[i]=c[k]; } } }

性能分析:时间复杂度O(nlogn)

总结

那么这么多排序算法,到底什么时候用什么样的算法呢?

因为不同的排序方法适应不同的应用换进和要求,选择合适的排序方法考虑以下因素:

  • 待排序的记录数n
  • 对其稳定性要求
  • 存储结构
  • 时间和辅助空间复杂度

(1)如果n比较小(例如n<=50),可采用直接插入排序或者简单选择排序。

(2)如果序列初始状态基本有序,则可选用直接插入排序,冒泡排序。

(3)如果n比价大,则可采用时间复杂度为O(nlogn)的算法:快速排序,堆排序,归并排序。

快速排序被认为目前基于比较的内部排序中最好的方法。当带排序的关键字随机分布时,快速排序平均时间最短。 不稳定

堆排序所需要的辅助空间小于快速排序,并且不会出现快速排序可能出现的最坏情况。 但还是比较不稳定

归并排序,比较稳定,但是归并排序一般不提倡使用,实用性很差,占用的辅助空间肯能个比较大。

[转载]C#高效编程话题集2(每期10话题)

mikel阅读(1023)

[转载]C#高效编程话题集2(每期10话题) – 不如来编码-luminji’s web – 博客园.

第一期话题在:C#高效编程话题集1(每期10话题)

C#快速成长团队第二期话题来到。欢迎进入C#快速成长团队进行讨论。

1:确保集合的线程安全

如果使用.net4.0,有新的线程安全集合类
新的 System.Collections.Concurrent 命名空间引入了多个新的线程安全集合类,可在需要时随时提供对项的无锁访问,并在锁适用时提供细粒度锁定。 在多线程方案中使用这些类应获得优于集合类型(例如, ArrayList 和 List <(Of <(T >)>))的性能。

除了System.Collections.Concurrent空间下集合外,非泛型集合使用
lock(非泛型集合对象.SyncRoot)进行锁定达到集合线程安全目的
泛型集合使用
static object sycObj = new object(); //是否static看具体应用
lock (sycObj)
{
//操作集合。
}

2:循环中先求长度还是使用list.Count,哪个效率高

第一类:

int len = list.Count;

for(int i; i<len; i++)

{

迭代

}

第二类:

for(int i; i<list.Count; i++)

{

迭代

}

答案是一样高。

第一种方法完全没有必要,很多人可能以为那样会为代码带来效率,而实际上是不会给效率带来任何提升。
因为事实上,索引器内部,为了安全期间,还是会去求整个list的count的。将两者代码贴出来可能会更好的理解这一点:
public T this[int index]
{
get
{
if (index >= this._size)
{
ThrowHelper.ThrowArgumentOutOfRangeException();
}
return this._items[index];
}
set
{
if (index >= this._size)
{
ThrowHelper.ThrowArgumentOutOfRangeException();
}
this._items[index] = value;
this._version++;
}
}
public int Count
{
get
{
return this._size;
}
}

3:善用延迟求值

以List<int> list = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};为例,说明linq查询中的延迟求值和主动求值。

List<int> list = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var temp1 = from c in list where c > 5 select c;
var temp2 = (from c in list where c > 5 select c).ToList<int>();
list[0] = 11;
Console.Write(“temp1: “);
foreach (var item in temp1)
{
Console.Write(item.ToString() + ” “);
}
Console.Write(“\ntemp2: “);
foreach (var item in temp2)
{
Console.Write(item.ToString() + ” “);
}

4:谨慎泛型类型中的静态成员

static void Main(string[] args)
{
MyList<int> list1 = new MyList<int>();
MyList<int> list2 = new MyList<int>();
MyList<string> list3 = new MyList<string>();
Console.WriteLine(MyList<int>.Count);
Console.WriteLine(MyList<string>.Count);
}
class MyList<T>
{
public static int Count { get; set; }
public MyList()
{
Count++;
}

}

代码输出是莫子?

只要知道 MyList<int> 和 MyList<string> 是两个不同的类型,这题就不难理解了。.NET 中类型参数不同的封闭泛型类型是不同的类型。

5:小心闭包中的陷阱

for (int i = 0; i < 10; i++)
{
Action t = () =>
{
Console.WriteLine(“t1:” + i.ToString());
};
t.BeginInvoke(null, null);
}

以上代码的输出为?

当闭包中引用了外部的局部变量或者方法参数的时候,C#会把该变量编译成一个类的实例字段,顶楼的代码编译后实际上等效于:
TempClass tp = new TempClass();
for (tp.i = 0; tp.i < 10; tp.i++)
{
Action t = tp.TempMethod;
t.BeginInvoke(null, null);
}
TempClass是C#编译器自动生成的类,其定义大概是这样:
class TempClass
{
public int i;
public void TempMethod()
{
Console.Writeline(“t1:” + i.ToString());
}
}
因为只循环10次,几乎一瞬间就完了,因此第一个异步委托还没开始执行 tp.i 就等于10了

6:event关键字的作用

既然使用委托也能实现回调,为什么又需要event关键字。答曰:event 最大的作用就是防止在类的外部触发类的事件。

7:区分IEnumerable<T>和IQueryable<T>

本地数据源用IEnumerable<T>,远程数据源用IQueryable<T>。
针对LinqLINQ TO to OBJECTS,使用Enumerable中的扩展方法对本地集合进行排序、查询等操作,查询参数接受的是Func< >。Func< >叫做谓语表达式,相当于一个委托。针对LinqLINQ TO to SQL则使用Querable中的扩展方法,它接受的参数是Expression< >。Expression< >用于包装Func< >。LinqLINQ TO to SQL引擎最终会将表达式树转化成为相应的SQL语句,然后在数据库中执行。

8:选择正确的集合

查看此文吧:http://www.cnblogs.com/luminji/archive/2011/03/24/1993393.html

9:泛型参数的约束是不是应该叫约定更好

在泛型的使用过程中,常常使用到的一个功能就是为泛型参数设定约束。约束听上去像是限制了泛型参数的使用范围,而实际上,约束本身确实拓展了泛型参数的使用。

一个没有约束的泛型参数,只能具有object的行为和属性,而一个指定约束为Student的泛型参数,却可以使用类型Student的所有公开属性和方法。

所以,俺觉得约束这个词翻译的实在不好,叫约定多好。

10:减少使用自定义委托

FCL中的3个(或者说3系列)委托已经满足了大部分自定义委托的需求,所以基本上不再需要自定义委托了。

它们是:

Action表示接受0个或多个输入参数,执行一段代码,但是没有任何返回值;

Func表示接受0个或多个输入参数,执行一段代码,同时有返回值;

Predicate表示定义一组条件并判断参数是否符合条件;

更多话题,期待下一期。

[转载]使用SQL Server Management Studio 2008 将数据库里的数据导成脚本

mikel阅读(830)

[转载]使用SQL Server Management Studio 2008 将数据库里的数据导成脚本 – 自由、创新、研究、探索 – 博客园.

之前很羡慕MySQL 有这样的工具可以把数据库里的数据导成脚本,SQL Server 2005 的时候大牛Pinal Dave写了个Database Publishing Wizard,具体用法参考他写的文章SQL SERVER – 2005 – Generate Script with Data from Database – Database Publishing WizardSQL Server Management Studio 2008现在已经自带了这样的功能,下面我就来演示下如何使用:

1、打开SQL Server Management Studio 2008 ,连接到你的数据库服务器,展开对象资源管理器到数据库节点

2、选择需要将数据导出到脚本的数据库,我这里选择的是AdventureWorks ,将包含所有的存储过程,表,视图,表里的数据等等。

image

3、右击选中的数据,按照以下路径选择生成脚本向导 :AdventureWorks -〉任务 -〉生成脚本

image

4、当点击生成脚本,弹出一个向导–生成数据库对象脚本:

image

5、下一步到达设置脚本编写选项,进入高级设置对话框,关键是要编写脚本的数据类型这里,默认是仅限架构,选择架构和数据或者是数据都可以吧数据导成脚本:

image

执行完就可以看到如下的结果了

image

[转载]使用SQL Server Management Studio 2008 将数据库里的数据导成脚本

mikel阅读(837)

[转载]使用SQL Server Management Studio 2008 将数据库里的数据导成脚本 – 自由、创新、研究、探索 – 博客园.

之前很羡慕MySQL 有这样的工具可以把数据库里的数据导成脚本,SQL Server 2005 的时候大牛Pinal Dave写了个Database Publishing Wizard,具体用法参考他写的文章SQL SERVER – 2005 – Generate Script with Data from Database – Database Publishing Wizard。SQL Server Management Studio 2008现在已经自带了这样的功能,下面我就来演示下如何使用:

1、打开SQL Server Management Studio 2008 ,连接到你的数据库服务器,展开对象资源管理器到数据库节点

2、选择需要将数据导出到脚本的数据库,我这里选择的是AdventureWorks ,将包含所有的存储过程,表,视图,表里的数据等等。

image

3、右击选中的数据,按照以下路径选择生成脚本向导 :AdventureWorks -〉任务 -〉生成脚本

image

4、当点击生成脚本,弹出一个向导–生成数据库对象脚本:

image

5、下一步到达设置脚本编写选项,进入高级设置对话框,关键是要编写脚本的数据类型这里,默认是仅限架构,选择架构和数据或者是数据都可以吧数据导成脚本:

image

执行完就可以看到如下的结果了

image