590 likes | 786 Views
第 3 章 栈和队列. 要求: 了解栈的定义及特点,掌握栈表示和实现,重点是栈初始化、判断栈空和栈满、出栈和入栈操作;(注意栈顶的约定) 栈的应用举例,重点是表达式求值;(了解波兰式、逆波兰式、中缀式等概念) 栈与递归的实现;(系统工作栈) 了解队列的定义及特点,掌握队列的表示和实现,重点是队列初始化、判断队空和队满、出队和入队操作;难点:循环队列。 (离散事件模拟不要求). 进栈. 出栈. 栈顶. a n. ……. 栈 s=(a1,a2,……,an). a 2. 栈底. a 1. 第 3 章 栈和队列.
E N D
第3章 栈和队列 要求: • 了解栈的定义及特点,掌握栈表示和实现,重点是栈初始化、判断栈空和栈满、出栈和入栈操作;(注意栈顶的约定) • 栈的应用举例,重点是表达式求值;(了解波兰式、逆波兰式、中缀式等概念) • 栈与递归的实现;(系统工作栈) • 了解队列的定义及特点,掌握队列的表示和实现,重点是队列初始化、判断队空和队满、出队和入队操作;难点:循环队列。 • (离散事件模拟不要求)
进栈 出栈 ... 栈顶 an ……... 栈s=(a1,a2,……,an) a2 栈底 a1 第3章 栈和队列 栈和队列是两种特殊的线性表,是操作受限的线性表,称限定性DS • 3.1 栈(stack) • 栈的定义和特点 • 定义:限定仅在表尾进行插入或删除操作的线性表,表尾—栈顶top,表头—栈底bottom,不含元素的空表称空栈 • 特点:先进后出(FILO)或后进先出(LIFO) 进栈-插入元素 出栈-删除元素 抽象数据类型定义
F E 5 5 5 top top top top top top top D 4 4 4 C 3 3 3 B top top top top top top 2 2 2 A 1 1 1 top=0 0 0 0 栈空 栈空 栈满 F • 栈的表示和实现 • 顺序栈 一维数组s[M] 或先分配一个基本容量,逐段扩大,动态数组 E D C B A 出栈 进栈 栈顶指针top,指向实际栈顶 后的空位置,初值为0 base保持不变 设数组维数为M top=0,栈空,此时出栈,则下溢(underflow) top=M,栈满,此时入栈,则上溢(overflow)
typedef struct { SElemType *base; //保持不变,NULL 不存在栈 SElemType *top; //栈顶,指向不用(空)元素,与定义不同 int stacksize; }SqStack; //(进)入栈 top++,出(退)栈 top-- 算法描述 InitStack, DestroyStack, ClearStack, StackEmpty, StackLength, GetTop, Push, Pop, StackTraverse
构造一个空栈S • Status InitStack(SqStack &S){ • S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType)); • if (!S.base) exit(OVERFLOW); //存储分配失败 • S.top = S.base; • S.stacksize = STACK_INIT_SIZE; • return OK; • } • 取栈顶元素 • Status GetTop(SqStack S, SElemType &e) { • if (S.top == S.base) return ERROR; • e = *(S.top-1); • return OK; • }
入栈算法 Stutas Push(SqStack &S, SElemType e) { if (S.top – S.base >= S.stacksize { S.base = (SElemType *)realloc(S.base, (S.stacksize+STACKINCREMENT)*sizeof(SElemType)); if (!S.base) exit(OVERFLOW); S.top = S.base + S.stacksize; S.stacksize += STACKINCREMENT; } *S.top++ = e; //先赋值,再加指针 return OK; }
0 M-1 栈1底 栈1顶 栈2顶 栈2底 • 出栈算法 Status Pop (SqStack &S, SElemType &e) { if (S.top == S.base) return ERROR; e = *--S.top; //先减指针,再取值 return OK; } • 在一个程序中同时使用两个栈
栈顶 栈底 …... top ^ data link top top 栈底 p x …... ^ q top 栈底 top …... ^ typedef struct node { int data; struct node *link; }JD; • 结点定义 • 链栈 • 入栈算法 • 出栈算法
8 159 8 8 2 19 2 3 7 例 把十进制数159转换成八进制数 余 7 3 top top top top 余 3 7 7 余 2 0 2 (159)10=(237)8 3 7 3.2 栈的应用举例 • 数制转换 N = (N div d)x d + N mod d 算法 3.1 P48 计算过程 - 入栈 打印过程 - 出栈
void conversion (int Num) { // 算法3.1 // 对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数 InitStack(S); // 构造空栈 while (Num) { Push(S, Num % 8); Num = Num/8; } while (!StackEmpty(S)) { Pop(S,e); printf ("%d", e); } printf("\n"); } // conversion
top d a d • 回文游戏:顺读与逆读字符串一样(不含空格) 1.读入字符串 2.去掉空格(原串) 3.压入栈 4.原串字符与出栈字符依次比较 若不等,非回文 若直到栈空都相等,回文 字符串:“madam im adam” • 括号匹配的检验 园、方、花括号 嵌套匹配
void LineEdit( ){ InitStack(S); ch=gether( ); while(ch!=EOF){ while(ch!=EOF && ch!=‘\n’){ switch(ch){ case ‘#’ : Pop(S,c); case ‘@’ : ClearStack(S); default : Push(S,ch); } ch=getchar( ); } transfer; ClearStack(S); if(ch!=EOF) ch=gethar( ); } DestroyStack(S); } • 简单行编辑程序 逐行存入,退格 #, 清行 @ 算法 3.2 P50 • 迷宫求解,地图四染色
6 18 3 * 4 + - - - -12 6 6 6 2 操作数 操作数 操作数 操作数 操作数 运算符 运算符 运算符 运算符 运算符 • 表达式求值 运算规则 中缀表达式 后缀表达式(RPN) a*b+c ab*c+ a+b*c abc*+ a+(b*c+d)/e abc*d+e/+ 中缀表达式:操作数栈和运算符栈 P53表3.1优先关系 例 计算 2+4-3*6
算法基本思想 P53 1)操作符栈 OPTR的栈底元素为表达式起始符 ‘#’,操作数栈 OPND为空 2)依次读入字符:是操作数则入OPND栈,是操作符则要判断 算法 3.4 注意 未考虑匹配,表达式必须正确 表达式的前缀、中缀、后缀表示,其中表达式的前缀表示称为波兰式,表达式的后缀表示称为逆波兰式RPN (Reverse Polish Notation)。由于逆波兰式用的较多,习惯上称为波兰式 。 中缀表达式 - 算符优先法,括号,双堆栈 前、后缀表达式 - 单堆栈,算符无优先级,无括号 中缀 -> 后缀
OperandType EvaluateExpression( ) { // 算法3.4 算术表达式求值的算符优先算法。 // 设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合。 InitStack (OPTR); Push (OPTR, '#'); InitStack (OPND); c = getchar(); while (c!= '#' || GetTop(OPTR)!= '#') { if (!In(c, OP)) {Push(OPND, c); c=getchar();} // 不是运算符则进栈 else switch (precede(GetTop(OPTR), c)) { case '<': // 栈顶元素优先权低 Push(OPTR, c); c=getchar(); break; case '=': // 脱括号并接收下一字符 Pop(OPTR, x); c=getchar(); break; case '>': // 退栈并将运算结果入栈 Pop(OPTR, theta); Pop(OPND, b); Pop(OPND, a); Push(OPND, Operate(a, theta, b)); break; } // switch } // while return GetTop(OPND); } // EvaluateExpression
15 3 top top top top top top 4 4 5 19 4 3 7 后缀表达式求值步骤: 1、读入表达式一个字符 2、若是操作数,压入栈,转4 3、若是运算符,从栈中弹出2个数,将运算结果再压入栈 4、若表达式输入完毕,栈顶即表达式值; 若表达式未输入完,转1 后缀表达式:435*+ 例 计算 4+3*5
子过程2 子过程1 子过程3 t s s 主程序 r r r s t r r s r 3.3 栈与递归的实现 • 过程的嵌套调用
递归过程及其实现 • 递归:函数直接或间接的调用自身叫~ • 实现:建立递归工作栈 例 递归的执行情况分析 void print(int w) { int i; if ( w!=0) { print(w-1); for(i=1;i<=w;++i) printf(“%3d,”,w); printf(“/n”); } } 运行结果: 1, 2,2, 3,3,3,
w w 1 0 w print(0); 2 返回 w (4)输出:1 (4)输出:1 主程序 print(1); 3 (3) 输出:2, 2 (3) 输出:2, 2 print(2); w=3; (2) 输出:3, 3, 3 (2) 输出:3, 3, 3 print(w) (1) (1) top (3)w=1 (1 ) 3 (4)w=0 (2)w=2 (3)w=1 (2) 2 (1)w=3 (2)w=2 (1) 3 top (1)w=3 top (4) 0 top (3) 1 (3) 1 top (2)w=2 (2) 2 (2) 2 (1)w=3 (1) 3 (1) 3 (1)w=3 top top top 结束 递归调用执行情况如下:
n x y z 返回地址 • Tower of Hanoi问题 • 问题描述:有A,B,C三个塔座,A上套有n个直径不同的圆盘,按直径从小到大叠放,形如宝塔,编号1,2,3……n。要求将n个圆盘从A移到C,叠放顺序不变,移动过程中遵循下列原则: • 每次只能移一个圆盘 • 圆盘可在三个塔座上任意移动 • 任何时刻,每个塔座上不能将大盘压到小盘上 • 解决方法: • n=1时,直接把圆盘从A移到C • n>1时,先把上面n-1个圆盘从A移到B,然后将n号盘从A移到C,再将n-1个盘从B移到C。即把求解n个圆盘的Hanoi问题转化为求解n-1个圆盘的Hanoi问题,依次类推,直至转化成只有一个圆盘的Hanoi问题 • 算法: • 执行情况: • 递归工作栈保存内容:形参n,x,y,z和返回地址 • 返回地址用行编号表示
1 2 3 A B C A B C 3 A B C 0 1 A B C 6 2 A C B 6 3 A B C 0 2 A C B 6 3 A B C 0 3 A B C 0 2 A C B 6 main() { int m; printf("Input number of disks”); scanf("%d",&m); printf(”Steps : %3d disks”,m); hanoi(m,'A','B','C'); (0) } void hanoi(int n,char x,char y,char z) (1) { (2) if(n==1) (3) move(1,x,z); (4) else{ (5) hanoi(n-1,x,z,y); (6) move(n,x,z); (7) hanoi(n-1,y,x,z); (8) } (9) }
A B C A B C 3 A B C 0 2 A C B 6 1 C A B 8 3 A B C 0 2 A C B 6 3 A B C 0 3 A B C 0 2 A C B 6 main() { int m; printf("Input the number of disks scanf("%d",&m); printf("The steps to moving %3d hanoi(m,'A','B','C'); (0) } void hanoi(int n,char x,char y,char z) (1) { (2) if(n==1) (3) move(1,x,z); (4) else{ (5) hanoi(n-1,x,z,y); (6) move(n,x,z); (7) hanoi(n-1,y,x,z); (8) } (9) }
A B C A B C 3 A B C 0 2 B A C 8 3 A B C 0 2 B A C 8 1 B C A 6 3 A B C 0 2 B A C 8 3 A B C 0 main() { int m; printf("Input the number of disks scanf("%d",&m); printf("The steps to moving %3d hanoi(m,'A','B','C'); (0) } void hanoi(int n,char x,char y,char z) (1) { (2) if(n==1) (3) move(1,x,z); (4) else{ (5) hanoi(n-1,x,z,y); (6) move(n,x,z); (7) hanoi(n-1,y,x,z); (8) } (9) }
A B C A B C 3 A B C 0 2 B A C 8 1 A B C 8 3 A B C 0 2 B A C 8 3 A B C 0 3 A B C 0 2 B A C 8 栈空 main() { int m; printf("Input the number of disks scanf("%d",&m); printf("The steps to moving %3d hanoi(m,'A','B','C'); (0) } void hanoi(int n,char x,char y,char z) (1) { (2) if(n==1) (3) move(1,x,z); (4) else{ (5) hanoi(n-1,x,z,y); (6) move(n,x,z); (7) hanoi(n-1,y,x,z); (8) } (9) }
递归的特性 • 有限次递归调用,非递归出口 if或while语句 • 递归的优缺点 • 优点:结构清晰、易读,正确性易证明 • 缺点:运行效率低,时空消耗大 • 递归过程的模拟 • 先写递归算法,再转化成非递归 • PASCAL版 英文版 Hanoi 非递归 • 实质:系统管理的递归工作栈改为程序员管理
作业: 3.6 3.7 3.8 补:写一递归算法将单链表(无头结点)倒序
出队 a1 a2 a3…………………….an 入队 队列Q=(a1,a2,……,an) front rear 出队 出队 a1 a2 a3…………………….an 入队 入队 端1 端2 3.4 队列 (Queue) • 队列的定义及特点 • 定义:队列是限定只能在表的一端进行插入,在表的另一端进行删除的线性表 双端 • 队尾(rear)——允许插入的一端 • 队头(front)——允许删除的一端 • 队列特点:先进先出(FIFO) • 双端队列
头结点 队头 队尾 …... front ^ rear 链队列 - 队列的链式表示和实现 抽象数据类型定义 QueueEmpty,EnQueue,DeQueue typedef struct { QueuePtr front; QueuePtr rear; } LinkQueue; • 结点定义 typedef struct QNode { QElemType data; struct QNode *next; }QNode, *QueuePtr; 设队首、队尾指针front和rear, front指向头结点,rear指向队尾
^ ^ x出队 x y ^ rear front y出队 空队 x入队 x ^ rear rear front front front rear y入队 x y ^ rear front
部分算法描述 P62 • InitQueue • DestroyQueue • 入队算法 EnQueue • 出队算法 DeQueue 最后一个元素出队后,队尾指针指向头结点 If (Q.rear == p) Q.rear = Q.front;
rear J6 J5 5 5 5 5 rear J4 4 4 4 4 rear rear rear J3 front 3 3 3 3 front front front J2 2 2 2 2 J1 1 1 1 1 front=-1 rear=-1 front front J4,J5,J6入队 J1,J2,J3出队 J1,J2,J3入队 0 0 0 0 队空 队列的顺序存储结构 • 实现:用一维数组实现sq[M] J3 J2 J1 设两个指针front,rear,约定: rear指示队尾元素; front指示队头元素前一位置 初值front=rear=-1 空队列条件:front==rear 入队列:sq[++rear]=x; 出队列:x=sq[++front];
M-1 rear …... 0 1 …... front • 存在问题 设数组大小为M,则: • 当front=-1,rear=M-1时,再有元素入队发生溢出——真溢出 • 当front-1,rear=M-1时,再有元素入队发生溢出——假溢出 • 解决方案 • 队首固定,每次出队剩余元素向下移动——浪费时间 • 循环队列 • 基本思想:把队列设想成环形,让sq[0]接在sq[M-1]之后,若rear+1==M,则令rear=0; • 实现:利用“模”运算 • 入队: rear=(rear+1)%M; sq[rear]=x; • 出队: front=(front+1)%M; x=sq[front]; • 队满、队空判定条件
front rear 5 4 0 3 1 2 rear J5 J6 J4 5 4 0 J4,J5,J6出队 3 1 2 front J7,J8,J9入队 J5 初始状态 J6 J4 5 4 0 3 1 J7 J9 2 J8 front rear 队空:front==rear 队满:front==rear 解决方案: 1.另外设一个标志以区别队空、队满 2.少用一个元素空间: 队空:front==rear 队满:(rear+1)%M==front
基本操作算法描述 P64 • InitQueue • QueueLength • 入队算法:EnQueue (Q.rear + 1) % MAXQSIZE == Q.front 满队 • 出队算法:DeQueue Q.front == Q.rear 空队
队列应用举例 • 离散事件模拟 • 划分子集问题 • 图的广度优先搜索 • 多任务操作系统中CPU调度,多队列,分时使用
划分子集问题 • 问题描述:已知集合A={a1,a2,……an},及集合上的关系R={ (ai,aj) | ai,ajA, ij},其中(ai,aj)表示ai与aj间存在冲突关系。要求将A划分成互不相交的子集A1,A2,……Ak,(kn),使任何子集中的元素均无冲突关系,同时要求分子集个数尽可能少 例 A={1,2,3,4,5,6,7,8,9} R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9), (5,6), (5,4), (7,5), (7,6), (3,7), (6,3) } 可行的子集划分为: A1={ 1,3,4,8 } A2={ 2,7 } A3={ 5 } A4={ 6,9 }
算法思想:利用循环筛选。从第一个元素开始,凡与第一个元素无冲突的元素划归一组;再将剩下的元素重新找出互不冲突的划归第二组;直到所有元素进组算法思想:利用循环筛选。从第一个元素开始,凡与第一个元素无冲突的元素划归一组;再将剩下的元素重新找出互不冲突的划归第二组;直到所有元素进组 • 所用数据结构 • 冲突关系矩阵 • r[i][j]=1, i,j有冲突 • r[i][j]=0, i,j无冲突 • 循环队列cq[n] • 数组result[n]存放每个元素分组号 • 工作数组newr[n]
工作过程 • 初始状态:A中元素放于cq中,result和newr数组清零,组号group=1 • 第一个元素出队,将r矩阵中第一行“1”拷入newr中对应位置,这样,凡与第一个元素有冲突的元素在newr中对应位置处均为“1”,下一个元素出队 • 若其在newr中对应位置为“1”,有冲突,重新插入cq队尾,参加下一次分组 • 若其在newr中对应位置为“0”, 无冲突,可划归本组;再将r矩阵中该元素对应行中的“1”拷入newr中 • 如此反复,直到9个元素依次出队,由newr中为“0”的单元对应的元素构成第1组,将组号group值“1”写入result对应单元中 • 令group=2,newr清零,对cq中元素重复上述操作,直到cq中front==rear,即队空,运算结束
0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 1 0 1 R= 0 1 1 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 cq 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 r 初始 f newr result • 算法描述 R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9), (5,6), (5,4), (7,5), (7,6), (3,7), (6,3) }
0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 1 0 1 R= 0 1 1 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 2 3 4 5 6 7 8 9 r f newr result • 算法描述 R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9), (5,6), (5,4), (7,5), (7,6), (3,7), (6,3) } cq
0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 1 0 1 R= 0 1 1 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 2 3 4 5 6 7 8 9 r f newr result • 算法描述 R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9), (5,6), (5,4), (7,5), (7,6), (3,7), (6,3) } cq
0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 1 0 1 R= 0 1 1 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 0 0 0 11 0 0 1 0 1 0 0 0 0 0 0 2 4 5 6 7 8 9 r f newr result • 算法描述 R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9), (5,6), (5,4), (7,5), (7,6), (3,7), (6,3) } cq
0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 1 0 1 R= 0 1 1 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 0 0 111 0 1 1 0 11 0 0 0 0 0 2 5 6 7 8 9 r f newr result • 算法描述 R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9), (5,6), (5,4), (7,5), (7,6), (3,7), (6,3) } cq
0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 1 0 1 R= 0 1 1 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 0 0 111 0 1 1 0 11 0 0 0 0 0 25 6 7 8 9 r f newr result • 算法描述 R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9), (5,6), (5,4), (7,5), (7,6), (3,7), (6,3) } cq
0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 1 0 1 R= 0 1 1 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 0 0 111 0 1 1 0 11 0 0 0 0 0 256 7 8 9 r f newr result • 算法描述 R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9), (5,6), (5,4), (7,5), (7,6), (3,7), (6,3) } cq
0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 1 0 1 R= 0 1 1 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 0 0 111 0 1 1 0 11 0 0 0 0 0 256 7 8 9 r f newr result • 算法描述 R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9), (5,6), (5,4), (7,5), (7,6), (3,7), (6,3) } cq
0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 1 0 1 R= 0 1 1 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 0 0 111 0 1 1 0 11 0 0 0 1 0 256 7 9 r f newr result • 算法描述 R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9), (5,6), (5,4), (7,5), (7,6), (3,7), (6,3) } cq
0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 1 0 1 R= 0 1 1 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 0 0 111 0 1 1 0 11 0 0 0 1 0 256 79 r f newr result • 算法描述 R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9), (5,6), (5,4), (7,5), (7,6), (3,7), (6,3) } cq
0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 1 0 1 R= 0 1 1 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 1 0 0 0 11 0 11 1211 0 0 0 1 0 56 79 r f newr result • 算法描述 R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9), (5,6), (5,4), (7,5), (7,6), (3,7), (6,3) } cq
0 1 0 0 0 0 0 0 0 1 0 0 0 1 1 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 1 0 1 R= 0 1 1 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 1 0 0 0 11 0 11 1211 0 0 0 1 0 6 79 5 r f newr result • 算法描述 R={ (2,8), (9,4), (2,9), (2,1), (2,5), (6,2), (5,9), (5,6), (5,4), (7,5), (7,6), (3,7), (6,3) } cq