新鲜出炉的8月前端面试题

原文链接:https://segmentfault.com/a/1190000015916686

前言

最近参加了几场面试,积累了一些高频面试题,我把面试题分为两类,一种是基础试题: 主要考察前端技基础是否扎实,是否能够将前端知识体系串联。一种是开放式问题: 考察业务积累,是否有自己的思考,思考问题的方式,这类问题没有标准答案。

基础题

题目的答案提供了一个思考的方向,答案不一定正确全面,有错误的地方欢迎大家请在评论中指出,共同进步。

怎么去设计一个组件封装

  1. 组件封装的目的是为了重用,提高开发效率和代码质量
  2. 低耦合,单一职责,可复用性,可维护性
  3. 前端组件化设计思路

js 异步加载的方式

  1. 渲染引擎遇到 script 标签会停下来,等到执行完脚本,继续向下渲染
  2. defer 是“渲染完再执行”,async 是“下载完就执行”,defer 如果有多个脚本,会按照在页面中出现的顺序加载,多个async 脚本不能保证加载顺序
  3. 加载 es6模块的时候设置 type=module,异步加载不会造成阻塞浏览器,页面渲染完再执行,可以同时加上async属性,异步执行脚本(利用顶层的this等于undefined这个语法点,可以侦测当前代码是否在 ES6 模块之中)

css 动画和 js 动画的差异

  1. 代码复杂度,js 动画代码相对复杂一些
  2. 动画运行时,对动画的控制程度上,js 能够让动画,暂停,取消,终止,css动画不能添加事件
  3. 动画性能看,js 动画多了一个js 解析的过程,性能不如 css 动画好

XSS 与 CSRF 两种跨站攻击

  1. xss 跨站脚本攻击,主要是前端层面的,用户在输入层面插入攻击脚本,改变页面的显示,或则窃取网站 cookie,预防方法:不相信用户的所有操作,对用户输入进行一个转义,不允许 js 对 cookie 的读写
  2. csrf 跨站请求伪造,以你的名义,发送恶意请求,通过 cookie 加参数等形式过滤
  3. 我们没法彻底杜绝攻击,只能提高攻击门槛

事件委托,目的,功能,写法

  1. 把一个或者一组元素的事件委托到它的父层或者更外层元素上
  2. 优点,减少内存消耗,动态绑定事件
  3. target 是触发事件的最具体的元素,currenttarget是绑定事件的元素(在函数中一般等于this)
  4. JavaScript 事件委托详解

线程,进程

  1. 线程是最小的执行单元,进程是最小的资源管理单元
  2. 一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程

负载均衡

  1. 当系统面临大量用户访问,负载过高的时候,通常会使用增加服务器数量来进行横向扩展,使用集群和负载均衡提高整个系统的处理能力
  2. 服务器集群负载均衡原理?

什么是CDN缓存

  1. CDN 是一种部署策略,根据不同的地区部署类似nginx 这种服务服务,会缓存静态资源。前端在项目优化的时候,习惯在讲台资源上加上一个 hash 值,每次更新的时候去改变这个 hash,hash 值变化的时候,服务会去重新取资源
  2. (CDN)是一个经策略性部署的整体系统,包括分布式存储、负载均衡、网络请求的重定向和内容管理4个要件
  3. CDN_百度百科

闭包的写法,闭包的作用,闭包的缺点

  1. 使用闭包的目的——隐藏变量,间接访问一个变量,在定义函数的词法作用域外,调用函数
  2. 闭包的内存泄露,是IE的一个 bug,闭包使用完成之后,收回不了闭包的引用,导致内存泄露
  3. 「每日一题」JS 中的闭包是什么?
  4. 闭包造成内存泄露的实验

跨域问题,谁限制的跨域,怎么解决

  1. 浏览器的同源策略导致了跨域
  2. 用于隔离潜在恶意文件的重要安全机制
  3. [jsonp ,允许 script 加载第三方资源]https://segmentfault.com/a/11...
  4. nginx 反向代理(nginx 服务内部配置 Access-Control-Allow-Origin *)
  5. cors 前后端协作设置请求头部,Access-Control-Allow-Origin 等头部信息
  6. iframe 嵌套通讯,postmessage

javascript 中常见的内存泄露陷阱

  1. 内存泄露会导致一系列问题,比如:运行缓慢,崩溃,高延迟
  2. 内存泄露是指你用不到(访问不到)的变量,依然占居着内存空间,不能被再次利用起来
  3. 意外的全局变量,这些都是不会被回收的变量(除非设置 null 或者被重新赋值),特别是那些用来临时存储大量信息的变量
  4. 周期函数一直在运行,处理函数并不会被回收,jq 在移除节点前都会,将事件监听移除
  5. js 代码中有对 DOM 节点的引用,dom 节点被移除的时候,引用还维持
  6. JavaScript 中 4 种常见的内存泄露陷阱

babel把ES6转成ES5或者ES3之类的原理是什么

  1. 它就是个编译器,输入语言是ES6+,编译目标语言是ES5
  2. babel 官方工作原理
  3. 解析:将代码字符串解析成抽象语法树
  4. 变换:对抽象语法树进行变换操作
  5. 再建:根据变换后的抽象语法树再生成代码字符串

Promise 模拟终止

  1. 当新对象保持“pending”状态时,原Promise链将会中止执行。
  2. return new Promise(()=>{}); // 返回“pending”状态的Promise对象
  3. 从如何停掉 Promise 链说起(promise内存泄漏问题)

promise 放在try catch里面有什么结果

  1. Promise 对象的错误具有冒泡性质,会一直向后传递,直到被捕获为止,也即是说,错误总会被下一个catch语句捕获
  2. 当Promise链中抛出一个错误时,错误信息沿着链路向后传递,直至被捕获

网站性能优化

  1. http 请求方面,减少请求数量,请求体积,对应的做法是,对项目资源进行压缩,控制项目资源的 dns 解析在2到4个域名,提取公告的样式,公共的组件,雪碧图,缓存资源,
  2. 压缩资源,提取公共资源压缩,提取 css ,js 公共方法
  3. 不要缩放图片,使用雪碧图,使用字体图表(阿里矢量图库)
  4. 使用 CDN,抛开无用的 cookie
  5. 减少重绘重排,CSS属性读写分离,最好不要用js 修改样式,dom 离线更新,渲染前指定图片的大小
  6. js 代码层面的优化,减少对字符串的计算,合理使用闭包,首屏的js 资源加载放在最底部

js 自定义事件实现

  1. 原生提供了3个方法实现自定义事件
  2. createEvent,设置事件类型,是 html 事件还是 鼠标事件
  3. initEvent 初始化事件,事件名称,是否允许冒泡,是否阻止自定义事件
  4. dispatchEvent 触发事件

angular 双向数据绑定与vue数据的双向数据绑定

  1. 二者都是 MVVM 模式开发的典型代表
  2. angular 是通过脏检测实现,angular 会将 UI 事件,请求事件,settimeout 这类延迟,的对象放入到事件监测的脏队列,当数据变化的时候,触发 $diget 方法进行数据的更新,视图的渲染
  3. vue 通过数据属性的数据劫持和发布订阅的模式实现,大致可以理解成由3个模块组成,observer 完成对数据的劫持,compile 完成对模板片段的渲染,watcher 作为桥梁连接二者,订阅数据变化及更新视图

get与post 通讯的区别

  1. Get 请求能缓存,Post 不能
  2. Post 相对 Get 安全一点点,因为Get 请求都包含在 URL 里,且会被浏览器保存历史纪录,Post 不会,但是在抓包的情况下都是一样的。
  3. Post 可以通过 request body来传输比 Get 更多的数据,Get 没有这个技术
  4. URL有长度限制,会影响 Get 请求,但是这个长度限制是浏览器规定的,不是 RFC 规定的
  5. Post 支持更多的编码类型且不对数据类型限制

有没有去研究webpack的一些原理和机制,怎么实现的

  1. 解析webpack配置参数,合并从shell传入和webpack.config.js文件里配置的参数,生产最后的配置结果。
  2. 注册所有配置的插件,好让插件监听webpack构建生命周期的事件节点,以做出对应的反应。
  3. 从配置的entry入口文件开始解析文件构建AST语法树,找出每个文件所依赖的文件,递归下去。
  4. 在解析文件递归的过程中根据文件类型和loader配置找出合适的loader用来对文件进行转换。
  5. 递归完后得到每个文件的最终结果,根据entry配置生成代码块chunk。
  6. 输出所有chunk到文件系统。

ES6模块与CommonJS模块的差异

  1. CommonJs 模块输出的是一个值的拷贝,ES6模块输出的是一个值的引用
  2. CommonJS 模块是运行时加载,ES6模块是编译时输出接口
  3. ES6输入的模块变量,只是一个符号链接,所以这个变量是只读的,对它进行重新赋值就会报错

模块加载AMD,CMD,CommonJS Modules/2.0 规范

  1. 这些规范的目的都是为了 JavaScript 的模块化开发,特别是在浏览器端的
  2. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行
  3. CMD 推崇依赖就近,AMD 推崇依赖前置

Node 事件循环,js 事件循环差异

  1. Node.js 的事件循环分为6个阶段
  2. 浏览器和Node 环境下,microtask 任务队列的执行时机不同

    • Node.js中,microtask 在事件循环的各个阶段之间执行
    • 浏览器端,microtask 在事件循环的 macrotask 执行完之后执行
  3. 递归的调用process.nextTick()会导致I/O starving,官方推荐使用setImmediate()

浅拷贝和深拷贝的问题

  1. 深拷贝和浅拷贝是只针对Object和Array这样的复杂类型的
  2. 也就是说a和b指向了同一块内存,所以修改其中任意的值,另一个值都会随之变化,这就是浅拷贝
  3. 浅拷贝, ”Object.assign() 方法用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象。它将返回目标对象
  4. 深拷贝,JSON.parse()和JSON.stringify()给了我们一个基本的解决办法。但是函数不能被正确处理

开放性问题

开放性问题主要是考察候选人业务积累,是否有自己的思考,思考问题的方式,没有标准答案。不过有些问题挺刁的,哈哈哈哈,比如:" 你见过的最好的代码是什么? "总之提前准备下没错。
  1. 先自我介绍一下,说一下项目的技术栈,以及项目中遇到的一些问题
  2. 从整体中,看你对项目的认识,框架的认识和自己思考
  3. 项目中有没有遇到什么难点,怎么解决
  4. 如果你在创业公司你怎么从0开始做(选择什么框架,选择什么构建工具)
  5. 说一下你项目中用到的技术栈,以及觉得得意和出色的点,以及让你头疼的点,怎么解决的
  6. 一个业务场景,面对产品不断迭代,以及需求的变动该怎么应对,具体技术方案实现
  7. 你的学习来源是什么
  8. 你觉得哪个框架比较好,好在哪里
  9. 你觉得最难得技术难点是什么
  10. 你见过的最好的代码是什么

😊往期的读书笔记

为了系统的串联前端知识,我平时喜欢用思维导图来记录读书笔记,我在 github 建了仓库放这些思维导图的原件,和读书笔记。如果你也喜欢用思维导图的方式来记录读书笔记,也欢迎和我一同维护这个仓库,欢迎留言或则微信(646321933)与我交流

精读《你不知道的 javascript(上卷)》

精读《你不知道的javascript》中卷

精读《深入浅出Node.js》

javascript 垃圾回收算法

精读《图解HTTP》

思维导图下载地址

展开阅读全文

新人求助,新鲜出炉的异常

11-15

rn17:17:09,447 [http-apr-8080-exec-3] ERROR RequestUtils : Error creating form bean of class cn.itcast.bbs.web.struts.forms.CategoryForm ==> org.apache.struts.util.RequestUtils.createActionForm(RequestUtils.java:304)rnjava.lang.NullPointerExceptionrn at org.apache.struts.config.FormBeanConfig.createActionForm(FormBeanConfig.java:212)rn at org.apache.struts.util.RequestUtils.createActionForm(RequestUtils.java:292)rn at org.apache.struts.util.RequestUtils.createActionForm(RequestUtils.java:191)rn at org.apache.struts.action.RequestProcessor.processActionForm(RequestProcessor.java:331)rn at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:202)rn at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)rn at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)rn at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)rn at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)rn at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)rn at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)rn at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)rn at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)rn at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)rn at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)rn at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)rn at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)rn at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)rn at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)rn at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)rn at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)rn at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2441)rn at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2430)rn at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)rn at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)rn at java.lang.Thread.run(Thread.java:619)rn17:17:09,450 [http-apr-8080-exec-3] ERROR RequestProcessor : No action instance for path /category could be created ==> org.apache.struts.action.RequestProcessor.processActionCreate(RequestProcessor.java:296)rnjava.lang.ClassNotFoundException: cn.itcast.bbs.web.struts.actions.CategoryAction rn at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1718)rn at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1569)rn at org.apache.struts.util.RequestUtils.applicationClass(RequestUtils.java:117)rn at org.apache.struts.util.RequestUtils.applicationInstance(RequestUtils.java:143)rn at org.apache.struts.action.RequestProcessor.processActionCreate(RequestProcessor.java:292)rn at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:230)rn at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)rn at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)rn at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)rn at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)rn at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)rn at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)rn at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)rn at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)rn at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)rn at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)rn at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)rn at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)rn at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)rn at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)rn at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)rn at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)rn at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2441)rn at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2430)rn at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)rn at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)rn at java.lang.Thread.run(Thread.java:619)rnrn[b]struts-config.xml文件[/b]rnrnrnrnrn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rnrnrn[color=#FF0000][b]CategoryForm.java文件[/b][/color]rnpackage cn.itcast.bbs.web.struts.forms;rnrnimport javax.servlet.http.HttpServletRequest;rnrnimport org.apache.struts.action.ActionErrors;rnimport org.apache.struts.action.ActionForm;rnimport org.apache.struts.action.ActionMapping;rnrn@SuppressWarnings("serial")rnpublic class CategoryForm extends ActionForm rn private int id;rn private String name;rn rn public int getId() rn return id;rn rn public void setId(int id) rn this.id = id;rn rn public String getName() rn return name;rn rn public void setName(String name) rn this.name = name;rn rn //完成categoryForm.validate方法rn @Overridern public ActionErrors validate(ActionMapping mapping,rn HttpServletRequest request) rn return super.validate(mapping, request);rn rn rnrnrnrn[color=#FF0000][b]CategoryAction.java文件[/b][/color]rnpackage cn.itcast.bbs.web.struts.actions;rnrnimport java.util.List;rnrnimport javax.servlet.http.HttpServletRequest;rnimport javax.servlet.http.HttpServletResponse;rnrnimport org.apache.struts.action.ActionForm;rnimport org.apache.struts.action.ActionForward;rnimport org.apache.struts.action.ActionMapping;rnimport org.apache.struts.action.ActionMessages;rnimport org.apache.struts.actions.DispatchAction;rnrnimport cn.itcast.bbs.domain.Category;rnimport cn.itcast.bbs.service.CategoryService;rnimport cn.itcast.bbs.web.service.impl.CategoryServiceImpl;rnrnpublic class CategoryAction extends DispatchAction rnrn protected CategoryService categoryService = new CategoryServiceImpl(); rn /**rn * 列表rn */rn @Overridern protected ActionForward unspecified(ActionMapping mapping, ActionForm form,rn HttpServletRequest request, HttpServletResponse response)rn throws Exception rn rn List categories = categoryService.findAll();rn request.setAttribute("categories", categories);rn return mapping.findForward("list");rn rn rn /**rn * 添加页面rn */rn public ActionForward addUI(ActionMapping mapping, ActionForm form,rn HttpServletRequest request, HttpServletResponse response)rn throws Exception rn rn return mapping.findForward("add");rn rn /**rn * 添加rn */rn public ActionForward add(ActionMapping mapping, ActionForm form,rn HttpServletRequest request, HttpServletResponse response)rn throws Exception rn// 校验错误,转发,自己校验formBeanrn ActionMessages errors = form.validate(mapping, request);rn if(errors!=null && errors.size()>0)rn saveErrors(request,errors);rn return addUI(mapping,form,request,response);rn rn rn rn rn //调用业务方法添加Categoryrn return mapping.findForward("showCategories");rn rn /**rn * 修改页面rn */rn public ActionForward editUI(ActionMapping mapping, ActionForm form,rn HttpServletRequest request, HttpServletResponse response)rn throws Exception rn rn return mapping.findForward("edit");rn rn rn /**rn * 修改rn */rn public ActionForward edit(ActionMapping mapping, ActionForm form,rn HttpServletRequest request, HttpServletResponse response)rn throws Exception rn rn return mapping.findForward("showCategories");rn rn /**rn * 删除rn */rn public ActionForward del(ActionMapping mapping, ActionForm form,rn HttpServletRequest request, HttpServletResponse response)rn throws Exception rn rn return mapping.findForward("edit");rn rn rn /**rn * 调整顺序(上下移动)rn */rn public ActionForward changeOrder(ActionMapping mapping, ActionForm form,rn HttpServletRequest request, HttpServletResponse response)rn throws Exception rn rn return mapping.findForward("showCategories");rn rn rnrnrnrnrnrnrn 论坛

链表 新鲜出炉 恳请指正

07-25

rn随着排序的完成,这个丑陋的链表终于基本竣工了,生平第一次rn用c++写了这么长的一个小程序,原本也没打算写,看书的时候,rn一看那链表结构有点麻烦,就跳过去了,前几天逛csdn,看到rn好多高手都说链表是最简单的数据结构,汗颜,我连最基本的rn都跳过去不看!于是决定了解一下链表,就有了这么个东东,rn估计在高手眼里这个小玩意不算啥,但他却是c++初学者两个不rn眠之夜的“杰作”,走过路过的,有闲时的帮我看一下这段程序,rn给我提提意见,也好让我少走点歪路,帮我看看里面有啥错误没,rn有哪些地方是太繁琐,可以写简单点的,那些东西可以合并的,rn哪些地方可以用一种更简便的方法写的,等等等等,之所以这个rn东西会这么长,我想是因为我的c++知识结构决定的,用到的都是rn在结构这章之前的东西,没有什么高级的技巧。但我想知道是否rn能有别的方法,让之更简洁明了。我需要批评、指导意见,但又rn不能太打击我,哈哈~ rnrn完成了这个,终于对链表有个初步的印象了,指针! 完全是指针!rn链表只是指针排列出来的一种形式而已。双向、循环、双向循环链rn表估计是更复杂一点的指针排列组合运用吧。rnrn想问个排序的问题,链表的排序应该怎么排?移动结点做删除、插入rn的动作?开始写排序那段时候,想了一会,只觉得好烦啊,每移动rn一个结点就得做一次删除、插入的动作,没办法,因为正好我链表rn需要排序的是数字,于是我就把他们全取出来组成一个数组,对数组rn先排好序,然后再依次把他们赋给各个结点,这样就逃过了移动结点rn来排序的一关。不知道这种取巧的方法有什么弊端,通常链表排序rn应该是怎么排的? 钱能的书上没讲。:(rnrn还有,我不知道我在摧毁链表那一段的东西是不是有问题,希望高手rn看一下,那样delete有问题么?会遗漏什么么?怎样才算是完全释放?rnrn最后给同样是初学者的朋友一句话:实践! 不仅仅是检验真理的唯一rn标准,也是提高技能的最快途径。rnrn//============================================================rn/*************************************************rnname: mylink.cpprnrn初学c++至结构章节,为熟悉链表的使用特作此程序rnrn知识点:链表的各项操作如增加、插入、删除、查找、排rn 序、输出、摧毁等rnrn by ntem. 07242002rn ***********************************************/rnrn#include rnusing namespace std;rnrnstruct linkrnrn long num;rn link* next; rn;rnrnvoid newLink();rnvoid addNode();rnvoid delNode(link* head);rnvoid insertNode(link* head);rnvoid searchNode(link* head);rnvoid modifyNode(link* head);rnvoid sortLink(link* head);rnvoid menu(int menutype);rnvoid listLink(link* head);rnvoid destroy();rnvoid autoNewLink();rnvoid sortArray(long* array, int size, int mode, int type); rnvoid qsort(long* array, long left, long right);rnrnlong numbers; rnlink* linkNode;rnlink* linkHead;rnlink* linkEnd;rnrnvoid menu(int menutype)rnrn if(menutype == 1) //一级菜单内容rn rn char choice;rn dorn rn cout << "\n\n\n\t\t\t 1. 新建空链表\n"rn << "\t\t\t 2. 新建自动赋值链表\n"rn << "\t\t\t 3. 操作所建链表\n"rn << "\t\t\t 4. 退出\n请选择(1-4): " ;rn cin >> choice;rn switch(choice)rn rn case '1' : newLink(); break;rn case '2' : autoNewLink(); break;rn case '3' : rn rn if (!linkHead) rn rn cout << "\n当前没有链表,请先建立链表" <> subChoice;rn switch(subChoice)rn rn case '1' : addNode(); break;rn case '2' : insertNode(linkHead); break;rn case '3' : delNode(linkHead); break;rn case '4' : searchNode(linkHead); break;rn case '5' : modifyNode(linkHead); break;rn case '6' : sortLink(linkHead);; break;rn case '7' : listLink(linkHead); break;rn case '8' : destroy();break;rn case '9' : return;rn rn while(1);rn rnrnrn//新建空链表rnvoid newLink()rnrn if(linkHead)rn rn cout << "\n已经存在一条链表,请删除后再建";rn return;rn rn if((linkNode = new link) == NULL) rn rn cout << "\n无法分配内存,空链表建立失败";rn return;rn rn linkHead = linkEnd = linkNode;rn linkHead->next = NULL;rn cout << "\n一条空链表建立成功,自动进入链表操作菜单" <> autoNum;rn if(autoNum >0 && autoNum <=1000) break;rn elsern if(autoNum == 0) return;rn else cout << "\n输入错误,请重新输入: ";rn while(1);rnrn if((linkNode = new link) == NULL) rn rn cout << "\n无法分配内存,空链表建立失败";rn return;rn rn linkHead = linkEnd = linkNode;rn for(int k=1; k<=autoNum; k++)rn rn linkNode->num = k;rn linkEnd->next = linkNode;rn linkEnd = linkNode;rn numbers++;rn if((linkNode = new link) == NULL) rn rn cout << "\n无法分配内存,无法继续创建链表,已有链表结点个数为:" << numbers <next = NULL;rn return;rn rn rn linkEnd->next = NULL; rn cout << "\n自动赋值链表建立成功,进入链表操作菜单:" <> linkNode->num;rn while(linkNode->num)rn rn if(linkHead == NULL)rn linkHead = linkNode;rn elsern linkEnd->next = linkNode;rn rn linkEnd = linkNode;rn numbers++;rn if((linkNode = new link) == NULL) rn rn cout << "\n无法分配内存,无法继续创建链表,已有链表结点个数为:" << numbers <next = NULL;rn return;rn rn cout << "继续输入(0为结束输入): ";rn cin >> linkNode->num ;rn rn linkEnd->next = NULL;rn//增加结点rnrn//删除结点rnvoid delNode(link* head)rnrn if(numbers == 0) cout << "\n链表为空" <> delLoc;rn if((delLoc > 0) && (delLoc <= numbers))rn rn link* tmp;rn for(int j=1; ;j++)rn rn tmp = head;rn if(j == (delLoc-1) || j == delLoc)rn rn link* toDel;rn if(j == delLoc) //如果要删除的结点是第一个rn toDel = head;rn elsern toDel = head->next ; rnrn if (toDel->next == NULL) //如果要删除的结点是最后一个rn rn linkEnd = tmp;rn linkEnd->next = NULL;rn rn if(j == delLoc) linkHead = toDel->next ; //如果要删除的结点是第一个rn elsern tmp->next = toDel->next ;rn cout << "删除第 " << delLoc << " 个结点: " << toDel->num <next ;rn rn rn else rn cout << "\n找不到你所要求的结点" < 论坛

没有更多推荐了,返回首页