伪代码及其实例讲解

伪代码(Pseudocode)是一种算法描述语言。使用伪代码的目的是为了使被描述的算法可以容易地以任何一种编程语言(Pascal,C,Java,etc)实现。因此,伪代码必须结构清晰、代码简单、可读性好,并且类似自然语言。 介于自然语言与编程语言之间。

  它以编程语言的书写形式指明算法的职能。相比于程序语言(例如Java, C++,C, Dephi 等等)它更类似自然语言。它是半角式化、不标准的语言。我们可以将整个算法运行过程的结构用接近自然语言的形式(这里,你可以使用任何一种你熟悉的文字,中文,英文 等等,关键是你把你程序的意思表达出来)描述出来. 使用伪代码, 可以帮助我们更好的表述算法, 不用拘泥于具体的实现.

  人们在用不同的编程语言实现同一个算法时意识到,他们的实现(注意:这里是实现,不是功能)很不同。尤其是对于那些熟练于不同编程语言的程序员要理解一个(用其他编程语言编写的程序的)功能时可能很难,因为程序语言的形式限制了程序员对程序关键部分的理解。这样伪代码就应运而生了。

  当考虑算法功能(而不是其语言实现)时,伪代码常常得到应用。计算机科学在教学中通常使用虚拟码,以使得所有的程序员都能理解。

  综上,简单的说,让人便于理解的代码。不依赖于语言的,用来表示程序执行过程,而不一定能编译运行的代码。在数据结构讲算法的时候用的很多。 

语法规则

  例如,类Pascal语言的伪代码的语法规则是: 在伪代码中,每一条指令占一行(else if,例外)。指令后不跟任何符号(Pascal和C中语句要以分号结尾)。书写上的“缩进”表示程序中的分支程序结构。这种缩进风格也适用于if-then-else语句。用缩进取代传统Pascal中的begin和end语句来表示程序的块结构可以大大提高代码的清晰性;同一模块的语句有相同的缩进量,次一级模块的语句相对与其父级模块的语句缩进。

    算法的伪代码语言在某些方面可能显得不太正规,但是给我们描述算法提供了很多方便,并且可以使我们忽略算法实现中很多麻烦的细节。通常每个算法开始时都要描述它的输入和输出,而且算法中的每一行都给编上号码,在解释算法的过程中会经常使用算法步骤中的行号来指代算法的步骤。算法的伪代码描述形式上并不是非常严格,其主要特性和通常的规定如下:
        1) 算法中出现的数组、变量可以是以下类型:整数、实数、字符、位串或指针。通常这些类型可以从算法的上下文来看是清楚的,并不需要额外加以说明。
        2) 在算法中的某些指令或子任务可以用文字来叙述,例如,"设x是A中的最大项",这里A是一个数组;或者"将x插入L中",这里L是一个链表。这样做的目的是为了避免因那些与主要问题无关的细节使算法本身杂乱无章。
        3) 算术表达式可以使用通常的算术运算符(+,-,*,/,以及表示幂的^)。逻辑表达式可以使用关系运算符=,≠,<,>,≤和≥,以及逻辑运算符与(and),或(or),非(not)。
        4) 赋值语句是如下形式的语句:a<-b 。
这里a是变量、数组项,b是算术表达式、逻辑表达式或指针表达式。语句的含义是将b的值赋给a。
        5) 若a和b都是变量、数组项,那么记号a<->b 表示a和b的内容进行交换。
        6) goto语句具有形式
                                        goto label(goto标号)
它将导致转向具有指定标号的语句。
        7) 条件语句有以下两种形式:
                                            if c then s或者 
                                               if c then s
                                                  else s′
这里c是逻辑表达式,s和s′是单一的语句或者是被括在do和end之间的语句串。对于上述两种形式,假若c为真,则s被执行一次。假若c为假,则在第一种形式中,if语句的执行就完成了,而在第二种形式中,执行s′。在所有的情况下,控制就进行到了下一个语句,除非在s或s′中的goto语句使控制转向到其它地方。
         8) 有两种循环指令:while和for。
         while语句的形式是
                                              while c do  
                                                    s
                                                  end
这里c是逻辑表达式,而s是由一个或更多个语句组成的语句串。当c为真时,执行s。在每一次执行s之前,c都被检查一下;假若c为假,控制就进行到紧跟在while语句后面的语句。注意,当控制第一次达到while语句时,假若c为假,则s一次也不执行。 
       for语句的形式是
                                      for var init to limit by incr do
                                                        s
                                                      end
这里var是变量,init、limit和incr都是算术表达式,而s是由一个或多个语句组成的语句串。初始时,var被赋予init的值。假若incr≥0,则只要var≤limit,就执行s并且将incr加到var上。(假若incr<0,则只要var≥limit,就执行s并且将incr加到var上)。incr的符号不能由s来该改变。
      9) exit语句可以在通常的结束条件满足之前,被用来结束while循环或者for循环的执行。exit导致转向到紧接在包含exit的(最内层)while或者for循环后面的一个语句。
     10) return用来指出一个算法执行的终点;如果算法在最后一条指令之后结束,它通常是被省略的;它被用得最多的场合是检测到不合需要的条件时。return的后面可以紧接被括在引号的信息。
      11) 算法中的注释被括在/* */之中。诸如read和output之类的各种输入或者输出也在需要时被用到。
     

伪代码实例

  伪代码只是像流程图一样用在程序设计的初期,帮助写出程序流程。简单的程序一般都不用写流程、写思路,但是复杂的代码,最好还是把流程写下来,总体上去考虑整个功能如何实现。写完以后不仅可以用来作为以后测试,维护的基础,还可用来与他人交流。但是,如果把全部的东西写下来必定可能会让费很多时间,那么这个时候可以采用伪代码方式。比如:

  IF 九点以前 THEN

     do 私人事务;

  ELSE 9点到18点 THEN

  工作;

  ELSE

  下班;

  END IF

  这样不但可以达到文档的效果,同时可以节约时间. 更重要的是,使结构比较清晰,表达方式更加直观.

  下面介绍一种类Pascal语言的伪代码的语法规则。

  在伪代码中,每一条指令占一行(else if 例外,),指令后不跟任何符号(Pascal和C中语句要以分号结尾);

  书写上的“缩进”表示程序中的分支程序结构。这种缩进风格也适用于if-then-else语句。用缩进取代传统Pascal中的begin和end语句来表示程序的块结构可以大大提高代码的清晰性;同一模块的语句有相同的缩进量,次一级模块的语句相对与其父级模块的语句缩进; 

  在伪代码中,通常用连续的数字或字母来标示同一即模块中的连续语句,有时也可省略标号。

  符号△后的内容表示注释;

  在伪代码中,变量名和保留字不区分大小写,这一点和Pascal相同,与C或C++不同;

  在伪代码中,变量不需声明,但变量局部于特定过程,不能不加显示的说明就使用全局变量;

  赋值语句用符号←表示,x←exp表示将exp的值赋给x,其中x是一个变量,exp是一个与x同类型的变量或表达式(该表达式的结果与x同类型);多重赋值i←j←e是将表达式e的值赋给变量i和j,这种表示与j←e和i←e等价。

  例如:

  x←y

  x←20*(y+1)

  x←y←30

  以上语句用C分别表示为:

  x = y;

  x = 20*(y+1);

  x = y = 30;

  选择语句用if-then-else来表示,并且这种if-then-else可以嵌套,与Pascal中的if-then-else没有什么区别。

  例如:

  if (Condition1)

  then [ Block 1 ]

  else if (Condition2)

  then [ Block 2 ]

  else [ Block 3 ]

  循环语句有三种:while循环、repeat-until循环和for循环,其语法均与Pascal类似,只是用缩进代替begin - end;

  例如:

  1. x ← 0

  2. y ← 0

  3. z ← 0

  4. while x < N

  1. do x ← x + 1

  2. y ← x + y

  3. for t ← 0 to 10

  1. do z ← ( z + x * y ) / 100

  2. repeat

  1. y ← y + 1

  2. z ← z - y

  3. until z < 0

  4. z ← x * y

  5. y ← y / 2

   上述语句用C或C++来描述是:

  x = y = z = 0;

  while( z < N )

  {

  x ++;

  y += x;

  for( t = 0; t < 10; t++ )

  {

  z = ( z + x * y ) / 100;

  do {

  y ++;

  z -= y;

  } while( z >= 0 );
     }
  z = x * y;

  }

  y /= 2;

  数组元素的存取有数组名后跟“[下标]”表示。例如A[j]指示数组A的第j个元素。符号“ …”用来指示数组中值的范围。

  例如:

  A[1…j]表示含元素A[1], A[2], … , A[j]的子数组;

  复合数据用对象(Object)来表示,对象由属性(attribute)和域(field)构成。域的存取是由域名后接由方括号括住的对象名表示。

  例如:

  数组可被看作是一个对象,其属性有length,表示其中元素的个数,则length[A]就表示数组A中的元素的个数。在表示数组元素和对象属性时都要用方括号,一般来说从上下文可以看出其含义。

  用于表示一个数组或对象的变量被看作是指向表示数组或对象的数据的一个指针。对于某个对象x的所有域f,赋值y←x就使f[y]=f[x],更进一步,若有f[x]←3,则不仅有f[x]=3,同时有f[y]=3,换言之,在赋值y←x后,x和y指向同一个对象。

  有时,一个指针不指向任何对象,这时我们赋给他nil。

  函数和过程语法与Pascal类似。

  函数值利用 “return (函数返回值)” 语句来返回,调用方法与Pascal类似;过程用 “call 过程名”语句来调用;

  例如:

  1. x ← t + 10

  2. y ← sin(x)

  3. call CalValue(x,y)

  参数用按值传递方式传给一个过程:被调用过程接受参数的一份副本,若他对某个参数赋值,则这种变化对发出调用的过程是不可见的。当传递一个对象时,只是拷贝指向该对象的指针,而不拷贝其各个域。

### 23种设计模式概述 以下是常见的23种设计模式及其对应的伪代码示例和简单讲解: --- #### **创建型模式** ##### 单例模式 (Singleton Pattern) 单例模式确保某一个类只有一个实例,并提供全局访问点。 ```java class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized(Singleton.class){ if(instance == null){ instance = new Singleton(); } } } return instance; } } ``` 通过 `getInstance` 方法可以获取唯一的对象实例[^1]。 --- ##### 工厂方法模式 (Factory Method Pattern) 工厂方法模式定义了一个用于创建对象的接口,但由子类决定要实例化的类是什么。 ```java abstract class Creator { abstract Product factoryMethod(); void someOperation() { Product product = factoryMethod(); // 调用工厂方法创建产品 product.operation(); } } class ConcreteCreator extends Creator { @Override Product factoryMethod() { return new ConcreteProduct(); } } interface Product { void operation(); } class ConcreteProduct implements Product { @Override public void operation() { /* 实现具体操作 */ } } ``` 此模式允许客户端无需知道具体的实现细节就能创建对象。 --- ##### 抽象工厂模式 (Abstract Factory Pattern) 抽象工厂模式提供了一组相关或依赖的对象的创建方式,而不需要指定它们的具体类。 ```java interface AbstractFactory { AbstractProductA createProductA(); AbstractProductB createProductB(); } class ConcreteFactory1 implements AbstractFactory { @Override AbstractProductA createProductA() { return new ProductA1(); } @Override AbstractProductB createProductB() { return new ProductB1(); } } // 类似地定义其他工厂和产品... ``` 该模式适用于需要一组相互关联的产品的情况。 --- ##### 建造者模式 (Builder Pattern) 建造者模式将复杂对象的构建过程与其表示分离,使得同样的构建过程能够创建不同的表示。 ```java class Director { Builder builder; void construct(Builder b) { this.builder = b; this.builder.buildPartA(); this.builder.buildPartB(); } } interface Builder { void buildPartA(); void buildPartB(); Product getResult(); } class ConcreteBuilder implements Builder { Product product = new Product(); @Override void buildPartA() { /* 构建 A 部分 */ } @Override void buildPartB() { /* 构建 B 部分 */ } @Override Product getResult() { return product; } } ``` 它简化了复杂的对象创建流程。 --- ##### 原型模式 (Prototype Pattern) 原型模式利用现有的对象作为原型,复制并生成新的对象。 ```java public interface Prototype { Prototype clone(); } public class ConcretePrototype implements Prototype { String field; @Override public Prototype clone() { try { return (ConcretePrototype) super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } } ``` 这种方式适合于当对象初始化成本较高时使用。 --- #### **结构型模式** ##### 组合模式 (Composite Pattern) 组合模式使客户能以一致的方式处理单独对象以及对象容器中的所有对象。 ```java interface Component { void operation(); } class Leaf implements Component { @Override void operation() { /* 叶节点的操作 */ } } class Composite implements Component { List<Component> children = new ArrayList<>(); @Override void operation() { for(Component child : children){ child.operation(); } } void add(Component component){ children.add(component); } void remove(Component component){ children.remove(component); } } ``` 这有助于管理树形结构的数据。 --- ##### 外观模式 (Facade Pattern) 外观模式为子系统的一组接口提供一个统一的高层接口,从而使其更容易被理解。 ```java class SubSystemOne { void methodOne(){ /* 子系统的功能一 */ } } class Facade { SubSystemOne subSysOne = new SubSystemOne(); void operation(){ subSysOne.methodOne(); } } ``` 它可以隐藏底层复杂性。 --- ##### 桥接模式 (Bridge Pattern) 桥接模式将抽象部分与其实现部分分离,从而使两者都能独立变化。 ```java interface Implementor { void operationImpl(); } class ConcreteImplementorA implements Implementor { @Override void operationImpl() { /* 具体实现 A */ } } abstract class Abstraction { protected Implementor implementor; void setImplementor(Implementor impl){ this.implementor = impl; } abstract void operation(); } class RefinedAbstraction extends Abstraction{ @Override void operation() { implementor.operationImpl(); } } ``` 这种模式提高了扩展性和灵活性。 --- ##### 装饰器模式 (Decorator Pattern) 装饰器模式动态地给某个对象增加额外的功能。 ```java interface Component { void operation(); } class ConcreteComponent implements Component { @Override void operation() { /* 基础组件的行为 */ } } abstract class Decorator implements Component { protected Component component; public Decorator(Component c){ this.component = c; } @Override void operation() { component.operation(); } } class ConcreteDecoratorA extends Decorator { public ConcreteDecoratorA(Component c){ super(c); } @Override void operation() { super.operation(); addedBehavior(); } void addedBehavior(){} } ``` 它支持灵活的功能增强。 --- ##### 适配器模式 (Adapter Pattern) 适配器模式将一个类的接口转换成另一个接口,以便与其他不兼容的类协同工作。 ```java class Target { void request() {} } class Adaptee { void specificRequest() {} // 不兼容的方法名 } class Adapter extends Target { Adaptee adaptee; Adapter(Adaptee a){ this.adaptee = a; } @Override void request() { adaptee.specificRequest(); } } ``` 这种方法解决了现有类无法满足需求的问题。 --- ##### 代理模式 (Proxy Pattern) 代理模式为其他对象提供一种代理以控制对该对象的访问。 ```java interface Subject { void request(); } class RealSubject implements Subject { @Override void request() { /* 真正的主题行为 */ } } class Proxy implements Subject { RealSubject realSubject; @Override void request() { if(realSubject == null){ realSubject = new RealSubject(); } preRequestHook(); realSubject.request(); postRequestHook(); } void preRequestHook(){} void postRequestHook(){} } ``` 它常用于延迟加载或其他权限控制场景下。 --- #### **行为型模式** ##### 模板方法模式 (Template Method Pattern) 模板方法模式在一个方法中定义算法骨架,将一些步骤推迟到子类中实现。 ```java abstract class AbstractClass { final void templateMethod() { stepOne(); stepTwo(); } abstract void stepOne(); abstract void stepTwo(); } class ConcreteClass extends AbstractClass { @Override void stepOne() { /* 步骤一的实现 */ } @Override void stepTwo() { /* 步骤二的实现 */ } } ``` 此模式体现了最大化的代码重用[^2]。 --- ##### 状态模式 (State Pattern) 状态模式允许对象在其内部状态改变时改变其行为。 ```java interface State { void handle(Context context); } class Context { State state; void setState(State s){ this.state = s; } void request(){ this.state.handle(this); } } class ConcreteStateA implements State { @Override void handle(Context context) { /* 切换至另一种状态 */ } } ``` 它避免了大量的条件判断语句[^3]。 --- ##### 观察者模式 (Observer Pattern) 观察者模式定义了一种一对多的关系,目标对象的状态发生变化时通知所有的观察者。 ```java interface Observer { void update(String message); } class ConcreteObserver implements Observer { @Override void update(String message) { System.out.println(message); } } class Subject { List<Observer> observers = new ArrayList<>(); void addObserver(Observer o){ observers.add(o); } void notifyObservers(String msg){ for(Observer observer : observers){ observer.update(msg); } } } ``` 它是事件驱动编程的基础之一。 --- ##### 迭代器模式 (Iterator Pattern) 迭代器模式提供一种顺序访问集合元素而不暴露其内部表现形式的方法。 ```java interface Iterator { boolean hasNext(); Object next(); } interface Aggregate { Iterator iterator(); } class ConcreteAggregate implements Aggregate { List<Object> items = new ArrayList<>(); @Override Iterator iterator() { return new ConcreteIterator(items.iterator()); } } class ConcreteIterator implements Iterator { java.util.Iterator<?> it; ConcreteIterator(java.util.Iterator<?> i){ this.it = i; } @Override boolean hasNext() { return it.hasNext(); } @Override Object next() { return it.next(); } } ``` 它增强了遍历机制的通用性。 --- ##### 解释器模式 (Interpreter Pattern) 解释器模式为语言或者表达式定义语法解析规则,并基于这些规则进行求值。 ```java abstract class Expression { abstract int interpret(Map<String, Integer> variables); } class VariableExpression extends Expression { String name; VariableExpression(String n){ this.name = n; } @Override int interpret(Map<String, Integer> vars){ return vars.get(name); } } class AddExpression extends Expression { Expression left, right; AddExpression(Expression l, Expression r){ this.left = l; this.right = r; } @Override int interpret(Map<String, Integer> vars){ return left.interpret(vars) + right.interpret(vars); } } ``` 主要用于简单的DSL开发。 --- ##### 中介者模式 (Mediator Pattern) 中介者模式用来减少多个对象之间的耦合度。 ```java interface Mediator { void send(String message, Colleague colleague); } class ConcreteMediator implements Mediator { Colleague col1, col2; void setColleagues(Colleague c1, Colleague c2){ this.col1 = c1; this.col2 = c2; } @Override void send(String message, Colleague sender){ if(sender == col1){ col2.receive(message); }else{ col1.receive(message); } } } class Colleague { Mediator mediator; void setMediator(Mediator m){ this.mediator = m; } void send(String message){ mediator.send(message, this); } void receive(String message){} } ``` 降低了模块间的直接交互。 --- ##### 责任链模式 (Chain of Responsibility Pattern) 责任链模式允许多个接收者有机会处理请求直到有一个成功为止。 ```java abstract class Handler { Handler successor; void setSuccessor(Handler h){ this.successor = h; } abstract void handleRequest(int request); void passOn(int req){ if(successor != null){ successor.handleRequest(req); } } } class ConcreteHandlerA extends Handler { @Override void handleRequest(int request) { if(request >=0 && request <10){ System.out.println("Handled by A"); }else{ passOn(request); } } } ``` 实现了职责划分。 --- ##### 命令模式 (Command Pattern) 命令模式将请求封装成对象,便于参数化、队列化或记录日志等功能。 ```java interface Command { void execute(); } class Receiver { void action(){} // 接收者的实际动作 } class ConcreteCommand implements Command { Receiver receiver; ConcreteCommand(Receiver r){ this.receiver = r; } @Override void execute() { receiver.action(); } } class Invoker { Command command; void setCommand(Command cmd){ this.command = cmd; } void invoke(){ command.execute(); } } ``` 提升了请求发起方和执行方的解耦程度。 --- ##### 访问者模式 (Visitor Pattern) 访问者模式可以在不修改已有数据结构的情况下新增加操作。 ```java interface Element { void accept(Visitor visitor); } class ConcreteElementA implements Element { @Override void accept(Visitor v) { v.visit(this); } } interface Visitor { void visit(Element element); } class ConcreteVisitor implements Visitor { @Override void visit(Element elem) { /* 对应元素的操作 */ } } ``` 特别适合对多种类型的数据应用相同逻辑。 --- #### 结论 以上是对23种经典设计模式的简述及伪代码展示。每种模式都有特定的应用场景,在实际项目中需根据实际情况选用合适的模式。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值