Cookie 会话身份验证是如何工作的?

在 Web 应用程序中,Cookie-Session 是一种标准的身份验证方法。饼干,也被称为“sweet cookies”。类型为“小文本文件”,是指一些网站为了识别用户身份而存储在客户端的数据。Session的主要功能是通过服务器记录用户的状态。

在典型的在线购物场景中,用户浏览多个页面并将一些商品添加到购物车。尽管如此,系统并不知道是哪个用户进行了操作,因为HTTP协议是无状态的,所以服务端需要为不同的用户创建相应的Session来识别和跟踪这个用户。在服务器端保存Session的方式有很多种,比如保存到内存、数据库或者文件中。

我们看一下Cookie-Session的认证过程:

这是一个典型的 HTTP 客户端(浏览器)和 HTTP 服务器对话,服务器运行在同一台计算机(本地主机)上,包含以下步骤。

  1. 用户访问登录页面后,输入相应的用户名和密码进行登录操作。
  2. 在客户端发起登录请求。一般在浏览器环境下,可以通过AJAX或者Form发起登录请求。
  3. 当服务器通过认证时,将为认证成功的用户创建一个Session,并存储Session信息。之后服务器会通过HTTP响应头来设置SessionId,即HTTP响应头中会包含 的响应头信息Set-Cookie。如果认证失败,则提示用户进行相关操作。
  4. 认证成功后,用户访问页面获取用户信息,此时客户端会在HTTP请求头中携带cookie信息。
  5. 服务端接收到客户端发起的请求,获取cookie中存储的SessionId来验证用户身份,验证通过后返回相应信息。

下面我将使用Koa来介绍Cookie-Session的认证过程。首先我们来定义首页的路由:

// router.js
路由器。get ( "/" , async (     ctx ) => {
 if (ctx.session.user ) { const { userName } = ctx.session.user ; ctx.body = ` < h1 > Cookie         /Session Authentication</h1>       你好, ${userName}         <div>           <a href="./getUserInfo">用户信息</a>           <a href="./logout">注销</a>         </div>         ` ;   } else {     ctx.
   









“登录”);
}
});

在上面的代码中,我们首先会判断当前用户是否已经登录到web应用中。如果已登录,将显示与当前用户对应的问候消息。如果没有登录,会跳转到登录页面,所以我们需要注册登录页面的路由:

// router.js
路由器。get ( "/login" , ( ctx     ) => {
 if (ctx.session.user ) { ctx.redirect ( " /" );   } else { ctx.body     = ` <form method = "     post" action="/ login">       <p><label>用户名</label><input type="text" name="username" /></p>       <p><label>密码</label><input type="password" name="密码" /></p>       <button type="

当未登录的用户在浏览器中访问 http://localhost:3000/login地址时,会显示如下用户登录表单:

当用户输入用户名和密码并点击登录按钮时,浏览器会发起POST请求并调用/loginAPI。对应的/login路由处理逻辑如下:

// router.js
路由器。post ( "/login" , async (ctx) => {
 try {
   const loginData = ctx.request . body ; const
  { username, password } = loginData;
   if (username === "bytefer" && password === "123 " ) {
     ctx. session . user = { userName : "bytefer" , userId : "007" };
     ctx. response . redirect ( "/"
  }否则{
     ctx。body = {代码:0,消息:“登录失败!” };
  }
} catch (err) {
   throw  new  Error ( "登录错误" );
}
});

在上面的代码中,我们使用ctx.request.body获取用户输入的用户名和密码,然后判断输入的用户名和密码是否完全匹配。当然,在真实的web项目中,通常会判断输入的信息与数据库user表中的信息一致。此外,为确保系统的安全,用户的密码将被加密或散列。如果输入的用户信息完全匹配,我们将当前登录的用户信息设置到该ctx.session.user属性并重定向到首页。并且如果用户信息不匹配,页面上会显示相应的错误信息。

我们看一下登录成功后服务器返回的HTTP响应报文:

从上图可以看出,登录成功后,服务器返回的HTTP响应报文中会包含Set-Cookie响应头。之后我们打开Chrome开发者工具的Application Tab页面,可以看到已经设置好的Cookie信息:

对于大部分的Web应用,一般都会提供一个用户信息页面,让用户可以查看当前已经登录成功的用户信息。这里我们也注册了一个/getUserInfo路由,用于显示已登录的用户信息:

// router.js
路由器。get ( "/getUserInfo" , async (     ctx ) => {
 if ( ctx.session.user ) { const { userName, userId } = ctx.session.user ; ctx.body = ` < div         > UserName           : ${userName} , UserId: ${userId}         </div>       ` ;   } else {     ctx.body = { code : 0 , message :
   






“您还没有登录。” };
}
});

用户登录成功后,访问web应用中的其他路由时,会发起相应的HTTP请求,请求头中会自动携带当前用户的Cookie信息,如下图:

除了上述功能,我们还需要注册一个路由来处理用户注销操作:

// router.js
路由器。get ( "/logout" , async (   ctx ) => {
 ctx.session = null ; ctx.body = ` < h1   >成功注销</h1>   <a href="./login">登录</a>   ` ; });

同样我们看一下注销成功后服务器返回的HTTP响应报文:

已经描述了包含在 Web 应用程序中的路由。为了应用能够正常运行,我们还需要创建一个Koa应用,并配置koa-session、koa-bodyparser等中间件。具体代码如下:

// app.js
const  Koa = require ( "koa" );
const app = new  Koa ();
const session = require ( "koa-session" );
const bodyParser = require ( "koa-bodyparser" );

常量端口 = 3000 ;
const router = require ( "./router.js" );

const  CONFIG = {
 key : "sid" ,
 maxAge : 86400000 ,
 httpOnly: true ,
 signed : true ,
 rolling : false ,
 renew : false ,
 sameSite : null ,
};
应用程序。键= [ “bytefer” ];
应用程序。use ( async  function ( ctx, next     ) { try
{ await
   next ( );
} catch (err) {
   ctx.status = err.status || 500 ; ctx.type
= "html" ;
   CTX。body = "<p>系统错误</p>" ;
   CTX。应用程序。发出(“错误”,错误,ctx);
}
});
应用程序。使用(会话(配置,应用程序));
应用程序。使用( bodyParser ());
应用程序。使用(路由器。路由())。使用(路由器。allowedMethods());

应用程序。on ( "error" , ( err, ctx ) => {
 控制台. 日志(错误);
});

应用程序。listen (port, function ( ) {
 console . log ( `服务器运行在 http://localhost: ${port} ` );
});

Cookie-Session的认证过程已经介绍过了,最后总结一下这种认证方式存在的一些问题。

饼干的缺陷

  • 每次HTTP请求都会添加Cookies,无形中增加了流量。
  • 安全性差,攻击者可以利用本地 cookie 进行欺骗和 CSRF 攻击。
  • Cookie 大小限制在 4KB 左右,不足以满足复杂的存储要求。

会话缺陷

  • session保存在服务器端,如果短时间内有大量用户,会影响服务器的性能。
  • 可扩展性不好。当有多台服务器时,如何共享Session就会成为一个问题。也就是说当用户第一次访问服务器A,第二次请求转发给服务器B时,服务器B无从知晓其状态。

那么如何解决以上问题呢?解决方案之一是使用基于令牌的身份验证。在下一篇文章中,我将介绍JWT认证方式。有兴趣记得关注我哦。

如果需要更加全面的学好前端,也可以来参与我们的三十天学习计划,全程不涉及任何费用!这是一套免费的三十天挑战计划的课程体系,包含了html+css+云端部署的课程体系,可以通过钉钉群里学习,有问题在群里可以提问,同时每节课还安排有作业,配套有阶段项目练习和综合项目实战,目的是帮助大家夯实前端基础,轻松入门到前端行业

为帮助到一部分同学不走弯路,真正达到一线互联网大厂前端项目研发要求,首次实力宠粉,打造了《30天挑战学习计划》,内容如下:

HTML/HTML5,CSS/CSS3,JavaScript,真实企业项目开发,云服务器部署上线,从入门到精通

  • PC端项目开发(1个)
  • 移动WebApp开发(2个)
  • 多端响应式开发(1个)

共4大完整的项目开发 !一行一行代码带领实践开发,实际企业开发怎么做我们就是怎么做。从学习一开始就进入工作状态,省得浪费时间。

从学习一开始就同步使用 Git 进行项目代码的版本的管理,Markdown 记录学习笔记,包括真实大厂项目的开发标准和设计规范,命名规范,项目代码规范,SEO优化规范

从蓝湖UI设计稿 到 PC端,移动端,多端响应式开发项目开发

  • 真机调试,云服务部署上线;
  • Linux环境下 的 Nginx 部署,Nginx 性能优化;
  • Gzip 压缩,HTTPS 加密协议,域名服务器备案,解析;
  • 企业项目域名跳转的终极解决方案,多网站、多系统部署;
  • 使用 使用 Git 在线项目部署;

这些内容在《30天挑战学习计划》中每一个细节都有讲到,包含视频+图文教程+项目资料素材等。只为实力宠粉,真正一次掌握企业项目开发必备技能,不走弯路 !

过程中【不涉及】任何费用和利益,非诚勿扰 。

如果你没有添加助理老师微信,可以添加下方微信,说明要参加30天挑战学习计划,来自公众号!老师会邀请你进入学习,并给你发放相关资料。

30 天挑战学习计划 Web 前端从入门到实战 | arry老师的博客-艾编程

本文转载于网络 如有侵权请联系删除

相关文章

  • 前端必备技能之如何制作精灵图「建议收藏」

    大家好,又见面了,我是你们的朋友全栈君。为什么要用精灵图?比如京东首页的这些icon,如果每个icon都去请求一个资源。是非常浪费资源的。因为我们浏览器在同一个域名下并发加载的资源(CSS、JS、图片等)数量是有限的。我们可以将这些icon放到一张图片,通过截取这张图片的不同的区域,拿到不同的icon 制作一个背景透明的Icon截图你喜欢的logo,最好是正方形。 打开ps,使用快速选择工具 选择白色区域ctrl+x删除。调节这个可以改变选择精度。 这样就OK了。 img标签引用。设置width,height改变大小,不然图片可能会变形<imgsrc="@/../public/img/home.png"style="width:30px;height:30px"/>复制制作精灵图非常好用的精灵图制作网站自动生成css:https://sprite.ydr.me/图片大小修改:https://www.sojson.com/image/change.html发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn

  • 【随笔】一些可用的 Google 搜索镜像站

    我在日常工作或生活中,几乎时时刻刻都用到Google搜索引擎,但因为“众所周知的原因”在国内无法直接访问。幸好,网上有热心人士搭建了Google镜像站,现分享给大家!温馨提醒:如果出现访问缓慢或无法打开等情况,请换个网址尝试;请勿在镜像站上登录Google账号或者搜索个人隐私,否则可能会被泄露给第三方;请勿搜索含有政治、色情、敏感、暴力血腥、恐怖、其他国家法律法规禁止的词汇,以及浏览违法内容。香港区域:https://g.xzx725.top/http://d.6wl.cc/https://g.qwq.fan/https://shitu.paodekuaiweixinqun.com/webhp/https://gogogle.cf/https://s.isway.cn/https://go.lizmt.cn/https://google.justscience.cn/日本区域:https://www.谷歌.cf/https://www.googlejxz.ml/https://so.ylyn.cc/韩国区域:https://ge1.azurewebsites.net/备用区域:http

  • 当数据库遇见AI,听大咖讲背后的故事

    2022世界人工智能大会(WAIC)来啦!9月1日--9月3日,全球人工智能领域最具影响力的行业盛会WAIC将在上海隆重开幕。WAIC2022将继续秉持“智联世界”理念,发挥“科技风向标、应用展示台、产业加速器、治理议事厅”的重要作用,将通过线上线下联动的会展形式,汇聚顶级科学家、企业家、政府官员、专家学者、国际组织、投资人、创新团队一同探讨前沿话题。腾讯云数据库技术负责人程彬受邀参加WAIC大会滴水湖AI开发者创新论坛:当数据库遇上AI专场。9月3日13:30,程彬将基于腾讯云数据库在AI智能化的探索与实践,分享数据库与AI融合背后的技术关键点,为产业界提供前沿解决方案。腾讯云数据库视频号全程同步直播,一键预约直播吧!嘉宾简介程彬,腾讯云数据库技术负责人,数据库和存储领域资深技术专家,专注于数据库的架构创新、企业级能力构建、云原生能力演进以及大规模系统自治。内容简介数字化时代,随着数字化转型的深入,业务应用、开发范式出现了全新的变化。传统的运营服务模式,给云厂商和企业在可用性、成本、运营效等方面带来新挑战。数据库构建的方法论需要进一步升级,从传统软硬结合,升级到软件+硬件+AI三位一

  • 微软又考了这道题

    大家好,我是吴师兄。今天分享的题目是LeetCode72.编辑距离。我发现这道题目外企非常喜欢考,亚马逊和微软考察的频率非常高。来看这道题目的描述:给你两个单词word1和word2,请你计算出将word1转换成word2所使用的最少操作数。你可以对一个单词进行如下三种操作:1、插入一个字符2、删除一个字符3、替换一个字符比如word1单词是horse,而word2单词是ros。那么word1可以通过如下的转换变为word2:先把horse开头的h替换为r,成为一个新的单词rorse,接着把第二个r删除,变成了rose,最后再删除e就转换为目标单词ros。解题思路就是利用动态规划,找出状态转移方程。图片来源于算法训练营课件具体可以这样分析。我们想知道从word1[0..i]到word2[0..j]的变换需要几步,而从word1[0..i]到word2[0..j]可以通过以下三种情况变化而来。1、先从word1[0..i-1]转换为word2[0..j-1],假设这个过程需要k步,转换完毕之后,再执行替换操作,将word1[i]改成word2[j],如果出现特殊情况word1[i]恰巧等

  • SpringCloud Alibaba Nacos服务注册和配置中心

    Nacos什么是nacosnacos(Nacos:DynamicNamingandConfigurationService)一个更易于构建云原生应用的动态服务发 现,配置管理和服务管理中心Nacos就是注册中心+配置中心的组合等价于netflix版本的Eureka+Config+Bus+zik解决了什么痛点之前我们在netflix版本遇到的配置需要手动的区分发信息,杜绝了我们需要专门自己建一个注册中心的包,阿里给我们提供了开箱即用的发行版本,我们只需要简单的配置,直接脚本启动可以直接查看到集群信息,和调用链路如何获得和社区文档下载地址:https://github.com/alibaba/Nacos中文文档地址 :https://nacos.io/zh-cn/index.html官方文档地址 :https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_nacos_discovery主流注册中心对比安装nacos环境

  • Java-单机版的书店管理系统(练习设计模块和思想_系列 八 )

    本系列前面博客的链接:Java-单机版的书店管理系统(练习设计模块和思想_系列七) http://blog.csdn.net/qq_26525215/article/details/51190696Java-单机版的书店管理系统(练习设计模块和思想_系列六) http://blog.csdn.net/qq_26525215/article/details/51169277Java-单机版的书店管理系统(练习设计模块和思想_系列五) http://blog.csdn.net/qq_26525215/article/details/51136848Java-单机版的书店管理系统(练习设计模块和思想_系列四(2)): http://blog.csdn.net/qq_26525215/article/details/51117135Java-单机版的书店管理系统(练习设计模块和思想_系列四(1)): http://blog.csdn.net/qq_26525215/article/details/51116429Java-单机版的书店管理系统(练习设计模块和思想_系列三): http://bl

  • 2020年最后一个技术问题:Jetson Xavier NX开发板为什么进不去用户界面?

    12月31日,在这个慵懒的下午,原以为2020年最后一天的工作可以愉快地收尾,没想到下午3点半收到客户的求救信息: 客人的JetsonXavierNX开发套件——也就是用户使用一张有效的TF系统卡,并不能够启动系统,直接掉进RAMDisk里的bash中.而并不能进一步的mountroot和后续启动过程.我们工程师很敏锐地判断可能性:存储卡的设备名称发生了改变:从/dev/mmcblk0变成了/dev/mmcblk1,从而让原本应该从/dev/mmcblk0上挂载的根文件系统操作失败。为了确认这一点,工程师让用户立刻使用如下指令查看是否跟我们预期符合:ls-l/dev/mmc*复制客户很配合,立刻发来图片: 果然跟我们预期的一样,工程师判断客户应该做了以下三点之一,导致发生这个情况: (1)改变了EEPROM,(2)改变了启动电阻(3)准备加焊EMMC芯片,从而脱离存储卡启动,于是我们问客户—— 于是我们询问客户:(1)是否使用外置编程器进行的修改?(2)修改前有无备份原始内容?客户表示——我们让客户尝试:(1)将一个好的卡的kernel参数配置文件,改成mmcblk1p1,保存.卸载该

  • OnlineJudge难度与正确度的相关

      本着做题的心态,上了东莞理工学院的oj 网;在选择难度的时候发现有些题目通过率和难度可能存在着某些关系,于是决定爬下这些数据简单查看一下是否存在关系。一、新建项目  我是用 Scrapy 框架爬取的(因为刚学没多久,顺便练练手)。首先,先新建 project(下载Scarpy部分已省略),在控制台输入 scrapy startproject onlineJudge(其中, onlineJudge为项目名称),敲击回车键新建项目完成。二、明确目的  在动手写代码之前,先分析一下网页结构。网站是通过动态加载的,数据通过json 文件加载。  1、明确要爬取的目标:http://oj.dgut.edu.cn/problems 网站里的题目,难度,提交量,通过率。在查找 json的时候发现只有通过数,那么通过率就要自己计算。  2、打开onlineJudge目录下的items.py 写下如下代码:classOnlinejudgeItem(scrapy.Item): id=scrapy.Field()#题目编号 title=scrapy.Field()#标题 difficulty=scra

  • Linux CentOS6编译安装Pyt

        CentOS6.x系统中一直沿用的都是Python2.6.x(目前最新版本是python-2.6.6),有时不能满足某些应用生产环境和开发环境的需要,直接从yum官方仓库和epel中安装Python2.7(目前最新版本是python-2.7.12)似乎也是没有什么可能,除非使用更三方的软件源。CentOS6.x系统中有很多系统组件是使用Python2.6的,比如刚才提到的yum,但yum不一定是唯一依赖Python2.6的程序,尽管一般的生产环境中不会使用到特别混杂的运行环境,但在使用的过程中需要留意某些工具&程序是否能在Python2.7下正常运行。    安装Python2.7.x实际上非常简单,唯一需要了解的是,编译安装Python2.7.x时必须将使用--enable-shared(enablebuildingsharedpythonlibrary)选项用来安装python动态链接库(shareobject,/usr/lib64/libpython2.7.so.1.0),这一文件会被很多python模块(甚至python本身)所用到,当没有使用这一选项时可以加上

  • 「docker实战篇」python的docker爬虫技术-fiddler之安卓模拟器如何抓包(九)

    上次说了web端通过fiddler的抓包,本次说下如何通过fiddler抓取app端。查看本机IP现在都是wifi上网,直接点击wifi图标右键更改网络属性笔记本的ip192.168.100.143记录下夜神模拟器启动夜神模拟机,点击右上角齿轮 属性设置,点击安装点击保存重启模拟器WLAN设置长按WiredSSID手机浏览器访问:baidu.com,弹出证书。先点继续看能否拦截fiddler的配置夜神模拟器内的浏览器输入fiddler的IP地址:192.168.100.143:8888点击安装证书密码输入4位就可以了夜神模拟器:打开浏览器搜索关键字查看PS:fiddler完成对app夜神浏览器的监控完成。其实不复杂。没搞过的可能感觉比较麻烦。

  • 第82天:jQuery中prop()和attr()的区别

    在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别?这些问题就出现了。关于它们两个的区别,网上的答案很多。这里谈谈我的心得,我的心得很简单:对于HTML元素本身就带有的固有属性,在处理时,使用prop方法。对于HTML元素我们自己自定义的DOM属性,在处理时,使用attr方法。上面的描述也许有点模糊,举几个例子就知道了。 <ahref="http://www.baidu.com"target="_self"class="btn">百度</a>复制 这个例子里<a>元素的DOM属性有“href、target和class",这些属性就是<a>元素本身就带有的属性,也是W3C标准里就包含有这几个属性,或者说在IDE里能够智能提示出的属性,这些就叫做固有属性。处理这些属性时,建议使用prop方法。<ahref="#"id="link1"action="delete&q

  • 科学家发现部分人口臭是因为基因突变,可以被遗传且无法治愈 | 黑科技

    研究人员猜测因为基因突变,口臭和癌症可能有关联。口臭是非常恼人的,究其产生原因,有90%是由于吃的大蒜、洋葱等食物导致的,通常刷牙或者用漱口水就可以去除气味;还有10%是由于鼻窦、扁桃体、食道和血液等身体原因导致的,想要根治的话,需要花心思调节身体。而最近,《Nature》杂志上发表了一项关于口臭产生原因的研究:口臭有可能是由基因突变引起的,并且这是可以遗传的,且是永久性的。据格罗宁根大学的EdwinWinkel所述,这项研究起源于25年前,一位荷兰女子来到Winkel牙科诊所,该女子告诉医生她哥哥也有同样的口臭问题。于是Winkel从患者身上获取体液样本,并将其送到RadboudUniversityNijmegen医学中心进行分析。该医学中心的研究人员在样品中发现含有4种含硫代谢物的异常高浓度,其中四种的两种是挥发性化合物二甲基硫醚和甲硫醇,这两种物质源自于食物,并可以在肠中大量生产。所以研究人员就指出,应该就是这两种物质之一导致患者口中的气味不好。对此,合作研究者HuubOpdenCamp解释道:“甲硫醇这种物质的气味就是一种腐臭气味,而二甲硫的味道就像煮卷心菜时释放的气味。”于是

  • python: sort, sorted, reverse

    python语言中的列表排序方法有三个:reverse反转/倒序排序、sort正序排序、sorted可以获取排序后的列表。在更高级列表排序中,后两中方法还可以加入条件参数进行排序。reverse()方法将列表中元素反转排序,比如下面这样>>>x=[1,5,2,3,4]>>>x.reverse()>>>x[4,3,2,5,1]reverse列表反转排序:是把原列表中的元素顺序从左至右的重新存放,而不会对列表中的参数进行排序整理。如果需要对列表中的参数进行整理,就需要用到列表的另一种排序方式sort正序排序。sort()排序方法此函数方法对列表内容进行正向排序,排序后的新列表会覆盖原列表(id不变),也就是sort排序方法是直接修改原列表list排序方法。>>>a=[5,7,6,3,4,1,2]>>>a.sort()>>>a[1,2,3,4,5,6,7]许多python初学者,对sort()方法比较糊涂。有的时候会需要一个排序好的列表,而又想保存原有未排序列表,他们会这么操作:>

  • 【Go 语言 redis内存数据库存储 demo】

    packagemain import( "fmt" "github.com.Go-Redis/github.com/alphazero/Go-Redis" "log" "strconv" ) const( a=iota b=iota c1 ) funcmain(){ //varbstring //b="fdsafds" c:="fdsa" a:=15 c=strconv.Itoa(a) fmt.Println(c) fmt.Println(c1) spec:=redis.DefaultSpec().Host("192.168.1.12").Port(6379) client,e:=redis.NewSynchClientWithSpec(spec) //是否连接出错 ife!=nil{ log.Println("erroronconnectredisserver") return } fmt.Println("endr

  • Hibernate(或其它ORM)里的inverse用法详解,内容摘自Java web轻量级开发面试教程

      本文来是从 javaweb轻量级开发面试教程从摘录的。  Inverse的英文含义是反转,在Hibernate中用来决定是由哪方来维护两个业务实体类之间的关联关系,具体而言,就是由哪方去设置这个被外键约束的字段值。  它的默认值是false,也就是说,本端(比如inverse=false写在学生端,那么本端是学生,另外一方是课程)不“反转控制权”,这句别扭的话的另外一种说法是,本端维护关联关系。如果两边都不写,那么两端都维护。这样会造成问题,即新时因为两端都控制关系,因此可能会导致重复更新。  注意,inverse仅仅是指定由谁来设置外键值,而不是用来设置级联操作,级联操作的方式由cascade来负责,很多人会混淆它们的含义和用法。  这个例子所用到的数据表是Person表和Card表,其中Person表里包含ID、Name和Phone字段,而Card表里包含了CardID、PersonID、Bank和balance四个字段。    在hibernate.cfg.xml文件里,通过mappingresource来指定对应的映射文件,其中关键的代码如下:  1 <!--添加实体

  • 算法与数据结构(十六) 快速排序(Swift 3.0版)

     上篇博客我们主要聊了比较高效的归并排序算法,本篇博客我们就来介绍另一种高效的排序算法:快速排序。快速排序的思想与归并排序类似,都是采用分而治之的方式进行排序的。快速排序的思想主要是取出无序序列中第一个值,然后通过比较将比该值小的元素放到该值的前方,将比该值大的元素放在该值的后方。这样一来该值前方的数据都要比该值小,该值后方的数据都要比该值大。然后再次对前半部分和后边半部分无序的数列进行上述操作,这样不断的操作,无序的序列的规模不断被缩小。等问题的规模被缩小到一定程度后,我们的序列就变的有序了。 之前我们说过,当一个问题可以被分成一些相同的子问题时,我们就可以使用递归来操作。所以在快速排序的过程中,我们是通过递归的方式将问题规模逐渐减小,知道序列为序为止。本篇博客将会给出这一过程,根据示意图,给出相应的代码实现。   一、将无序数组进行拆分 在本篇博客,我们先聊一聊如果将大的问题拆分成一些相同的子问题。我们需要对需要排序的数组进行拆分,从无序序列中取出一个值,然后通过比较,将比该值大的放在该值的后方,比该值小的,放在该值的前方。本部分,我们将给出相应的示意图以及代码

  • HDU 4762 Cut the Cake(公式)

    CuttheCake TimeLimit:2000/1000MS(Java/Others)    MemoryLimit:32768/32768K(Java/Others)TotalSubmission(s):263    AcceptedSubmission(s):113 ProblemDescription MMMgotabigbigbigcake,andinvitedallherMfriendstoeatthecaketogether.SurprisinglyoneofherfriendsHZtooksome(N)strawberrieswhichMMMlikesverymuchtodecoratethecake(ofcoursetheyalsoeatstrawberries,notjustfordecoration).HZisinchargeofthedecoration,andhethinksthatit'snotabigdealthatheputthestrawberriesonthecaker

  • python3在同一行内输入若干个数

    相信很多人都会使用 a=input() b=input() 复制 来进行输入操作, 但是,这是以换行进行操作的,而有些题目是需要进行一行输入,空格隔开的,这时候就需要变换输入方式了。 那么怎么办呢? 我们可以这样写 a,b=map(int,input().split()) 复制 这样就实现了一行输入,空格隔开的结果了。 如果有多个变量只需继续加就行了,如 a,b,c=map(int,input().split()) 复制 如果想以逗号隔开,只需 a,b,c=map(int,input().split(',')) 复制 python3在同一行内输入n个数并用列表保存,用空格分开 List=list(map(int,input().split())) 复制

  • 工控随笔_09_西门子_S7-200 Smart与V20 USS通信USS_RPM_R利用轮询的方式通讯异常

      前两天处理过一个故障,是S7-200 Smart与V20的USS通讯,设备厂家在程序里面利 用USS_RPM_R程序循环轮询5个V20设备读取频率和电流值等信息。        图 USS_RPM_R读取信息   上图是第一个站点的读取,其采用的控制方式是利用状态位SM0.0 置位M13.0=1, 然后 通过上面的程序段进行读取参数,然后再利用M13.1这个标志位,再做为下一个站点的XMT和 EN信号,同时复位M13.0=0;依次类推一直轮询完5个站点后,再重新设置M13.0=1 开始新 一轮的查询。   一、问题   那天我的同事要修改程序里面一个模拟量的量程,然后修改完后直接下载程序,在下载完毕后 重新运行程序,PLC有Stop状态切换至RUN状态,这个时候出现了一个问题,那就是USS_RPM_R 这个程序块卡主了,整个轮询不再执行。   二、分析   同事搞了很久,没有找出原因,还和其他人一起把V20的参数恢复出厂设置了,但是还是不 行, 后来就给我打电话,让我过去看看。   我一过去看就问是不是

  • 会议2.9

      任务看板: 燃尽图:  

  • Comet OJ - Contest #10 C题 鱼跃龙门

    ###题目链接###   题目大意: 给你一个n,让你求出最小的正整数x使得x*(x+1)/2 %n==0,即x*(x+1) %2n==0。   分析: 1、由于x*(x+1) 为2n的倍数,故分离出它们各自的某个因数使得 k1* k2 ==2n。 则令 k2* b=x+1,k1* a=x。则有:     2、显然上述 一式 为不定方程,倘若先将负号放到 a 里面,则系数分别为 k2 与k1,有解 b 与 a 当且仅当 gcd(k2,k1)|1,故 k2 与 k1 必须互质。 3、故结合二式,求得 k1 与 k2 互斥时的解即可。很直接的做法是 枚举根号2n 中的 k1 与  k2 ,判断是

相关推荐

推荐阅读