,p:true,s:[9篇

时间:2022-09-02 13:30:07 来源:网友投稿

,p:true,s:[9篇,p:true,s:[ 第第99章章查找查找 1“”2“”34 “”&ldqu下面是小编为大家整理的,p:true,s:[9篇,供大家参考。

,p:true,s:[9篇

篇一:,p:true,s:[

9 9 章章查找查找

 1“”2“”34

 “”“”“”查找表的两个类别:

 “ “” ”“ “” ”

 “ “” ”“ “” ”“ “” ”“ “” ”

 9.1

 9.2

 9.3

 9.1

 D:R:DADT StaticSearchTable {

 Create(&ST, n);Destroy(&ST);Search(ST, key);Traverse(ST, Visit());P:} ADT StaticSearchTable

 构造一个含有n个数据元素的静态查找表ST。Create(&ST, n);操作结果:

 销毁表ST。Destroy(&ST);初始条件:操作结果:静态查找表ST存在;

 ST key “”Search(ST, key);STkey

 按某种次序对ST的每个元素调用 函数Visit()一次且仅一次。

 一旦Visit()失败, 则操作失败。Traverse(ST, Visit());初始条件:操作结果:静态查找表ST存在, Visit是对元素操作的应用 函数;

 typedef

 struct {ElemType *elem; // 0int

  Length;

 // } SSTable;typedef struct {的实现keyType key;

 // … …// } ElemType ;

 以顺序表或线性链表表示静态查找表。一、

 21 37 88 19 92 05 64 56 80 75 13

 0

 1

  2

  3

 4

  5

 6

  7

 8

  9

 10

 11

 ST.LengthST.eleme=64,ST.elem[k] = e, : k = ?k k k k k k k

 int location( SSTable ST, KeyType key) {k = 1;for (k=1; k<=L.Length &&ST.elem[k]!=key;k++);if ( k<= L.Length)

 return k; else

 return 0;}

 21 37 88 19 92 05 64 56 80 75 13

 0

 1

  2

  3

 4

  5

 6

  7

 8

  9

 10

 11

 ST.Lengthkey=64ST.elem21 37 88 19 92 05 64 56 80 75 13

 0

 1

  2

  3

 4

  5

 6

  7

 8

  9

 10

 11

 ST.Lengthkey=60ST.elem60ii64iiiiiiiiiiiiiii

 int Search_Seq(SSTable ST, KeyType key) {ST.elem[0].key = key;// “”for (i=ST.Length; ST.elem[i].key!=key; --i);

 return i;// i0}

 (Average Search Length): n PiiCi分析顺序查找的时间性能iniiCPASL111iniP

 在等概率查找的情况下,顺序表查找成功的平均查找长度为:对而言, Ci= n-i+1n1iP 21111 nn)i(nASLnissASL = nP1+(n-1)P2+ …+2Pn-1+Pn

 在不等概率查找的情况下, ASLss在PnPn-1···P2P1时取极小值。

 二、 有序查找表二、 有序查找表

 05 13 19 21 37 56 64 75 80 88 92

 0

 1

  2

  3

 4

  5

 6

  7

 8

  9

 10

 11

  ST.elemST.lengthlowhighmidlowmidhighmidlowhighmid = (low+high)/2

 int Search_Bin ( SSTable ST, KeyType key ) {low = 1;

 high = ST.length;

  while (low <= high) {mid = (low + high) / 2;if EQ (key , ST.elem[mid].key) )return

 mid;

 // else

 if ( LT (key , ST.elem[mid].key) )high = mid - 1;

  else

 low = mid + 1; // }return 0;

  // }// //

 n=116391425781011i13243243546173849 10 1123Ci4

 n=2h-1 n>50n n 1) 1(log12112111njinnjnCnASLhjnibs1) 1(log2nASLbs

 :

 A

 B

  C

  D

  EPi:

  0.2 0.3

 0.05

  0.3

  0.15Ci:

 2

 3

  1

  2

  3:ASL=2 0.2+3 0.3+1 0.05+2 0.3+3 0.15=2.42

 1

 3

 2

 3ASL=2 0.2+1 0.3+3 0.05+2 0.3+3 0.15=1.9

 n1iihiwPHPHPHnhiwi=c*pipici

 :

 A

 B

  C

  D

  EPi:

  0.2 0.3

 0.05

  0.3

  0.15Ci:

 2

 3

  1

  2

  3Ci2

 1

 3

 2

 3CADBEPH=0.05+(0.2+0.3)*2+(0.3+0.15)*3=2.4BADBEPH=0.3+(0.2+0.3)*2+(0.05+0.15)*3=1.9

 

 (rl,rl+1,...,rh)rl.key<rl+1.key<...<rh.keyrijj111ijhijiwwP{rl,rl+1,...,ri-1}{ri+1,...,rh}ri

 11)(iilhiswswswswPwl-1 = 0 swl-1= 0jijiwsw1jj111ijhijiwwP)swsw(iswswP1l1ihilih

 j00012221 18 12 496213358 11 15 18 2338043546375wjswjpjkeyA B C D E F GCA1)(lhswswPlhh10 185h0E211h33lG31iiiswsw

 ECGABDF:= 3 2+4 1+2 5+3 3+1 4+3 3+2 5 = 52= 3 2+2 1+3 5+1 3+3 4+2 3+3 5 = 59DBACFEG

 Status SecondOptimal(BiTree &T, ElemType R[], float sw[], int low, int high){ // R[low..high]sw// TPiif (!(T = new BiTNode)) return ERROR;T->data = R[i];

 //

 if (i==low)

 T->lchild = NULL;

 // else

 SecondOptimal(T->lchild, R, sw, low, i-1);// if (i==high)

 T->rchild = NULL;

 // else SecondOptimal(T->rchild, R, sw, i+1, high);// return OK;}

 Status CreateSOSTre(SOSTree &T, SSTable ST) {

 // ST // ST if (ST.length = 0)

 T = NULL;else {FindSW(sw, ST);// ST // weight SecondOpiamal(T, ST.elem, sw, 1, ST.length);}return OK;} // CreatSOSTreeTweight

 12

 22 12 13 8 22 9 20 33 42 44 38 24 48 60 58 74 49 86 5322 48 8617 13

 =(Lb)+

 (Lw)

 9.2

 ADT DynamicSearchTable {DRD

 InitDSTable(&DT)DestroyDSTable(&DT)P:SearchDSTable(DT, key);InsertDSTable(&DT, e);DeleteDSTable(&T, key);TraverseDSTable(DT, Visit());}ADT

 DynamicSearchTable

 DTInitDSTable(&DT);

 DTDestroyDSTable(&DT);DT

 DTkey“”SearchDSTable(DT, key);DTkey

 DTe InsertDSTable(&DT, e);DTe.key e DT

 DTkeyDeleteDSTable(&T, key);DTkey

 DTVisitTraverseDSTable(DT, Visit());DTVisit()Visit()

 B -B+

 一、 二叉排序树(二叉查找树)12345

 1132

 503080209010854035252388

 50308020901085403525238866

 通常, 用 二叉链表作为二叉排序树的存储结构。typedef struct BiTNode { // TElemType

 data;struct BiTNode *lchild, *rchild; // 左右孩子指针} BiTNode, *BiTree;

 2123

 5050505050503030808020909085404035358832== 50 ,35 ,90 ,95

 在查找过程中, 生成了 一条:;或者————

 Status SearchBST (BiTree T, KeyType key,BiTree f, BiTree &p ){if (!T){ p = f;

 return FALSE; }

 // } // SearchBSTelse

 if ( EQ(key, T->data.key) )else

 if ( LT(key, T->data.key) )else{ p = T;

 return TRUE; }

 // SearchBST (T->lchild, key, T, p );

 // SearchBST (T->rchild, key, T, p ); //

 30201040352523fT设 key = 48fTTfT22pffTTTTfffp

 3

 Status Insert BST(BiTree &T, ElemType e ){// e.key // e // TRUE; FALSEif (!SearchBST ( T, e.key, NULL, p )){

  ……}else return FALSE;} // Insert BST

 s = new BiTNode;

  // s->data = e;

 s->lchild = s->rchild = NULL;

 if

 ( !p )

 T = s;

  // s else

  if ( LT(e.key, p->data.key) ) p->lchild = s;// *s *p else

 p->rchild = s;

  // *s *p return TRUE;

  //

 (1)

 (2)

 (3) 4

 503080209085403588321= 2088

 503080209085403588322= 4080

 5040308020908540403588323= 50

 Status DeleteBST (BiTree &T, KeyType key ){ // T key // // TRUEFALSEif (!T)

 return FALSE;// keyelse {

 … … }} // DeleteBST

 if ( EQ (key, T->data.key) ) // keyelse if ( LT (key, T->data.key) )else{

 Delete (T);

  return TRUE;

 }DeleteBST ( T->lchild, key );// DeleteBST ( T->rchild, key );//

 void Delete ( BiTree &p ){// p// if (!p->rchild) {

  } //else if (!p->lchild) {

 } //… …else {

 }} // Delete… …… …

 // 右子树为空树则只需重接它的左子树q = p;

 p = p->lchild;

 delete q;pp

 // 左子树为空树只需重接它的右子树q = p;

 p = p->rchild;

 delete q;pp

 q = p;

 s = p->lchild;while (!s->rchild) { q = s;

 s = s->rchild; }// s // p->data = s->data;if (q != p )

 q->rchild = s->lchild;

  else

 q->lchild = s->lchild;// *qdelete s;pqs

 5ASL n

 31254123452134535412ASL =1+2+3+4+5= 3/ 5ASL =1+2+3+2+3= 2.2/ 5

 nkn-k-1,n-k-1knk P(n, k)

 ( 0 k n-1 )

 n n! n k10),(1)(nknPnnPASLiininiiC1nCpknP11),(CnnnnPlog12)(

 

 11RLhh548254821

 :5, 4, 2, 8, 6, 95424258665842向右旋转一次先向右旋转再向左旋转

 426589642895向左旋转一次继续插入关键字 9

 二叉排序树的平衡旋转ABBLARBRhh-1h-112ABBLARBR00LL

 二叉排序树的平衡旋转RRABBRALBLhh-1h-1-1-2ABBRBLAL00

 二叉排序树的平衡旋转LRABBLARCLh-1h-2h-1-12CRC1ACBLARCR-10B0CL

 二叉排序树的平衡旋转RLBCALBRCR-10A0CLABBRALCLh-1h-2h-11-2CRC1

 log(n)

 B -12345

 1. B-树的定义mB-m (1)m (2) (3)m/2 (4)(n,A0,K1,A1,K2,A2,...,Kn,An)K1 <K2 <……< Kn,

  Ai

 B-

 root

 50

  15

  71

  84

  3

  8

 20

 26

 43

  56

 62

 78

  89

 964阶B-树

 typedef struct BTNode {int

 keynum;

 // struct BTNode

 *parent;// KeyType

  key[m+1]; // 0struct BTNode

 *ptr[m+1]; // Record

 *recptr[m+1]; // 0} BTNode, *BTree; // BB

 2.

 typedef struct {BTNode

 *pt;

  // 指向找到的结点的int i;

  // 1..m, 在结点中的关键字int tag;

  // 查找成功(=1)或失败(=0)} Result;

  // 在B树的查找结果类型

 Result SearchBTree(BTree T, KeyType K) {p=T;

 q=NULL;

 found=FALSE;

 i=0; while (p && !found) {n=p->keynum;

 i=Search(p, K);// p->key[1..keynum]i p->key[i]<=K<p->key[i+1]if (i>0 && p->key[i]==K)

 found=TRUE; else { q=p;

  p=p->ptr[i]; }

 // q p }if (found)

 return (p,i,1);

  // else return (q,i,0);

 // } // SearchBTree

 31n<m

 2n=m“”s = m/2A0K1……Ks-1As-1AsKs+1Ks……KnAnp3

 5030 50

 80 803020 40 20 80 60 80 60 80 9060= 60,90,9050

 8030,40 503阶B-树

 m/2 -1()“”()“”4

 B-B-5N m B-logm/2((N+1)/2)+1

 B-B+

 1B+B-nn

 50

  9615

 5062 78 9671

 7884 89

 9656

  6220 26 43 503

 8

  15sqroot

 2B+ KiAi

 3B-

 1.2. .3. Trie

 1.

 “”‘ ’

 D$S$VE$$$E$GH$S${HAD, HAS, HAVE, HE, HER, HERE, HIGH, HIS }RHAIE

 2.

 —typedefenum { LEAF, BRANCH }NodeKind; // 两种结点类型:

 {}:first symbol nextinfoptr symbol next

 HAD$HADE$R$$ES$GH$IHEHERHEREHIGHHIS…T

 typedef struct DLTNode {char symbol;struct DLTNode

 *next;

 NodeKind

 kind;union {Record

  *infoptr;

  struct DLTNode

 *first;// // // }} DLTNode, *DLTree;

  //

 #define MAXKEYLEN

 16 //typedef struct {char ch[MAXKEYLEN];

  // int num;

  // } KeysType;

 //

 :: T K.ch[0..K.num-1]():K.ch[i] =? p->symbol: p 0 i K.num-1

 :

 p=T->first;

  i = 0;( p && p->symbol == K.ch[i] && i<K.num-1)p=p->first;

 i++;( p && p->symbol != K.ch[i] )p=p->next;( p && p->symbol==K.ch[i] && i==K.num-1)p->infoptr ( p == NULL);

 3. Trie—(retrieve)0

 1

 2

 3

 4

 5

 … …24

 25

 26假设以字母作为基数

 0

 1(A) 3

 4

 5(E)

 9(I)

 ……268(H)4(D)

 19(S)

  22(V)

  0

 18(R)

 7(G)

 190

 5(E)THADHAS HAVE HEHERHEREHIGHHIS

 typedef struct TrieNode {NodeKind

 kind;

  // union {struct { KeyType

 K; Record

 *infoptr } lf;

  // ()struct { TrieNode *ptr[27]; int num } bh;

  // (27) }} TrieNode, *TrieTree;

 // C :

 Trie:: T Trie K.ch[0..K.num-1]():p pp = p->bh.Ptr[ord(K.Ch[i])]

 ;( :

  0 i K.num-1 )

 :

 p=T;

  i = 0;( p && p->kind == BRANCH && i<K.num)p=p->bh.ptr[ord(K.ch[i])];

 i++;ord ( p && p->kind==LEAF && p->lf.K==K)p->lf.infoptr ( !p || p->kind==LEAF && p->lf.K!=K );

 二、三、四、五、

 一、

 ASL = 0

 000 ~ 999 1000 xx000 ~ xx999 ()

 key H(key) 1) 2)

 0

 1

  2

 3

 4

  5

 6

  7

 8

 9

  10

 11

  12

 13{Zhao, Qian, Sun, Li, Wu, Chen, Han, Ye, Dei}例如:

 对于如下 9 个关键字H(key) =(Ord() -Ord("A")+1)/2ChenZhaoQian SunLiWuHanYeDei

 1)

  2)

 “”key1 key2H(key1) = H(key2)

 H(key)()

 关键字取值范围地址空间取值范围H(key)解决冲突的方法哈希表

 二、1.3. 5. 4. 6. 2.

 H(key) = keyH(key) = a key + b1.= =

 2.s (u1, u2, …, us)

 3. :

 4. :

 :H(key) = key MOD p

 ,pmpm 20 5.

 6.:H(key) = Random(key)Random

 ()

 三、1. 3. 2. 4.

 H(key)H0, H1, H2, …Hs1sm-1H0= H(key)Hi= ( H(key) + di) MOD m i=1, 2, …, s1.

 di1) di= ci 最简单...

篇二:,p:true,s:[

章 栈与队列 4.1 栈 4.1.1 栈的结构特点和操作 4.1.2 栈的表示和操作的实现 4.2

 栈的应用举例 4.3

 队列 4.3.1

 队列的结构特点和操作 4.3.2

 队列的表示和操作的实现 4.4

  队列的应用举例1

 4.1 栈 3.1.1

 栈的结构特点与操作 栈(stack)

 是限定只能在一端进行插入和删除操作的线性表。

 其中允许进行插入和删除的一端称为“栈顶(top)

 ” , 另一端称为“栈底(bottom)

 ” 。

 数据元素个数为零的栈是“空栈” 栈是一种“先进后出(LIFO)

 ” 的线性表。 例:

 假设栈中元素以(a1,a2,…,an)

 的顺序进栈, 出栈的第一个元素是a素是an.2a1a2…栈顶栈底进栈出栈an出栈的第一个元素为栈顶元素an… a2a1

 在应用中, 常用的栈的基本操作有: InitStack(&s):构造一个空栈S ; DestoryStack(&s):销毁一个已存在的栈s; ClearStack(&s):将栈s清为空栈; ClearStack(&s):将栈s清为空栈;4.1.2

  栈的基本操作3 StackLength(s):返回s的元素个数; StackEmpty(S)

 :

 判断栈S是否为空, 为空返回“TRUE”,否则, 返回“FALSE”;

  Push(&S, e)

 :

 将新元素e插入作为栈S的栈顶。 Pop(&S, &e)

 :

 删除S的栈顶元素,并用e返回其值。 GetTop(S, &e)

 :

 用e返回栈顶元素,S保持不变。 StackTraverse(S)

 :

 从栈底到栈顶依次输出S中的各个元素。4.1.2

  栈的基本操作4

 4.1.2 栈的表示和操作的实现 栈有两种表示方法:

 顺序栈和链栈。 1.顺序栈 用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素, 并附设一栈顶指针Top指示栈顶顶的数据元素, 并附设元素在顺序栈中的位置。5栈顶指针Top指示栈顶 顺序栈通常用一维数组来实现, 并预设一最大数组空间, 并且还可以根据需要设一个增补量。

 1.顺序栈 栈的顺序存储表示Const STACK_INT_SIZE=100;//初始分配的最大空间量Const STACKINCREMENT=10;//增补空间量Typedef struct {SElemType *elem; //存储空间的基地址SElemType

 *elem; //存储空间的基地址int

  top;//栈顶指针int

  satcksize;//当前分配的最大容量int

  incrementsize;//约定的增补空间}Sqstack; // stacksize和incrementsize以SElemType为单位6用C做描述语言时, 通常以top=-1表示顺序栈为空。

 1.顺序栈 基本操作的实现 初始化操作void InitStack_Sq (Sqstack &S, int maxsize= STACK_INIT_SIZE, int incresize= STACKINCREMENT) { //构造一个最大容量为maxsize的顺序栈S.elem = new SElemType [maxsize]; S.top =-1;S.stacksize = maxsize;S.incrementsize = incresize;} // Initstack_Sq  复杂度为O(1)7

  取栈顶元素bool GetTop_Sq(SqStack S,SElemType &e){

 //若栈不空, 用e返回S的栈顶元素, 并返回TRUE, 否则返回FALSEif(S.top==-1) return FALSE;e=S.elem[S.top]; return TRUE;e S e e[S top]; etuU ;}1.顺序栈8执行后e=“数据结构”C语言数据结构C语言数据结构S.topS.top

  将新元素压入栈中的操作:void Push_Sq(SqStack &S,SElemType e){//将新元素e压入栈中作为新的栈顶元素if(S.top==S.stacksize)

 incrementStacksize(S);//若栈已满则重新分配存储空间//若栈已满, 则重新分配存储空间, 并追加S.incrementsize个元素空间。S.elem[++S.top]=e;}// Push_Sq并追加1.顺序栈9

 例:

 已知顺序栈S如图所示, x=“数据结构”执行push(S,x)

 后的结果为:执行后执行后1.顺序栈10S.topC语言C语言数据结构S.top

  删除栈顶元素的操作bool Pop_Sq(SqStack &S,SElemType &e){//若栈不空, 则用e返回栈顶元素, 并返回TRUE, 否则, 返回FALSEif(S t1)tFALSEif(S.top==-1) return FALSE;e=S.elem[S.top--];return TRUE;}// Pop_Sq1.顺序栈11 复杂度为O(1)

 执行后S tS.top例:

 删除栈顶元素的过程1.顺序栈12C语言数据结构C语言S.tope=“数据结构”

  顺序栈在使用时受到最大空间容量的限制, 在当前栈已满并需要加入新的数据元素的情况下, 需要追加存储空间。

 这是顺序栈在使用时的一个弱点。 下面将介绍栈的另一种存储结构——链栈2.链栈13 链栈是用链表结构来表示和实现的栈。

 链栈的结点结构与链表的结点结构相同, 包括数据域和指针域两部分。

 其中, 存储数据元素本身的域称为数据域,存储直接后继元素的存储位置的域称为指针域。 链栈中的多个结点通过指针链接起来, 并设一指向栈顶元素的指针——栈顶指针。

 datanext栈顶2.链栈typedef struct LNode{ElemTypestruct LNode *next;}LNode,* LinkList;Typedef Linklist LinkStack;若S为LinkStack类型的变量,则S是栈顶指针。

 若S=NULL,则表示该链栈为空data;栈的链式存储描述:s14…^栈底

  链栈的基本操作 void InitStack_L(LinkStack &S){//构造一空栈S=NULL;}//InitStack L}//InitStack_L void push_L(LinkStack &S,Elemtype e){//将新元素e插入链栈Sp=new

 LNode;//分配新结点p->data=e; p->next=S;S=p;//修改栈顶指针} push_L

 2.链栈15

 2.链栈• 假设一链栈S的状态如图所示; 现要插入一元素e作为S的新栈顶元素。3SSS1657^epS

  bool Pop_L(LinkStack &S,ElemType &e) {//若栈不为空, 用e返回栈顶元素的值, 并删除之 if(S) {2.链栈17 p=S;S=S->next;//修改栈顶指针e=p->data;delete p;//释放结点空间return TRUE; }//if else return FALSE; }// Pop_L

 2.链栈S7733p185^57^Se=3

 4.2 栈的应用举例 例4.1:

 将一个非负的十进制数转换为八进制数的问题。{//InitStack(S);While(N)的八进制数应是对十进制数除8取余的逆序,符合栈LIFO的特点, 可以用栈来实现。While(!StackEmpty){Pop(S,e);cout<<e;}//while}//conversion 根据十进制与八进制之间的转换关系, 对应的八进制数应是对十进制数除8取余的逆序,{push(S,N%8);N=N/8;}//whileVoid conversion( int N)19( )请同学们思考该算法的时间复杂度?

  例4.2:

 假设某表达式中允许使用两种括号:

 圆括号和方括号, 设计一算法对表达式中的括号是否匹配进行检验。 分析:

 从左向右扫描表达式, 假设出现的括号排列情况是:[1 (2[3]4)356。与第6个匹配, 然而紧随其后的却是第2个括号, 这时它又期待与第2个括号匹配的第5个括号的出现, 依次类推, 最后一个读取的括号需要匹配的紧急程度最高。 括号匹配的处理过程与栈的特点相吻合, 可以用栈来实现。 基本思想:

 从左向右扫描表达式, 并设置一个栈, 若是左括号则压入栈中; 若是右括号, 如果它能与当前栈顶元素相匹配, 则删除栈顶元素, 继续下一次扫描, 如果不能与栈顶元素匹配, 则认为当前表达式括号匹配不正确而返回。5]6。根据括号的匹配规则, 第1个括号期待4.2 栈的应用举例20

 Bool matching(char exp[]){//检验括号嵌套是否正确, ‘#’为表达式结束符int state=1;ch=*exp++;While(ch!=‘#’&&state){switch of ch{

  case ‘[’| |

 ‘(‘:{push(S,ch);break;case’)’:{if(!StackEmpty(S) && GetTop(S)=‘(‘)pop(S,e);else state=0;bk }break;}case’]’:{if(!StackEmpty(S)&&GetTop(S)=‘[‘)pop(S,e);else state=0;break;}}//switchch=*exp++;}//whileif(state&&StackEmpty(S)) return TRUEelse return FALSE;}//matching21O(n)

  例4.3 背包问题求解。

 假设一个总体积为T的背包和n件物品, 每件物品的体积为wi(1≤i≤n)

 。

 现从n件物品中任选若干件使他们的体积之和正好T, 要求求出所有满足条件的解。若T=10, W[]={1, 8, 4, 3, 5, 2}按照物品的编号依依次将满足条件的物品放入背包中, 物品编号从0开始。4.2 栈的应用举例2201 8 8 23501 8 12043 04205…解2解1

 4.2 栈的应用举例 Void knapsack(int w[],int T,int n) {//w[0]至w[n-1]存放n件物品的体积, T为背包的总体积 Initstack(S);k=0;//k为物品编号 do{{ Whlie(T>0&&k<n){if(T-w[k]>=0){push(S,k);T-=w[k];}//ifk++;}//while23 if(T==0)StackTraverse(S); pop(S,k);T+=w[k]; k++; }//while(!(StackEmpty(S)&&k==n)); }//knapsack

  例4.4

 表达式求值。 表达式::操作数 运算符 操作数 操作数::简单变量| 表达式 表达式有三种不同的表示方法:4.2 栈的应用举例24 前缀表示方法:

 OP S1 S2 中缀表示方法:

 S1 OP S2 后缀表示方法:

 S1 S2 OP前缀表达式为:

 +*ab*-c/def中缀表达式:

 a*b+(c-d/e)*f后缀表达式为:

 ab*cde/-f*+前缀表达式和后缀表达式包含了 确定的运算顺序, 而中缀表达式的运算顺序很多情况下需要借助于括号来确定。

 如在后缀表达式中, 每个运算符和在其之前出现两个操作数构成一个最小表达式。

  后缀表达式的计算4.2 栈的应用举例 后缀表达式是无括号的表达式, 计算时不需要考虑运算符的优先级, 只需设置一操作数栈 后缀表达式计算时读取的方向为从左至右后缀表达式的计算步骤: 后缀表达式的计算步骤:251.建立操作数栈, 初始化为空;2.若表达式未读取完, 则从左至右读取表达式中的一运算单元;3.若是操作数, 直接进栈;4.若是运算符, 则从操作数栈中弹出两个操作数进行运算,并将结果压入栈中。5.重复2~4, 直到表达式读取完, 最后的栈顶元素即为计算结果。

 例:

 计算ABC/D- +空操作数栈读AAA读CBAC读“/”B/CA读DB/CAD4.2 栈的应用举例26读BBA读“-”B/C-DA读“+”A+B/C-D计算结果请大家阅读教材P72算法4.4

 将中缀表达式转换为后缀表达式(规则)1.建立运算符栈2.设表达式的结束符和运算符栈的栈底为‘#’3.从左向右读表达式(1)

 若读取的是操作数, 直接输出到后缀表达式;(2)

 若读取的是‘(’直接进栈(2)

 若读取的是‘(’ , 直接进栈(3)

 若读取的是‘)

 ’, 输出栈顶运算符到后缀表达式, 直到弹出‘(’ 为(4)

 若读取的是非括号运算符, 将之与栈顶运算符进行比较:

 若比栈顶运算符的优先数高, 则直接进栈; 否则将栈顶运算符发送到到后缀表达式,再继续比较, 直到栈为空或栈顶元素的优先级低于当前读取的运算符。4.若表达式未读取完, 重复3; 若表达式读取完, 而栈非空, 则依次将栈中运算符发送给后缀表达式, 直到栈空。4.2 栈的应用举例27

  将a+(b+(c/d-e))*f #转换成后缀表达式4.2 栈的应用举例a + ( b + ( c / d - e ) ) * f #读取的操作单元运算符#(+-)/^优先级-101122328#a+b(*+c(d // -e - +f * + #后缀表达式操作符栈程序代码参见教材P73算法4.5

  例4.5 栈在递归函数的应用 递归函数的运行是函数自己对自己的调用, 调用函数与被调用函数之间的链接和信息交换一般是由编译系统通过栈来实现的。

 栈中保存的信息主要包括:返回地址4.2 栈的应用举例29 返回地址; 函数被调用时所有局部变量的值以及传值形式参数的值; 所有引用参数及常量引用参数的定义。

  用递归解决问题的一般步骤: 确定递归结束的条件; 定义递归的执行部分。例例:4.2 栈的应用举例301,若n<=1

 //结束条件f(n)=nf(n-1) , 若n>1 //执行部分

  设函数Ackerman的定义如下:4.2 栈的应用举例x+1,

  n=0;x,x,

  n=1,y=0;n=1,y=0;31 A(n,x,y)

 =

  0,

 n=2,y=0;1,

  n=3,y=0;2,

  n≥4,y=0;A(n-1,A(n,x,y-1),x)

 , n≠0,y≠0 当n和y均不等于0时, 该函数的执行是一个递归调用的过程

  请看A(3,2,1)

 计算过程中栈的部分内容的变化情况。A(n-1,A(n,x,y-1),x)

 ,

  n≠0,y≠0 4.2 栈的应用举例 A(n,x,y)

 =

  0,

  n=2,y=0;A( 3,2,1)

  1,

  n=3,y=0;2,

  n≥4,y=0;x+1,

  n=0;x,

  n=1,y=0;323,2,13,2,02,1,22,1,12,1,02,1,21,0,11,0,02,1,20,0,01,1,11,1,00,1,1

  例4.5非递归算法的代码分析(用栈实现)栈的元素类型定义:Typedef struct{i tlint nval;int xval;int yval;}ElemType;Pop(S,e); e.nval--;e.yval=e.xval; e.xval=u;

  Push(S,e);}//if}//while(!StackEmpty(S))}// Aackerman4.2 栈的应用举例int Aackerman (int n,int x,int y){//用栈S求Aackerman函数的值InitStack(S);e.nval=n;e.xval=x;e.yval=y;push(S,e);do{GetTop(S,e);while(e.nval!=0&&e.yval!=0){e.yval--; Push(S,e); }//whilee.yval; Push(S,e); }//whilePop(S,e);u=value(e.nval,e.xval,e.yval)

  ;if(! StackEmpty (S)){33

 4.2 栈的应用举例 N皇后问题(递归回溯)将N个皇后放到一个N× N的棋盘上, 皇后的走向范围包括上、 下、 左、 右、 左上、 右上、 左下和右下八个方向,任意两个皇后不能放在同一行、 或同一列、 或同一对角线上。

 求放置N个皇后的方法解。34

 假设N=40

 1

 2

 3011第一个皇后第二个皇后第三个皇后无法继续走无法继续走, 回溯到第二个皇后的位置回溯到N皇后问题3523

 N皇后问题第二个皇后寻找新的位置寻找位置寻找位置第三个皇后第四个皇后0

 1

 2

 30113623第四个皇后无位置回溯第三个皇后

 N皇后问题0

 1

 2

 30

 1

 2

 3001111第三个皇后无法继续回溯第二个皇后第三个皇后第四个皇后无法继续回溯第三个皇后寻第三个皇后寻无法继续回溯无法继续回溯寻找新位置到第二个皇后寻找新位置寻找新位置寻找...

篇三:,p:true,s:[

3

 产生 式表示法产生式的基本概念产生式的知识表示方法产生式系统的组成产生式系统的组成产生式系统的推理方式

 一、产生式基本概念例:1)

  如果 某种动物是哺乳动物, 并且吃肉, 那么 这种动物被称为食肉动物。P:该动物是哺乳∧ ∧该动物吃肉R:

 该动物是食肉动物P  R

 产生式:P

  R或IF

 PTHEN

 RR:

 后项它说明应用这条规则产生的操作、 结果P:

 前项它说明应用这条规则必须满足的条件;

 2)如果病人出现如打喷嚏, 咳嗽等症状 , 则 该病人感冒了。前提条件前提条件◆ P1

 ◆ P2

 打喷嚏咳嗽结论Q:该病人感冒P1 ∧ ∧ P2  Q

 3)x-1 > 1 ∧ null (y) => x:= 04)

 文法分析语言学的一个重要问题就是判定一个符号序列是否合法句符号序列是否合法句, 称为文法分析。文法分析可用产生式系统加以解决,下面就以英语为例。S, N, NP, P, PP, V, VP, DET称为文法分析

 一组重写规则作为产生式规则:N  NP /名词就是名词词组;DET NP  NP /冠词加名词词组还是名词词组;P NP PP /介词加名词词组构成介词词组;NP PP  NP /名词词组后跟介词词组仍是名词词组;V NP PP  VP /动词词组后跟名词词组和介词词组构成谓语;NP VP  S /名词词组与谓语一起构成句子;

 二、产生式系统的知识表示方法

 1 (AGE ZHAOLING

  43)2(FATHER ZHAOLYIN

  TRUE)例1 ZHAOLING

  IS 43.2ZHAOLYIN

 IS FATHER.1)

 、 确定性事实表示三元组表示 〈特性 对象 取值〉4(DOSEDRUG

  2.0 GRAMS)5(MANZHAOLING

  TRUE)6(WOMAN ZHAOLING

  FASE)

 4DRUG

 DOSE IS 2.0 GRAMS.5ZHAOLING IS

 MAN.6ZHAOLING ISN’T WOMAN.

 2)

 、 确定性规则知识的产生式表示IF

 P

 THEN

  Q 或者例: IF

 动物会飞 AND 会下蛋 THEN

 该动物是鸟。其中其中,前提(FLY

 X

  TRUE)

 ∧(EGG

 X

 TRUE)结论(BIRD X

 TRUE)P→Q,

 2014-11-189P→Q:(FLY

 X

  TRUE)

 ∧(EGG

 X

 TRUE)

 → (BIRD X

 TRUE)

 3)、 不完全事实的表示为了表示不完全的事实, 常需加入关于该事实确定性程度的数值度量。一般用四元组表示(属性,

 对象, 值, 置信度)

  或(关系 对象1 对象2 置信度)(关系,对象1,对象2,置信度)例1:1) ZHAOLING

  MAYBE 40

 。(AGE ZHAOLING

  40

 0.8)2) 老李和老张可能是朋友.(friend, li, zhang, 0.8)

 例2:MYCIN中用置信度来表示事实的可信程度。1)

  (细菌2菌属( IDENT )

 是连锁状球菌属( STRETOCOCCUS )

 的置信度为0.7)(IDENT ORGANISM2

  STRETOCOCCUS 0.7)2)

  (细菌2菌属( IDENT )

 是葡萄球( STAHYOCOCCUS )

 菌属的置信度为0.3)(IDENT ORGANISM2

  STAHYOCOCCUS 0.3)3)

  (细菌1的形态( MORH )

 为杆状形态的置信度是0.8)(MORH ORGANISM1

  ROD 0.8)4)

  (细菌1的形态( MORH )

 是球状( COCCUS )

 形态的置信度为0.2)(MORH ORGANISM1

  COCCUS 0.2)5) (细菌3革兰氏染色( GRAMSTAIN )

 为革兰氏阴性( GRAMNEG )置信度为1.0) (GRAMSTAIN ORGANISM3 GRAMNEG 1.0)

 4)、 不完全知识的表示为了表示不完全的知识, 常需加入关于该规则确定性程度的数值度量。基本形式是IF

 P

 THEN

  Q (置信度) 或者P→Q (置信度) 例 已知症状如下:E1:

 打喷嚏, E2:

 咳嗽。诊断结果:H1:

 可能感冒H2:

 另一种可能是花粉过敏IF E1 THEN H2(.50)

 。IF E1, E2 THEN H2(0.50)

 。

 例1: IF

 动物会飞 AND 会下蛋 THEN

 该动物可能是鸟。(FLY,

 X,

  TRUE)

 ∧(EGG,

 X,

 TRUE)

 → (BIRD, X,

 TRUE)

 (0.8)2014-11-1813

 例2:在专家系统MYCIN中有这样一条产生式:IF

  本微生物的染色斑是革兰氏阴性本微生物的形状呈杆状病人是中间宿主THEN

 该微生物是绿脓杆菌,置信度为0.6.它表示当前提中列出的各个条件都满足时 结论它表示当前提中列出的各个条件都满足时,结论“该微生物是绿生杆菌” 可以相信的程度为0.6 。

 三、产生式系统的组成

 例1R1

 R2

 R3依次使用该动物是人该动物会思考该动物有智慧

 产生式系统的的基本工作过程(1)

 初始化综合数据库。(2)

 检查规则库中是否存在尚未使用过的规则, 若有则执行(3)

 ;否则转(7)

 。(3)

 选择可与综合数据库中已知事实相匹配的规则; 如没有转(6)

 。(4)

 执行并标记当前选中规则, 把所得到的结论作为新事实放入综合数据库; 如果该规则的结论是一些操作, 则执行这些操作。(5)

 检查综合数据库中是否包含了 该问题的解, 如是, 问题求解结束;否则, 转(2)(6)

 当规则库中没有与综合数据库中的已有事实相匹配的规则时, 要求用户进一步提供关于该问题的已知事实求用户进一步提供关于该问题的已知事实, 若能提供, 则转(2)

 ;否则, 说明该问题无解, 终止问题求解过程。(7)

 若知识库中不再有未使用规则, 也说明该问题无解, 终止问题求解过程。若能提供则转(2)R1该动物是人R2 该动物会思考R3

 该动物有智慧该动物会劳动该动物脑部没毛病

 例2:设字符转换规则为:A∧B→CA∧C→DB B∧ ∧C→GB∧EB∧E→FD→EC→GF已知:

 A, B求:

 F

 分析:一、 数据库{x}, 其中x为字符二、 规则集1, IF

 A∧B

 THEN

 C2, IF

 A∧C

 THEN

 D3, IF

 B∧C

 THEN

 G4, IF

 B∧E

 THEN

 F5, IF

  D

  THEN

 E

 三、 控制策略顺序排队四、 初始数据{A, B}五结束条件五、 结束条件F∈{x}

 求解过程数据库可触发规则被触发规则A, B(1)(1)A, B, C(2)

 (3)(2)A, B, C, D(3)

 (5)(3)A, B, C, D, G(5)(5)A, B, C, D, G, E(4)(4)A, B, C, D, G, E, F1, IF

 A∧B

 THEN

 C

 3, IF

 B∧C

 THEN

 G 5, IF

  D

  THEN

 E2, IF

 A∧C

 THEN

 D4, IF

 B∧E

 THEN

 F

 例3:设综合数据库db的初始内容为集合{a,b,c}, 其中a、 b、 c均为字符;规则库包含以下三条插入双字符的规则:R1: ?(a

 b ∈ db) =>insert(db,"ab")R2: ?(a c ∈ db) =>insert(db,"ac")R2: ?(a

 c db) insert(db, ac )R3: ?(b

 c ∈ db) =>insert(db,"bc")推理的目标是使db成为:{a, b, c, ab, ac, bc}

 控制机制控制机制控制机制控制机制产生式系统:

 综合据库、 产生式规则和控制系统。或失败结束。控制策略作用说明下一步应该选用什么规则。产生式系统的控制机制就是不断地挑选可触发/激活的规则对综合数据库进行操作, 直至得到解答(综合数据库内容转变为描述了目标状态)

 ,通常从选择规则到执行操作分3步:1)匹配 2)

 冲突解决 3)

  操作规则库综合数据库寻找满足要求的事实寻找满足要求的规则改变综合数据库的事实

 冲突解决被触发的规则不一定总是启用规则。因为可能同时有几条规则的条件部分被满足。这就要在解决冲突中来解决这个问题。在复杂的情况下, 在数据库和规则的条件部分之间可能要进行近似匹配。

 两条美式足球规则R1:

 进攻一方如果在前三次进攻中前进的距离少于10码(short yardage), 那么在第四次进攻(fourth dawn)时, 可以踢悬空球(punt)。R2:

 如果进攻这一方, 在前三次进攻中,前进的距离少于10码, 而进攻的位置又在离对方球门线30码距离之内, 那么就可以射门(field goal)。

 专一性排序如果当前数据库包含事实“fourth dawn” 和“short yardage” 以及 “within 30 yards”, 则上述两条规则都被触发, 这就需要用冲突解决来决定首先使用哪一条规则。有很多种冲突解决策略, 其中一种策略是先使用规则R2, 因为R2的条件部分包括了更多的限制, 因此规定了一个更为特殊的情况。

 这是一种按专一性来编排顺序的策略, 称为专一性排序。如果某一规则条件部分规定的情况, 比另一规则条件部分规定的情况更有针对性, 则这条规则有较高的优先级。

 规则1:问:

 该动物有奶吗?是。结论:

 这种动物为哺乳动物。专一性排序规则2:问:

 该动物有奶吗?是。问:

 有蹄吗?是。结论:

 这种动物为有蹄动物。

 反例规则:

 如果该动物会飞, 并且会下蛋, 那么, 该动物是鸟。补充数据库:该动物有羽毛。

 四、产生式系统的推理方式

 • 1.

 正向推理• 2.

 逆向推理• 3.

 双向推理四、产生式系统的推理方式

 例1:

 (Mammal ?x)

 ∧ (Eat ?x Meat) (Carnivore ?x)IF(Mammal Dog) (Eat Dog Meat)THEN(Carnivore Dog )

 例2:

 文法分析问题 ( 正向推理)一组重写规则作为产生式规则:N  NP /名词就是名词词组;DET NP  NP /冠词加名词词组还是名词词组;P NPP NP PP /介词加名词词组构成介词词组;PP /介词加名词词组构成介词词组NP PP  NP /名词词组后跟介词词组仍是名词词组;V NP PP  VP /动词词组后跟名词词组和介词词组构成谓语;NP VP  S /名词词组与谓语一起构成句子;

 作文法分析的句子是:the boy plays football in the place.1)

 将该句子的所有单词先替换为语法词汇:DET

  N

  V

  N

  P

  DET

  N2)

 作进一步的替代为:NP V NP PPNP

  V

  NP

  PP3)

 通过激活规则去进行符号重写:NP

  VP4)

 最后, 综合数据库只剩下符号S(指示合法句)

 , 文法分析成功结束。

 • 例3 :

 区分动物( 逆向推理)机器人去逛动物园, 为帮助它区分其中的七种动物,给它存入了 如下几条产生式规则:p1:

 若动物有毛发, 则它是哺乳动物;若动物有奶p2:

 若动物有奶, 则它是哺乳动物;则它是哺乳动物p3:

 若动物有羽毛, 则它是鸟类;p4:

 若动物会飞且生蛋, 则它是鸟类;p5:

 若动物是哺乳动物且吃肉, 则它是食肉 动物;p6:

 若动物是哺乳动物且有犬齿, 有爪, 眼睛紧盯着前方, 则它是食肉动物;p7:

 若动物是哺乳动物且反刍食物, 则它是蹄类且是偶蹄动物;

 p8:

 若动物是哺乳类且有蹄, 则它是有蹄类;p9:

 若动物是食肉类, 黄褐色, 有黑的斑点, 则它是一只金钱豹;p10:

 若动物是食肉类, 黄褐色, 有黑色条纹, 则它是老虎;p11:

 若动物是有蹄类, 长腿, 长脖子, 有黄褐色暗斑点, 则它是长颈鹿;p12:

 若动物是有蹄类, 白色有黑条纹, 则它是斑马;p13:

 若动物是鸟, 不会飞, 长腿, 长脖子, 黑、 白色, 则它是驼鸟;p14:

 若动物是鸟, 不会飞, 会游泳, 黑、 白色, 则它是企鹅;p15:

 若动物是鸟, 善飞, 则它是信天翁。

 p8:

 若动物是哺乳类且有蹄, 则它是有蹄类;p9:

 若动物是食肉 类, 黄褐色, 有黑的斑点, 则它是一只金钱豹;p10:

 若动物是食肉类, 黄褐色, 有黑色条纹, 则它是老虎;p11:

 若动物是有蹄类, 长腿, 长脖子, 有黄褐色暗斑点, 则它是长颈鹿;p12:

 若动物是有蹄类, 白色有黑条纹, 则它是斑马;p13:

 若动物是鸟, 不会飞, 长腿, 长脖子, 黑、 白色, 则它是驼鸟;p14:

 若动物是鸟, 不会飞, 会游泳, 黑、 白色, 则它是企鹅;p14:

 若动物是鸟, 不会飞, 会游泳, 黑、 白色, 则它是企鹅;判断金钱豹的推理树有毛发黑斑点黄褐色吃肉食肉类哺乳类金钱豹1P5 P9Pp15:

 若动物是鸟, 善飞, 则它是信天翁。

 p8:

 若动物是哺乳类且有蹄, 则它是有蹄类;p9:

 若动物是食肉类, 黄褐色, 有黑的斑点, 则它是一只金钱豹;p10:

 若动物是食肉类, 黄褐色, 有黑色条纹, 则它是老虎;p11:

 若动物是有蹄类, 长腿, 长脖子, 有黄褐色暗斑点, 则它是长颈鹿;p12:

 若动物是有蹄类, 白色有黑条纹, 则它是斑马;p13:

 若动物是鸟, 不会飞, 长腿, 长脖子, 黑、 白色, 则它是驼鸟;p14:

 若动物是鸟, 不会飞, 会游泳, 黑、 白色, 则它是企鹅;p15:

 若动物是鸟, 善飞, 则它是信天翁。•哺乳、 有蹄是中间结果•网络中标识出 逻辑关系合取与析取

 小结• 1

 产生式由前项P和后项R两部分组成P RP R • 2

 产生式的表示1) 可用谓词逻辑、 符号和语言的形式表示事实及规则。

 谓词表示 :1)

  MAN(ZHAOLING)

  真值 T / F2)

 ¬ WOMAN(ZHAOLING) 真值 T / F3)

 FLY

 (X) ∧(EGG(

 X) → IS (X, BIRD)IF

 动物会飞 AND 会下蛋 THEN

 该动物可能是鸟。

 3

  产生式与蕴涵式产生式的特殊形式为蕴涵。—表示不精确知识 / 精确知识—进行不精确匹配 / 精确匹配—无真值 /

 有真值 T / F

 产生式应用实例

 例例1 1传教士与野人问题传教士与野人问题有N个传教士和N个野人要过河。

 约束条件:– 现在有一条船只能承载K个人(包括野人和传教士)

 , K<N。士)

 , K<N。– 在任何时刻, 如果有野人和传教士在一起(包括岸上与船上)

 , 必须要求传教士的人数多于或等于野人的人数。– 传教士和野人都可以撑船过河

 变量m

 传教士在左岸的实际人数变量c:

 野人在左岸的实际人数变量b:

 指示船是否在左岸(值1指示船在左岸, 否则为0)综合数据库:初始状态: (N, N, 1)初始状态: (N, N, 1)目标状态: (0, 0, 0)( m ,c , b)

 2)

 传教士与野人问题R(Sm,Sc):从右岸回到左岸的划船操作L(Sm,Sc):从左岸到右岸的划船操作规则库:例:L(1,0): IF(m, C ,b= 1)

 ∧ L(1,0)

  THEN( m-1, C , b= 0)约束条件为:Sm 、 S c

 分别是船上野人和传教士人数船上:

 Sm +S c <=KSm >= Sc

 左岸:m >= c右岸:N- m- Sm>=N- c- Sc

 传教士野人问题规则库(N=3, K=2)• if L10

  ∧ ( M ,C , B=1 )

  then ( M–1 , C ,

 B =0 ) • if L01∧ ( M ,C , B=1 )

  then ( M ,

 C–1 ,

 B =0 ) • if L11∧ ( M ,C , B=1 )

  then ( M–1 , C–1 ,

 B =0 ) • if L20∧ ( M ,C , B=1 )

  then ( M–2 , C ,

 B =0) • if L02∧ ( M ,C , B=1 )

  then ( M ,

  C–2 ,

 B =0 ) ()• if R10∧ ( M ,C , B=0 )

  then ( M+1 , C ,

  B=1) • if R01∧ ( M ,C , B=0 )

  then ( M ,

  C+1 , B =1 ) • if R11∧ ( M ,C , B=0 )

  then ( M+1 , C +1, B =1 ) • if R20∧ ( M ,C , B=0 )

  then ( M+2 , C ,

  B =1 ) • if R02∧ ( M ,C , B=0 )

  then ( M ,

 C +2,B =1) R1R2R3R4R5()• 指示推理成功结束(到达目标状态)

 的规则:m = 0 ∧ c = 0 ∧ b = 0 T halt();R6R7R8R9R10

 例2八数码游戏规则在3*3的方格棋盘上放置分别标语有数字的八张牌:1 1, , 2 2, , 3 3, , 4 4, , 5 5, , 6 6, , 7 7, ,初始状态为S0目标状...

篇四:,p:true,s:[

S使用F<"SN"SRaFSdtdtt%使用XPS%使用Fee新建一文件fee.ieaxaxx>MA SOP生成A SPA SP生成静态网页的多种方法StwstsclttttttOfFoapleta.a..生成si.=oo=x1W2WC=lhfnsSt=r=rlCetssee="i"ior=m.eeS,C.ae若该文件已存在则覆盖它rWtrevOebrj e.cMta(p"PSactrhi(p"tuidn0g3./ fFsiol.ehStyms"t)emObj ect")eraitteeT"e新文件已建立"xtFile(NewFile,True)rf这句话是使用Wt这句话是使用Wtsvsrereee.iLidrOtita.penetMeLe方法写入的。<aanidB2pTnarPeet>ax方法写入的。<a"ttB1hFr(i>"l"ued(0F3i/ flseo,.8h,tTmr"u)e)"打开成可以在结尾写入数据的文件LHTTP生成<"S"xxBBSDSSMM"Fdsoooo%使用Xe把下面的地址替换成你的首页的文件地址,mmooeieeyyA duiebbbbMt一定要用hllddtmttFFonmtj Sj Sj Sj SLxt..yyxffMiidcoottttHmtOSTTmssyllbtbbrrrrTlppeeelooFee.ij Sj SeeeeT=:enxx=,=i..SottaaaaPS/ / 开ndttNMClWCtnrrmmmm生成e头的绝对路径,"r不能写相对路径Gver.CreateObj ect("Microsoft.XMLHTTP")ET","http:/ / www.kinoko.name/ ud03/ ",False==oyrerlrBee....xBtFe=ioeyaaTMOWmyhiaftsatmmyoprltiltseeme.eneeoLRsgeTsopBosntsre(BBooddyyText,"gb2312")O.ibCnj erece(taB(to"edSTyceTrxeitxpFtti)ilneg(.sFeirlveeSry.sMtaepmPOabtj ehc(t""u)d03.htm"),True)"生成的html的文件名使用处理二进制数据sToBstr(strBody,CodeBase)=pdeiSeente==r13ver.CreateObj ect("A dodb.Stream")estrBody

 oooBosE%使用Xbbbyben>Mj Sj Sj Stj StdtttetoFrrrsrbueeeTej SnaaaoatcmmmBmrt...s.eiPTCtCaooyhrlmnspa=o=ierosnt=sbeoi2ej Son=0tt=rCeoadme.BRaesaedTextthingLHTTP批量生成<"dHFHIFFHDDsdsooDbDsoooooNH%<RRR%%使用Xitottiitootiebbiiiebbbbbet>%eee>Mmmrmellm_ U_ Urmtj Xj Xmnmtj A dj A dj A dj A dj A dxmLslilmeelrrUoommbFoooooootlHt_ T=_ T_ CNP_ TllrbblliibbSSSSSTre1elaae==lj Xj XHHnlj A dj A dtttttTUmTmamtm"D=mmttFeoorrrrrPrpopsehphoDllttiDSSeeeee批量生成l=3=s===t_ UoHHpplattaaaaa,"0Hi"SHtr_ Utt..etrrmmmmmI<"tdA retplrttosDaee.....tU需要生成的im=crm:&lpppea=aaTOWSCeLdlihvl/ / w"m>1_ T_ C"到3elassid,id,FileName,FilePath,Do_ Url,Html_ Temp0mp&"<LI>"ie_ Tw?vrewpe.m.=sMpk"_ "a&i&&pFnIIPiottalkeeteommhP._ C_ C(anll"taaa/ "hmss)&ess&"/ uii"<ddd\ "/ L0"&&I3W"F>/ iE.i"nBhltemN"a"m生成的hetml文件名d路径之后的IeDx.php""WEB路径=entommypralSndabe"(rG)vEeTr".,CsrteraUtrelO,bfj eaclts(e"Microsoft.XMLHTTP")j XmlHttp.responseBody=peivoSentese=(eTer1)(o(ver.CreateObj ect("A DODB.Stream")bF)iinlFeiFlielDeaPtaat)h,2_ Temp=Html_ Temp&"<UL>"ssspppooonnnssseee...WWWrrriiittteee((H""t成功生成文件"<m)BlR_ T>e"m)p

 A S大家都知道H站的网页数量增多搜索引擎收录的数量也可能多再加下提高网页的质量也意未着什么PT用标签替换的方法生成静态网页ML静态网页更容易被搜索引擎收录索引动态生成HTML网页也可使网呢我想大家也知道。为了这个我决定了改变之前网站建设,页动态生成的方法我比较喜欢用标签替换的方法成生网页。网页设计的方法,经过多翻的研究及思考对多种网标签替换法这是我个人理解的定义不知道别人怎么叫它的呵呵标签替换法就是在设计好了的网页模板中放入自已设定的标签然后用你需要显示出来的东东替换它。如模板文件1t<<<<<{<<在以上模板中我放入了两个标签{的代码这个模板我们保存在数据库表中ehht/ hb$/ bh$mteieoA rotSpmatadcdmitldldy_ Lylta>>e>>i>>eble>{$SiteName}</ title>st$}Name}网站名称和{$A rc_ List$}文章列表,再来看下面<dSFsrhrh{h数替换{scss%iiiestst$t$eoeemtlt.m.mSmA rtnttreerolclilcrncfsNPsp=l=t=_ Ls.os,aa=erorehi=cnoSmtsnsseNtsnln=iehe"(epamtoo=Ct==rs"e"SvetN我的第一个动态生成的HeeleaTrremmMv.cpeLect",网页"rr[)A rc_ List,fso,myFile,FilePath,html.et"Mae读取网页模板atmpepPo]abftj erhco(tm"(t/ h"etammdplot/ idanbbd.lerexe,.cchootrnmdnls,"e1)t,"1)lml$tsnrae&}heoec}r标签ie标签e(html,"{$SiteName}",SiteName)"用自定义的SiteName替换place(html,"{$A rc_ List$}",get_ A rcList())"用自定义的get_ A rcList()函ngtahtienOgbj ect("***ing.FileSystemObj ect")"创建文件系统对象

 SMMSsrrFdssrwsrwrsg%E以上的方法是不是很简单现在很多C用比较灵活只要你用心去设计一下你的系统以后网做一个网站只要设计模板就可以了。eyyeeeeuittshtseste>nMtFFttssnmrr.ir.n.rtMiiMfppcs1=ol1mdc=_ A ryllysoott="pe=oFeeFonnir"<ensvi..i=sso,"unotelWclneenserleo..gt=io=tweerftsnhrnt1seeoiid_ A roL"tnt(c.i关闭文件hge)LCnree(ahttemTle)x"t把hFtiml代码写入文件e(FilePath,True)"创建文件i""n释放系统文件对象<g"释放文件对象***language="j ava***">window.alert("文件生成成功了");</ ***>"ist()l"trn>sr1e{es&xll."tiee<scolttfi}T<i/ utll>e",urlfromA rc"><ahref="&rs("url")&">"&rs("Title")&"</ a></ li>"lrcoeLspielsatc=es(tsrtr,"{list}",Str1)dSF都是采用这种方法生成静态网页的这种方法使unctiona<hi改"""""""""FiimhFDs%pnp生成静态网页不用模板直接传参数读取asp文件sd=e5x0mulu="/ asp/ 00/ pro""""""""""修改这里为本系统所在相对目录以根据自己的程序修*函数名h作用生成静态页面hFfA rA r*uffutio*t*m*l*l*********************************************************参数tiirr*nmhlml_ UmllNC*cutulerleeao*tlm=mPlmNfmn*iuliua=uaret*o=mnlt"lmo-e*n"uduhhuem-n*h"le==t----t*ttuxiSt-----*mh=mnep---参数的名称数组-*le"udr:---H生成的H生成的HTTTMMMLLL模板(文件名(文件.a不包括.及扩展名s及扩展名)p源文件)存放的目录-*ln"lev/ / "-*(mtuxe对应参数的内容数组*muh&mr*ulemu.*lunulM*u=hlua*,"tu&p*h/ nm*tel*mwm*lsu*m/ "l*u"u*l默认生成的H=*uT"*,M/ h*FLt*i文件存放的目录m*l*e*N*a*m*e*,*f*i*l*e*f*r*o*m*,*A r*r*N*a*m*e*,*A r*r*C*o*n*t*e*n*t*)l/ ""默认HTML模板存放的目录hPtamtlhm(umluulu)&"\ "&FileName

 DiDfDnessoobSsooooosE%ofoooentebbieebbbbben>_ UI_ Ur_ Uxdrtj Xj Xnttj A dj A dj A dj A dj A dtdrsrirtiUommFooooooooFlA rl=l=r=1=DaDtDoyooo_ U(_ UU_ UrA rrbrlrlol&N&u&Ra"n"em?d&qe"("u)&A r&etA rrA rshrNrteNaN.namaServerVariables("SERVER_ NA ME")&htmlmulu&filefrommeme)e(0)&A rrContent(0)(i)&A rrContent(i)frbllibbSSSSSbulj XHHlj Xj A dtttttj A dn=mttemorrrrrocDlttDlSeeeeeStoHppaHtaaaaati_ Ut..ttrmmmmmrortosate.....enlppe=paTOWSCa=eno=mypralmSndbN=peivo=e"(j XoSentesnrG)mte=(eTeovEeTr".,csrteraUtrelO,bfj eaclts(e"Microsoft.XMLHTTP")lhr1)(o(tHivtnetgrp.responseBody.createObj ect("A DODB.Stream")bF)hiinlFeiFlielDeaPtaat)h,2ingA S下面的例子是将、i生成n<dHFHIFFHDDPnd%itottiitoo生成静态网页的方法deexx1..ahstpm?,iidn=d1e/ ixn2d.ehxt.ma,sipn?diedx=32./ ihntdme存在根目录下面x.asp?id=3/ 这三个动态页面分别mmrmellm_ U_ Uslilmeelrrt_ T=_ T_ CNP_ Tllre1elaae==UmTmamtm"Drpopsehphol=3=s===t_ U,"I<tUeLm>_ C"lassid,id,FileName,FilePath,Do_ Url,Html_ TempHi"SHtrtdIetplm=nrm:&lidvl/ / "R_ Temp&"<LI>"ee_ Txre".m&MpIa&tpFePimal_ CtelhPa(as"ts/ "hi)&d&"&"<"\ "/ L.&IhF>ti"ml"eNameequest.ServerVariables("SERVER_ NA ME")&"/ main/ index.asp"

 DsdsooDbDsoooooNH%<RRR%otiebbiiiebbbbbet>%eee>_ Urmtj Xj Xmnmtj A dj A dj A dj A dj A dxmrUoommbFoooooootllrbblliibbSSSSS=lj Xj XHHnlj A dj A dtttttD=mmttFeoorrrrroDllttiDSSeeeee_ UoHHpplattaaaaar_ Utt..etrrmmmmmlrttosDaee.....&lpppea=aaTOWSC"?Item_ Classid="&Item_ Classid=entommypralSndabe"(rG)vEeTr".,CsrteraUtrelO,bfj eaclts(e"Microsoft.XMLHTTP")j XmlHttp.responseBody=peivoSentese=(eTer1)(o(ver.CreateObj ect("A DODB.Stream")bF)iinlFeiFlielDeaPtaat)h,2_ Temp=Html_ Temp&"<UL>"ssspppooonnnssseee...WWWrrriiittteee((H""t成功生成文件"<m)BlR_ T>e"m)p非摸板生成静态页目前已经有很多生成hh成h由于代码比较短这里就不进行注释了<""dFddDdessctttmmmlll的新闻系统但是都是用的模板本函数实现把a代码保存成为一个h的新闻系统了。^st_ ^pm页面产生的l文件这样就没有必要改动原来的页面就可以轻松完成一个生%当目标页面的包含文件即#注意本文件一定要放在fiuiiiixeeoiimnmmmmettnnlhcetrmcfftceutxmesos=elngiep,,dofnuahoc_ srme=stdmcnoteeehgdr1的页面里边存在r指向的文件的同一目录下ieeesponse.End()的时候本程序有问题ut_ r_ etxceo_ cdoede(filename),content,fso,f,aspStart,aspEnd=Co="r.f"eO.apRteeenaOTdbeA lj exlcttF(i"lSec(rsieprtvienrg..mFaiplpeaStyhs(tfeimlOebnj eacmte")))

 fsssrrrcrrdsistceeelssraasrrrdehvatdsist.eeeeeeoeeoefemolxnoeeesseeeeoxubsmoefemcttt...n..lffrigptgpo=seglaelasno=notnoteo=nobttbttnerae=aehowelrrlritrc=ne=nnheat=.f=gigsr"ra"neeu\ <el\ <gx=e\ %ps\ !ptrue\ @le\ -[a^c\ %e](+c\ %o\ >n"tent,"")\ -\ s*\ #include\ s*file\ s*=\ s*\ ""([^\ ""]+)\ ""\ s*\ -\ -\ >"tmtpnsidott.ppt111wegcppmsm_ stetipmmpESr...hchrE_ ss.=te=cmrnros=teu(g=.n0eret)tex<e>c0utthee(ncontent)_ e.xree_ cpoldaec(em(.csounbtmeanttc,htemsp(_ s0t)r))dfo=santeigpioclntn=tda1glaldhfdront=r=noteei,==toe1tnobta=u"iMhtrihnni=gn"g^\ s*="=eraese_ r"niiwelrpxt"SdnRc=nSec&t(Seaf=tcovrctgsa"aodb(orEelrrdecan(x=sete&rstaptes>&"lpespEnd,content,"<%")+2ruepav"fSnosb"&ttnpc&"a,sErr"raenle"ts\ .dfp),pW+&l&cSr1"a"otite(.+)"hc"naue"trg("ethr&n,cevtahpb,silc"puar%E_ rcl\ >ntef"dc(oMdied=(content,aspEnd,aspStart-aspEnd-2),"""",""""""),)-+a2spStart-2)tmtpmsm_ ss.=t=cmrros=eu(r1n0e.t)1e<x>e0ctuhteen(tmp_ str).replace(tmp_ str,"hughchiu_ rtcode=hughchiu_ rtcode&"&m.submatches(0))

 eeelssealsseh"gEfdch"e"ae%lxnoeexsoeexu"enuiourxrsn>sidottepotteg"tdnmdgeeepdetipmmcSprrch&_ eFccehscs2fdfo=sotn=daonerto=thte=ihxiniengncSgotdre(&arsep.Ernedp,lcaocnet(etnmtp,_ s"t<r%,"")h+u2ghchiu_ rtcode=hughchiu_ rtcode&")eeocvxuto=cpuphu1=dhbenidrhototn=neic_ ccoeeinenmcno=urotnote_ rldiathxtfeoshiec&=npinco""ngod"<gde"%e&)"&"&&v""eb""xc&"err"cle&ofpvd&lbe"ac&hcr"uel%g(f\ >hrcehpilua_ rctec(oMdied=(content,aspEnd),"""",""""""),vbcrlf,"2html(filename)pus(sltl_ rece=iat.o.hoccWdWuneorerg(di)ihrete&ep"(l"ca"oc"de"e(&)rvebpclralcfe,("g"e)t,_ e"x<e%_ c"o,d"e"()f,i"l%e\ >n"a,m"e")),"hughchiu_ rtcode=tceh(ihuu_ rgthccohdieu_ rtcode)使用范例ssffss,ee..eefttWcttsffrlffos=io=softsno=seeo=CoLr.ieCnarete(eaaOtsbepj eT2cehtxt(tm"FlSi(cl"reyi(opsutepiranvggee.r.F.aimslapep"Sp)ya)stthe(m"Oyboj eucpta"g)e.htm"),true)tnhoitnhging可见虽然是新方法还是需要的支持

 下面代码可以帮您生成静态页面如l面你的域名是fiReReOilfelennsySsssdEtsapepir.ovoa.ensnFspeie是读数据库的页面要生在ltl.i可以用下面代码使用方法st.html静态页ew(r"i/ httem"l已生成"/ list.html","http:/ / www.flyso.net/ list.asp")thenofrnse.write"没有生成"如生成失败请把代码orResumeNext封了查看具体错误信息代码如下程序代码<iReRefDOSW..GESSW......ESiSeeS%felenuineiOSeneeiTOWSCCnefarlaSsssdnmEttpetdtttypraaldtevrsvapepicA drRhenRWRA dhpeivnoWA dre.eevoenFsiel.ew(r"i/ httem"l已生成"/ list.html","http:/ / www.flyso.net/ list.asp")thenoftsreRndeiesA dentecsisrFcnse.write"没有生成"i,ote"oRrrtGneRireSteeitarsve"viuav,eemlaRFve=leiaNSlleee,xr(GtvLeotcRaelmFoitleeDNaatmae,RemoteFileUrl)er.CreateObj ect("Microso"&"ft.XM"&"LHTTP")moteFileUrl,False,"",""mtt=s=ohrSteData=.ResponseBodyieervvaelr=.NCortehaitnegObj ect("A do"&"db.Str"&"eam")1eTeet=<ilGol(hn>leeF()ti)RleemSoetrevDeart.aMapPath(LocalFileName),2o0eatt=rhhfieannlgseFile=true

 eE%nn>ddiffunctionA S新闻系统、b从而减轻服务器的压力本文为大家搜集整理了A S有使用f1<"SN"SRaFSdtdtt%2<"S"PlPs.%使用Fee新建一文件fee...

篇五:,p:true,s:[

科技大学计算机学院(1 1 )数据结构2006-- 9 --1

 2、 动态查找表• 特点:

 用于频繁进行插入、 删除、 查找的所谓动态查找表。• 二叉分类树:

 空或有一个根, 根的左子树若非空, 则左子树上的所有结点的关键字值均小于根结点的值。

 根的右子树若非空, 则右子树上的所有结点的关键字值均大于根结点的值。

 根结点的左右子树同样是二叉分类树。122e、 g:

 二叉分类树L25030011020099NPEMCY105230216

 2、 动态查找表1、 分割式查找法:查找步骤:

 若根结点的关键字值等于查找的关键字, 成功。否则, 若小于根结点的关键字值, 查其左子树。若大于根结点的关键字值, 查其右子树。在左右子树上的操作类似。12225030030011011020020099Bitree SearchBST ( BiTree T,

 KeyType key )// 在二叉分类树查找关键字之值为 key 的结点, 找到返回该结// 点的地址// 点的地址, 否则返回空。

 T 为二叉分类树的根结点的地址。否则返回空T 为二叉分类树的根结点的地址105230216{ if

 ( ( !T) ||

 EQ( key, T ->data. key ) ) return ( T ) ;else if ( LT( key , T ->data. key ) ) return (SearchBST ( T -> lchild, key ));else return (SearchBST ( T -> rchild, key )); } // SearchBST

 2、 动态查找表2、 插入算法:• 首先执行查找算法, 找出被插结点的父亲结点。• 判断被插结点是其父亲结点的左、 右儿子。

 将被插结点作为叶子结点插入。• 若二叉树为空。

 则首先单独生成根结点。注意:

 新插入的结点总是叶子结点。e、 g:

 将数的序列:

 122、 99、 250、 110、 300、 280 作为二叉分类树的结点的关键字值, 生成二叉分类树。

 2、 动态查找表2、 插入算法:• 首先执行查找算法, 找出被插结点的父亲结点。• 判断被插结点是其父亲结点的左、 右儿子。

 将被插结点作为叶子结点插入。• 若二叉树为空。

 则首先单独生成根结点。注意:

 新插入的结点总是叶子结点。e、 g:

 将数的序列:

 122、 99、 250、 110、 300、 280 作为二叉分类树的结点的关键字值, 生成二叉分类树。122

 2、 动态查找表2、 插入算法:• 首先执行查找算法, 找出被插结点的父亲结点。• 判断被插结点是其父亲结点的左、 右儿子。

 将被插结点作为叶子结点插入。• 若二叉树为空。

 则首先单独生成根结点。注意:

 新插入的结点总是叶子结点。e、 g:

 将数的序列:

 122、 99、 250、 110、 300、 280 作为二叉分类树的结点的关键字值, 生成二叉分类树。12212299

 2、 动态查找表2、 插入算法:• 首先执行查找算法, 找出被插结点的父亲结点。• 判断被插结点是其父亲结点的左、 右儿子。

 将被插结点作为叶子结点插入。• 若二叉树为空。

 则首先单独生成根结点。注意:

 新插入的结点总是叶子结点。e、 g:

 将数的序列:

 122、 99、 250、 110、 300、 280 作为二叉分类树的结点的关键字值, 生成二叉分类树。1221229912225099

 2、 动态查找表2、 插入算法:• 首先执行查找算法, 找出被插结点的父亲结点。• 判断被插结点是其父亲结点的左、 右儿子。

 将被插结点作为叶子结点插入。• 若二叉树为空。

 则首先单独生成根结点。注意:

 新插入的结点总是叶子结点。e、 g:

 将数的序列:

 122、 99、 250、 110、 300、 280 作为二叉分类树的结点的关键字值, 生成二叉分类树。122122991222509912225011099

 2、 动态查找表2、 插入算法:• 首先执行查找算法, 找出被插结点的父亲结点。• 判断被插结点是其父亲结点的左、 右儿子。

 将被插结点作为叶子结点插入。• 若二叉树为空。

 则首先单独生成根结点。注意:

 新插入的结点总是叶子结点。e、 g:

 将数的序列:

 122、 99、 250、 110、 300、 280 作为二叉分类树的结点的关键字值, 生成二叉分类树。12212299122250991222501109912225030011099

 2、 动态查找表2、 插入算法:• 首先执行查找算法, 找出被插结点的父亲结点。• 判断被插结点是其父亲结点的左、 右儿子。

 将被插结点作为叶子结点插入。• 若二叉树为空。

 则首先单独生成根结点。注意:

 新插入的结点总是叶子结点。e、 g:

 将数的序列:

 122、 99、 250、 110、 300、 280 作为二叉分类树的结点的关键字值, 生成二叉分类树。1222503001102809912212299122250991222501109912225030011099

 2、 动态查找表2、 插入算法:Status SearchBST ( BiTree T, KeyType key,BiTree f, BiTree &p )// 在二叉分类树查找关键字之值为 key 的结点。

 初始时 f

 为 NULL。

 如树空, 返回//

 p 为 NULL及 FALSE。

 如树非空且查找成功, 返回 p = T 及 TRUE。//

 如树非空且查不成功, 返回 p = f 及 FALSE。

 f 为待插入结点的的父亲结点的//

 地址。{ if

 ( ( !T)

 { p = f; return FALSE; }• 程序实现:else if ( EQ( key, T ->data. key ) ) { p = T; return TRUE; }else if ( LT( key , T ->data. key ) ) return (SearchBST ( T -> lchild, key, T, p ));else return (SearchBST ( T -> rchild, key , T, p )); } // SearchBST12225030011099Tpf:nullf: T 的父亲结点p: 指向最后一个结点,TRUE 找到; FALSE 叶子的父亲结点。

 如:

 插入280 的过程。280

 2、 动态查找表2、 插入算法:• 执行实例:

 插入值为 280 的结点12225030030011011099Tf:

 null12225030030011011099fTKey=28012225030011099fTKey=280f12225030011099T:nullKey=280p12225030011099280

 2、 动态查找表2、 插入算法:Status Inset BST ( BiTree &T, Element e )// 在二叉分类树中不存在 e.key 时, 插入并返回 TRUE, 否则返回 FALSE。{

 if

 (

 ! SearchBST ( T, e.key, NULL, p ) { s = ( Bitree ) malloc ( sizeof ( BitNode ) ); s->data = e; s->lchild = s->rchild = NULL;if

 ( ! p )

 T = s;else if ( LT( e.key , p ->data. key ) ) p -> lchild = s;else p -> rchild = s; return TRUE;• 程序实现:;}return FALSE;

 }

 // Insert BST12225030011099Tpf: T 的父亲结点p: 指向最后一个结点,TRUE 找到; FALSE 叶子的父亲结点。

 如:

 插入280 的过程。280f:null

 2、 动态查找表6020503、 二叉分类树的查找分析•平均情况分析(在成功查找两种的情况下)e.g: 下述两种情况下的成功的平均查找长度 ASL152015703060703050ASL=(1+2+2+3+3+3)/6=14/6ASL=(1+2+3+4+5+6)/6=21/6

 2、 动态查找表3、 二叉分类树的查找分析•平均情况分析(在成功查找两种的情况下)在一般情况下, 设 P(n, i)

 且它的左子树的结点个数为 i 时的平均查找长度。

 右图的结点个数为 n = 6 且 i = 3; 则P(n,i)

 = P(6, 3)

 =

 [ 1+ ( P(3) + 1) * 3 + ( P(2) + 1) * 2 ] / 6=

 [ 1+ ( 5/3 + 1) * 3 + ( 3/2 + 1) * 2 ] / 6注意:

 这里 P(3)、 P(2) 是具有 3 个结点、 2 个结点的二叉分类树的平均查找长度。

 在一般情况下, P(i)

 为具有 i 个结点二叉分类树的平均查找50长度。P(3) = (1+2+2)

 / 3 = 5/3P(2) = (1+2)

 / 2 = 3/2∴ P(n,i)

 = [ 1+ ( P(i) + 1) * i + ( P(n-i-1) + 1) * (n-i-1) ] / n∴n-1P(n)

 =

 ∑ P(n,i)

 / ni=0= 1.465log2n 1560703020左子树0到n-1个结点右子树n-1到0个结点

 2、 动态查找表4、 二叉分类树的删除操作•叶子结点:

 直接删除, 更改它的父亲结点的相应指针场为空。

 如:

 删除数据场为 15、 70 的结点。15607030205060302050•子树的根结点:

 通常的做法:

 选取“替身” 取代被删结点。

 有资格充当该替身的是谁哪?左子树中最大的结点 或 右子树中最小的结点, 参看下图。要点:

 维持二叉分类树的特性不变。

 在中序周游中紧靠着被删结点的结点才有资格作为“替身” 。

 2、 动态查找表4、 二叉分类树的删除操作122122400450450•子树的根结点:

 若被删结点的左儿子为空或者右儿子为空。如下图所示, 删除结点的数据场为 99 、 200 的结点。122122400450删除9925030011020099105230216500被删结点250300200230216500110105

 2、 动态查找表4、 二叉分类树的删除操作122122400450450•子树的根结点:

 若被删结点的左儿子为空或者右儿子为空。如下图所示, 删除结点的数据场为 99 、 200 的结点。122122400450删除20025030011020099105230216500被删结点25030023021650011099105

 2、 动态查找表4、 二叉分类树的删除操作122122400450450•子树的根结点:

 若被删结点的左儿子为空或者右儿子为空。如下图所示, 删除结点的数据场为 99 、 200 的结点。25030011020099105230216500被删结点结论:

 ·将被删结点的另一儿子作为它的父亲结点的儿子, 究竟是作为左儿子还是右儿子依原替身结点和其父亲结点的关系而定。·释放被删结点的空间。被删结点

 2、 动态查找表4、 二叉分类树的删除操作•子树的根结点:

 若被删结点的左、 右子树皆不空, 则:通常的做法:

 选取“替身” 取代被删结点。

 有资格充当该替身的是谁哪?左子树中最大的结点(被删结点的左子树中的最右的结点, 其右儿子指针场为空) 或 右子树中最小的结点(被删结点的右子树中的最左的结点, 其左儿子指针场为空) , 参看下图。要点:

 维持二叉分类树的特性不变。

 在中序周游中紧靠着被删 结点的结点才有资格作为“替身” 。400被删结点40012225030011020099105230216450500替身替身11025030010520099230216450500做法:

 将替身的数据场复制到被删结点的数据场。将结点的左儿子作为的父结点的右儿子。11011099注意:

 结点右儿子必为空结点的父结点为11011099

 2、 动态查找表4、 二叉分类树的删除操作•子树的根结点:

 若被删结点的左、 右子树皆不空, 则:400被删结点400通常的做法:

 选取“替身” 取代被删结点。

 有资格充当该替身的是谁哪?左子树中最大的结点(被删结点的左子树中的最右的结点, 其右儿子指针场为空) 或 右子树中最小的结点(被删结点的右子树中的最左的结点, 其左儿子指针场为空) , 参看下图。要点:

 维持二叉分类树的特性不变。

 在中序周游中紧靠着被删 结点的结点才有资格作为“替身” 。12225030011020099105230216450500替身替身20025030011099105230216450500做法:

 将替身的数据场复制到被删结点的数据场。将结点的右儿子作为的父结点的左儿子。注意:

 结点左儿子必为空结点的父结点为200200200200250

 2、 动态查找表4、 二叉分类树的删除操作•子树的根结点:

 若被删结点的左、 右子树皆不空, 则:400被删结点通常的做法:

 选取“替身” 取代被删结点。

 有资格充当该替身的是谁哪?左子树中最大的结点(被删结点的左子树中的最右的结点, 其右儿子指针场为空) 或 右子树中最小的结点(被删结点的右子树中的最左的结点, 其左儿子指针场为空) , 参看下图。要点:

 维持二叉分类树的特性不变。

 在中序周游中紧靠着被删 结点的结点才有资格作为“替身” 。12225030011020099105230216450500替身替身结论:

 ·先将替身的数据场复制到被删结点·将原替身的另一儿子作为它的父亲结点的儿子, 究竟是作为左儿子还是右儿子依原替身结点和其父亲结点的关系而定。·释放原替身结点的空间。

 2、 动态查找表F被删结点4、 二叉分类树的删除操作PPRPLF被删结点FFFFPR•PL、 PR皆 空,直接删除 。•PL或PR为空,•PL为空, 删除后的情况。PCCLPRQQLSSLSCCLPRQQLSLCCLPRQQLSSL1.删除法2.删除法

 2、 动态查找表Status DeleteBST ( BiTree &T, KeyType key )// 若二叉分类树 T 中存在关键字为 key 的结点时, 则删除该结点, 并返回 TRUE;// 否则返回 FALSE。{ if ( ( !T){ if

 ( ( !T)

 return FALSE;

 // 二叉分类树 T 中不存在关键字为 key 的结点tFALSE// 二叉分类树 T 中不存在关键字为 k的结点• 程序实现:4、 二叉分类树的删除操作else if ( EQ( key, T ->data. key ) ) Delete (T); // 存在关键字为 key 的结点, 进行删除else if ( LT( key , T ->data. key ) ) DeleteBST ( T -> lchild, key );else DeleteBST ( T -> rchild, key ); return TRUE;} // DeleteBST

 2、 动态查找表Status Delete ( BiTree &p )// 在二叉分类树中删除地址为 p 的结点, 并保持二叉分类树的性质不变。{ if

 ( ! p-> rchild )

 { q = p; p =

 p->lchild ; free(q); }else if ( ! p-> lchild ) { q = p; p =

 p->rchild ; free(q); }else { q = p; s = p-> lchild;{ qp;• 程序实现:4、 二叉分类树的删除操作p;while ( s->rchildn ) { q = s; s = s->rchild; }p->data = s->data;if ( q != p ) q->lchild = s->rchild;else q->lchild = s->lchild;free(s);

  }} // DeleteBST注意:

 删除根结点而相应的二叉树没有另增的头结点的情况。

 DGG2、 动态查找表EDDABCBB5、 平衡二叉分类树• 起因:

 提高查找速度, 避免最坏情况出现。

 如右图情况的出现。虽然丰满树的树型最好, 但构造困难。

 常使用平衡树。CFFEGA• 平衡因子(平衡度)

 :

 结点的平衡度是结点的左子树的高度-右子树的高度。• 平衡二叉树:

 每个结点的平衡因子都为 +1、 -1、 0 的二叉树。

 或者说每个结点的左右子树的高度最多差一的二叉树。•注意:

 丰满树必为平衡树, 平衡树不一定是丰满树。

 2、 动态查找表5、 平衡二叉分类树• 平衡因子(平衡度)

 :

 结点的平衡度是结点的左子树的高度-右子树的高度。• 平衡二叉树:

 每个结点的平衡因子都为 +1、 -1、 0 的二叉树。

 或者说每...

篇六:,p:true,s:[

验题目 实现单链表各种基本运算的算法 小组合作 无 姓名

 班级

 学

 号

 一、 实验目的

 领会单链表存储结构和掌握单链表中各种基本运算算法设计 二.实验环境 Miscroft

 Visual

 C++6.0 环境。

 三.实验内容与步骤 . 1. 编写 linkp list.cpp 程序包含有关 单链 表运算算法

 . 2. 编写 exp2- -p 2.cpp 程序包含有关程序代码

 . 3. 运行程序 exp2- - 2.cpp ,得到结果

 四、实验过程与分析 //单链表运算算法 #include <stdio.h> #include <malloc.h> typedef char ElemType; typedef struct LNode a {

 ElemType data;

 struct LNode *next;

  //指向后继结点

 } LinkNode;

  //单链表结点类型 void CreateListF(LinkNode *&L,ElemType a[],int n)

 //头插法建立单链表

  {

 LinkNode *s;

 L=(LinkNode *)malloc(sizeof(LinkNode));

 //创建头结点

 L->next=NULL;

 for (int i=0;i<n;i++)

 {

 s=(LinkNode *)malloc(sizeof(LinkNode));

 //创建新结点 s

  s->data=a[i];

  s->next=L->next;

 //将结点 s 插在原开始结点之前,头结点之后

  L->next=s;

 } } void CreateListR(LinkNode *&L,ElemType a[],int n)

 //尾插法建立单链表 {

  LinkNode *s,*r;

 L=(LinkNode *)malloc(sizeof(LinkNode));

 //创建头结点

 L->next=NULL;

 r=L;

  //r 始终指向尾结点,开始时指向头结点

 for (int i=0;i<n;i++)

 {

 s=(LinkNode *)malloc(sizeof(LinkNode));

 //创建新结点 s

  s->data=a[i];

  r->next=s;

  //将结点 s 插入 r 结点之后

  r=s;

 }

 r->next=NULL;

  //尾结点 next 域置为 NULL }

  实验截图(1)

 void InitList(LinkNode *&L)

  //初始化线性表 {

 L=(LinkNode *)malloc(sizeof(LinkNode));

 //创建头结点

 L->next=NULL;

  //单链表置为空表 } void DestroyList(LinkNode *&L)

 //销毁线性表 {

 LinkNode *pre=L,*p=pre->next;

  while (p!=NULL)

 { free(pre);

  pre=p;

 //pre、p 同步后移一个结点

 p=pre->next;

 }

 free(pre);

 //此时 p 为 NULL,pre 指向尾结点,释放它 } bool ListEmpty(LinkNode *L)

  //判线性表是否为空表 {

 return(L->next==NULL); } int ListLength(LinkNode *L)

  //求线性表的长度 { int i=0;

 LinkNode *p=L;

 //p 指向头结点,n 置为 0(即头结点的序号为 0)

 while (p->next!=NULL)

 { i++;

  p=p->next;

  }

 return(i);

 //循环结束,p 指向尾结点,其序号 i 为结点个数 } void DispList(LinkNode *L)

 //输出线性表 { LinkNode *p=L->next;

  //p 指向首结点

 while (p!=NULL)

  //p 不为 NULL,输出 p 结点的 data 域

 { printf("%c ",p->data);

  p=p->next;

  //p 移向下一个结点

 }

 printf("\n"); }

  实验截图(2)

 bool GetElem(LinkNode *L,int i,ElemType &e)

 //求线性表中第 i 个元素值 { int j=0;

 if (i<=0) return false;

  //i 错误返回假

 LinkNode *p=L;

  //p 指向头结点,j 置为 0(即头结点的序号为 0)

 while (j<i && p!=NULL)

  //找第 i 个结点 p

 { j++;

  p=p->next;

 }

 if (p==NULL)

 //不存在第 i 个数据结点,返回 false

  return false;

 else

 //存在第 i 个数据结点,返回 true

 { e=p->data;

  return true;

 } } int LocateElem(LinkNode *L,ElemType e)

 //查找第一个值域为 e 的元素序号 { int i=1;

 LinkNode *p=L->next;

 //p 指向首结点,i 置为 1(即首结点的序号为 1)

 while (p!=NULL && p->data!=e)

 //查找 data 值为 e 的结点,其序号为 i

 { p=p->next;

  i++;

 }

 if (p==NULL)

 //不存在值为 e 的结点,返回 0

  return(0);

 else

 //存在值为 e 的结点,返回其逻辑序号 i

  return(i); }

 实验截图(3)

 bool ListInsert(LinkNode *&L,int i,ElemType e)

 //插入第 i 个元素 { int j=0;

 if (i<=0) return false;

  //i 错误返回假

 LinkNode *p=L,*s;

 //p 指向头结点,j 置为 0(即头结点的序号为 0)

 while (j<i-1 && p!=NULL)

 //查找第 i-1 个结点 p

 { j++;

  p=p->next;

 }

  if (p==NULL)

  //未找到第 i-1 个结点,返回 false

  return false;

 else

  //找到第 i-1 个结点 p,插入新结点并返回 true

 { s=(LinkNode *)malloc(sizeof(LinkNode));

  s->data=e;

  //创建新结点 s,其 data 域置为 e

  s->next=p->next;

  //将结点 s 插入到结点 p 之后

  p->next=s;

  return true;

 } } bool ListDelete(LinkNode *&L,int i,ElemType &e)

 //删除第 i 个元素 { int j=0;

 if (i<=0) return false;

  //i 错误返回假

 LinkNode *p=L,*q;

  //p 指向头结点,j 置为 0(即头结点的序号为 0)

 while (j<i-1 && p!=NULL)

 //查找第 i-1 个结点

 { j++;

  p=p->next;

 }

 if (p==NULL)

  //未找到第 i-1 个结点,返回 false

  return false;

 else

  //找到第 i-1 个结点 p

 { q=p->next;

  //q 指向第 i 个结点

  if (q==NULL)

 //若不存在第 i 个结点,返回 false

 return false;

  e=q->data;

  p->next=q->next;

  //从单链表中删除 q 结点

  free(q);

  //释放 q 结点

  return true;

 //返回 true 表示成功删除第 i 个结点

 }

 }

 实验截图(4)

 编写 exp2- -p 2.cpp 程序包含有关代码

 //文件名:exp2-2.cpp #include "linklist.cpp" int main() {

 LinkNode *h;

 ElemType e;

 printf("单链表的基本运算如下:\n");

 printf("

 (1)初始化单链表 h\n");

 InitList(h);

 printf("

 (2)依次采用尾插法插入 a,b,c,d,e 元素\n");

  ListInsert(h,1,"a");

 ListInsert(h,2,"b");

 ListInsert(h,3,"c");

 ListInsert(h,4,"d");

 ListInsert(h,5,"e");

 printf("

 (3)输出单链表 h:");

 DispList(h);

 printf("

 (4)单链表 h 长度:%d\n",ListLength(h));

 printf("

 (5)单链表 h 为%s\n",(ListEmpty(h)?"空":"非空"));

 GetElem(h,3,e);

 printf("

 (6)单链表 h 的第 3 个元素:%c\n",e);

 printf("

 (7)元素 a 的位置:%d\n",LocateElem(h,"a"));

 printf("

 (8)在第 4 个元素位置上插入 f 元素\n");

 ListInsert(h,4,"f");

 printf("

 (9)输出单链表 h:");

 DispList(h);

 printf("

 (10)删除 h 的第 3 个元素\n");

  ListDelete(h,3,e);

 printf("

 (11)输出单链表 h:");

 DispList(h);

 printf("

 (12)释放单链表 h\n");

 DestroyList(h);

  return 1; }

 实验截图(5)

 运行得到结果

 实验截图(6)

 五.实验总结 通过这次实验,我的收获如下:

 1.进行编程时,要在感到模糊的地方进行备注,方便在报错的时候进行修改。

 2.要保持 linklist.cpp 程序中的函数名与 exp2-2.cpp 程序中的函数名完全一致,特别是大小写部分要特别注意。

 3.领会到了单链表存储的大体结构 4.了解了在单链表中各种基本运算算法设计

篇七:,p:true,s:[

章 数字签字和密码协议7.1

 数字签字的基本概念7.2

 数字签字标准数字签字标准7.3

 其他签字方案7.4

 认证协议7.5

 身份证明技术7.6

 其他密码协议习 题

 数字签字由公钥密码发展而来, 它在网络安全, 包括身份认证、 数据完整性、 不可否认性以及匿名性等方面有着重要应用。

 本章首先介绍数字签字的基本概念和一些常用的数字签字算法, 然后介绍身份认证协议、 身份证明技术以及其他一些常用的密码协议。

 上一章介绍的消息认证其作用是保护通信双方以防第三方的攻击, 然而却不能保护通信双方中的一方防止另方的欺骗或伪造防止另一方的欺骗或伪造。

 通信双方之间也可能有多种形式的欺骗, 例如通信双方A和B(设A为发方,B为收方)

 使用图6.1所示的消息认证码的基本方式通信, 则可能发生以下欺骗:通信方之间也能有7.1

 数字签字的基本概念7.1.1

 数字签字应满足的要求

 ① B伪造一个消息并使用与A共享的密钥产生该消息的认证码, 然后声称该消息来自于A。② 由于B有可能伪造A发来的消息, 所以A就可以对自己发过的消息予以否认。这两种欺骗在实际的网络安全应用中都有可能发生,例如在电子资金传输中, 收方增加收到的资金数,并声称这数目来自发方并声称这一数目来自发方。

 又如用户通过电子邮件向其证券经纪人发送对某笔业务的指令, 以后这笔业务赔钱了 , 用户就可否认曾发送过相应的指令。又如用户通过电子邮件

 因此在收发双方未建立起完全的信任关系且存在利害冲突的情况下, 单纯的消息认证就显得不够。

 数字签字技术则可有效解决这一问题。

 类似于手书签字, 数字签字应具有以下性质:① 能够验证签字产生者的身份, 以及产生签字的日期和时间。② 能用于证实被签消息的内容② 能用于证实被签消息的内容。③ 数字签字可由第三方验证, 从而能够解决通信双方的争议。

 由此可见, 数字签字具有认证功能。

 为实现上述3条性质, 数字签字应满足以下要求:① 签字的产生必须使用发方独有的一些信息以防伪造和否认。② 签字的产生应较为容易。③ 签字的识别和验证应较为容易。④ 对已知的数字签字构造一新的消息或对已知的消息构造一假冒的数字签字在计算上都是不可行的。

 数字签字的产生可用加密算法或特定的签字算法。1. 由加密算法产生数字签字利用加密算法产生数字签字是指将消息或消息的摘要加密后的密文作为对该消息的数字签字, 其用法单又根据是单钥加密还是公钥加密而有所不同。有7.1.2

 数字签字的产生方式

 (1) 单钥加密如图7.1(a)所示, 发送方A根据单钥加密算法以与接收方B共享的密钥K对消息M加密后的密文作为对M的数字签字发往B。

 该系统能向B保证所收到的消息的确来自A, 因为只有A知道密钥K。

 再者B恢复出M后, 可相信M未被篡改, 因为敌手不知道K就不知如何通过修改密文而修改明文就不知如何通过修改密文而修改明文。

 具体来说,就是B执行解密运算Y=DK(X), 如果X是合法消息M加密后的密文, 则B得到的Y就是明文消息M,否则Y将是无意义的比特序列。具体来说

 图7.1 消息加密产生数字签字的基本方式

 (2) 公钥加密如图7.1(b)所示, 发送方A使用自己的秘密钥SKA对消息M加密后的密文作为对M的数字签字, B使用A的公开钥PKA对消息解密, 由于只有A才拥有加密密钥SKA, 因此可使B相信自己收到的消息的确来自A。

 然而由于任何人都可使用A的公开钥解密密文所以这种方案不提供保密性密文, 所以这种方案不提供保密性。

 为提供保密性,A可用B的公开钥再一次加密, 如图7.1(c)所示。为提供保密性

 下面以RSA签字体制为例说明数字签字的产生过程。① 体制参数。选两个保密的大素数p和q, 计算n=p× q, φ(n)=(p-1)(q-1); 选一整数e, 满足1&lt;e&lt;φ(n), 且gcd(φ(n),e)=1; 计算d, 满足d·e≡1 mod φ(n); 以{e,n}为公开钥,{d,n}为秘密钥。② 签字过程。设消息为M, 对其签字为S≡Mdmod n

 ③ 验证过程。接收方在收到消息M和签字S后, 验证是否成立, 若成立, 则发送方的签字有效。实际应用时, 数字签字是对消息摘要加密产生, 而不是直接对消息加密产生, 如图6.3(a)~图6.3(d)所示。?modeMSn

 由加密算法产生数字签字又分为外部保密方式和内部保密方式, 外部保密方式是指数字签字是直接对需要签字的消息生成而不是对已加密的消息生成,否则称为内部保密方式。

 外部保密方式便于解决争议, 因为第3方在处理争议时, 需得到明文消息及其签字。

 但如果采用内部保密方式, 第3方必须得到消息的解密密钥后才能得到明文消息到消息的解密密钥后才能得到明文消息。

 如果采用外部保密方式, 接收方就可将明文消息及其数字签字存储下来以备以后万一出现争议时使用。如果采用

 2. 由签字算法产生数字签字签字算法的输入是明文消息M和密钥x, 输出是对M的数字签字, 表示为S=Sigx(M)。

 相应于签字算法, 有一验证算法, 表示为Verx(S,M), 其取值为True SVer SMFalse S算法的安全性在于从M和S难以推出密钥x或伪造一个消息M′使M′和S可被验证为真。,xxxSigMSigM

 数字签字的执行方式有两类:裁的方式。1. 直接方式直接方式和具有仲直接方式是指数字签字的执行过程只有通信双方参与, 并假定双方有共享的秘密钥或接收一方知道发方的公开钥。7.1.3

 数字签字的执行方式

 直接方式的数字签字有一公共弱点, 即方案的有效性取决于发方秘密钥的安全性。

 如果发方想对已发出的消息予以否认, 就可声称自己的秘密钥已丢失或被窃, 因此自己的签字是他人伪造的。

 可采取某些行政手段, 虽然不能完全避免但可在某种程度上减弱这种威胁。

 例如, 要求每一被签字的消息都包含有一个时戳(日期和时间)

 并要求密钥丢失后立含有个时戳(日期和时间)

 并要求密钥丢失后立即向管理机构报告。

 这种方式的数字签字还存在发方的秘密钥真的被偷的危险, 例如敌手在时刻T偷得发方的秘密钥, 然后可伪造一消息, 用偷得的秘密钥为其签字并加上T以前的时刻作为时戳。

 2. 具有仲裁方式的数字签字上述直接方式的数字签字所具有的缺陷都可通过使用仲裁者得以解决。

 和直接方式的数字签字一样,具有仲裁方式的数字签字也有很多实现方案, 这些方案都按以下方式运行:息签字后, 将消息及其签字先发给仲裁者A, A对消息及其签字验证完后消息及其签字验证完后, 再连同一个表示已通过验证的指令一起发往收方Y。

 此时由于A的存在, X无法对自己发出的消息予以否认。

 在这种方式中,仲裁者起着重要的作用并应取得所有用户的信任。发方X对发往收方Y的消再连同一个表示已通过验

 以下是具有仲裁方式数字签字的几个实例, 其中X表示发方, Y表示收方, A是仲裁者, M是消息,X→Y:M表示X给Y发送一消息M。

 例7.1 签字过程如下:① X→A:

 M‖ EKXA[IDX‖ H(M)]。② A→Y: EKAY[IDX‖ M‖ EKXA[IDX‖ H(M)]‖ T]。其中E是单钥加密算法, KXA和KAY分别是X与A共享的密钥和A与Y共享的密钥, H(M)是M的杂凑值, T是时戳, IDX是X的身份。

 在①中, X以EKXA[IDX‖ H(M)]作为自己对M的签字, 将M及签字发往A。

 在②中A将从X收到的内容和IDX、 T一起加密后发往Y, 其中的T用于向Y表示所发的消息不是旧消息的重放。

 Y对收到的内容解密后,将解密结果存储起来以备出现争议时使用。如果出现争议, Y可声称自己收到的M的确来自X,并将并将EKAY[IDX‖ M‖ EKXA[IDX‖ H(M)]]发给A, 由A仲裁, A由KAY解密后, 再用KXA对EKXA[IDX‖ H(M)]解密, 并对H(M)加以验证, 从而验证了 X的签字。

 以上过程中, 由于Y不知KXA, 因此不能直接检查X的签字, 但Y认为消息来自于A因而是可信的。所以在整个过程中, A必须取得X和Y的高度信任:• X相信A不会泄露KXA, 并且不会伪造X的签字;• Y相信A只有在对EKAY[IDX‖ M‖ EKXA[IDX‖ H(M)]‖ T]中的杂凑值及X的签字验证无误后才将之发给Y及X的签字验证无误后才将之发给Y;• X, Y都相信A可公正地解决争议。如果A已取得各方的信任, 则X就能相信没有人能伪造自己的签字, Y就可相信X不能对自己的签字予以否认。

 本例中消息M是以明文形式发送的, 因此未提供保密性, 下面两个例子可提供保密性。例7.2 签字过程如下:① X→A:

 IDX‖ EKXY[M]‖ EKXA[IDX‖ H(EKXY[M])]。② A→Y: EKAY[IDX‖ EKXY[M]‖ EKXA[IDX‖ H(EKXY[M])]‖ T]。

 其中KXY是X, Y共享的密钥, 其他符号与例7.1相同。

 X以EKXA[IDX‖ H(EKXY[M])]作为对M的签字,与由KXY加密的消息M一起发给A。

 A对EKXA[IDX‖ H(EKXY[M])]解密后通过验证杂凑值以验证X的签字, 但始终未能读取明文M。

 A验证完X的签字后, 对X发来的消息加一时戳, 再用KAY加密后发往Y。

 解决争议的方法与例7 1一样。密后发往Y。

 解决争议的方法与例7.1样。

 本例虽然提供了 保密性, 但还存在与上例相同的一个问题, 即仲裁者可和发方共谋以否认发方曾发过的消息, 也可和收方共谋以伪造发方的签字。

 这一问题可通过下例所示的采用公钥加密技术的方法得以解决。

 例7.3 签字过程如下:① X→A:

 IDX‖ ESKX[IDX‖ EPKY[ESKX[M]]]。② A→Y:

 ESKA[IDX‖ EPKY[ESKX[M]]‖ T]。

 其中SKA和SKX分别是A和X的秘密钥, PKY是Y的公开钥, 其他符号与前两例相同。

 第①步中, X用自己的秘密钥SKX和Y的公开钥PKY对消息加密后作为对M的签字, 以这种方式使得任何第3方(包括A)

 都不能得到M的明文消息。

 A收到X发来的内容后, 用X的公开钥可对ESKX[IDX‖ EPKY[ESKX[M]]]解密, 并将解密得到的ESKX[IDX‖ EPKY[ESKX[M]]]解密, 并将解密得到的IDX与收到的IDX加以比较, 从而可确信这一消息是来自于X的(因只有X有SKX)

 。

 第②步, A将X的身份IDX和X对M的签字加上一时戳后, 再用自己的秘密钥加密发往Y。

 与前两种方案相比, 第3种方案有很多优点。

 首先,在协议执行以前, 各方都不必有共享的信息, 从而可防止共谋。

 第二, 只要仲裁者的秘密钥不被泄露,任何人包括发方就不能发送重放的消息。

 最后, 对任何第三方(包括A)

 来说, X发往Y的消息都是保密的。

 数字签字标准DSS(Digital Signature Standard)是由美国NIST公布的联邦信息处理标准FIPS PUB 186,其中采用了 上一章介绍的SHA和一新的签字技术,称为DSA(Digital Signature Algorithm)。

 DSS最初于1991年公布在考虑了 公众对其安全性的反馈意于1991年公布, 在考虑了 公众对其安全性的反馈意见后, 于1993年公布了 其修改版。7.2

 数字签字标准

 首先将DSS与RSA的签字方式做一比较。

 RSA算法既能用于加密和签字, 又能用于密钥交换。

 与此不同, DSS使用的算法只能提供数字签字功能。

 图7.2用于比较RSA签字和DSS签字的不同方式。7.2.1

 DSS的基本方式

 图7.2 RSA签字与DSS签字的不同方式

 采用RSA签字时, 将消息输入到一个杂凑函数以产生一个固定长度的安全杂凑值, 再用发方的秘密钥加密杂凑值就形成了 对消息的签字。

 消息及其签字被一起发给收方, 收方得到消息后再产生出消息的杂凑值, 且使用发方的公开钥对收到的签字解密。这样收方就得了 两个杂凑值, 如果两个杂凑值是一样的, 则认为收到的签字是有效的。样的, 则认为收到的签字是有效的。

 DSS签字也利用一杂凑函数产生消息的一个杂凑值,杂凑值连同一随机数k一起作为签字函数的输入,签字函数还需使用发送方的秘密钥SKA和供所有用户使用的一族参数, 称这一族参数为全局公开钥PKG。

 签字函数的两个输出s和r就构成了 消息的签字(s, r)。

 接收方收到消息后再产生出消息的杂凑值, 将杂凑值与收到的签字一起输入验证函数, 验值, 将杂凑值与收到的签字证函数还需输入全局公开钥PKG和发送方的公开钥PKA。

 验证函数的输出如果与收到的签字成分r相等, 则验证了 签字是有效的。起输入验证函数, 验

 DSA是在ElGamal和Schnorr两个签字方案(见下一节)的基础上设计的, 其安全性基于求离散对数的困难性。算法描述如下:全(1) 全局公开钥p:

 满足2L-1&lt;p&lt;2L的大素数, 其中512≤L≤1024且L是64的倍数。q:

 p-1的素因子, 满足2159&lt;q&lt;2160, 即q长为160比特。g:

 g≡h(p-1)/qmod p, 其中h是满足1&lt;h&lt;p-1且使得h(p-1)/qmod p&gt;1的任一整数。7.2.2

 数字签字算法DSA

 (2) 用户秘密钥xx是满足0&lt;x&lt;q的随机数或伪随机数。(3) 用户的公开钥yy≡gxmod p。(4) 用户为待签消息选取的秘密数kk是满足0&lt;k&lt;q的随机数或伪随机数。k是满足0&lt;k&lt;q的随机数或伪随机数。(5) 签字过程用户对消息M的签字为(r, s),其中r≡(gkmod p) mod q,s≡[k-1(H(M)+xr)] mod q,H(M)是由SHA求出的杂凑值。

 (6) 验证过程设接收方收到的消息为M′, 签字为(r′,s′)。

 计算w≡(s′)-1mod q,u1≡[H(M′)w] mod qu2≡r′ w mod q,v≡[(gu1yu2) mod p] mod q检查若(M′,r′,s′)=(M,r,s), 则v r若(, , ) (v r, 若相等, 则认为签字有效。

 这是因为, , )则?1()(())[()mod ]modp[mod ]modp(mod )modpH M wxrwH Mxr skvggqgqgqr

 算法的框图如图7.3所示, 其中的4个函数分别为s≡f1[H(M),k,x,r,q]≡[k-1(H(M)+xr)] mod qr =f2(k,p,q,g)≡(gkmod p) mod qw =f3(s′,q)≡(s′)-1mod qv =f4(y,q,g,H(M′),w,r′)≡[(g(H(M′)w) mod qyr′w mod q) mod p] mod q≡[(gy) mod p] mod q

 图7.3 DSA的框图

 由于离散对数的困难性, 敌手从r恢复k或从s恢复x都是不可行的。还有一个问题值得注意, 即签字产生过程中的运算主要是求r的模指数运算r=(gkmod p) mod q, 而这一运算与待签的消息无关, 因此能被预先计算。

 事实上, 用户可以预先计算出很多r和k-1...

篇八:,p:true,s:[

表达式解释器实现原理 1 以 JavaScript 正则为例 Author:tuiye@126.com

  正则表达式可以用来 1验证字符串是否符合指定特征比如验证是否是合法的邮件地址。

 2用来查找字符串从一个长的文本中查找符合指定特征的字符串比查找固定字符串更加灵活方便。

 3用来替换比普通的替换更强大。

 对于一个正则表达式一般有 2 种方式以 JS 为例 其一为使用正则表达式文字常量 var re = /^[Jj]ava[Ss]cript/i; 其二为使用 RegExp 构造函数 var re = new RegExp(“^[Jj]ava[Ss]cript”,”i”);

  而一个正则表达式解释器主要有 3 部分组成分别是解析parse、编译compile与执行execute。

  1 解析 正则的表达式的词法与语法比较简单基本语法如下 A普通字符和元字符 普通字符是那些表示自身的字符例如从 a 到 zA 到 Z0 到 9 等 元字符具有特殊意义如‘.’表示除了‘/n’外的所有字符其他具有此功能的有

  表 1 元字符 元字符 ^ 匹配 &quot;^&quot; 字符本身请使用 &quot;/^&quot; $ 匹配 &quot;$&quot; 字符本身请使用 &quot;/$&quot; . 意一个字符。要匹配小数点本身请使用 &quot;/.&quot; * 要匹配 &quot;*&quot; 字符本身请使用 &quot;/*&quot; + 配“+” 字符本身请使用 “/+” ? 匹配 “?” 字符本身请使用 “/?” 特殊意义 匹配输入字符串的开始位置。

 要匹配输入字符串的结尾位置。

 要匹配除了换行符/n以外的任修饰匹配次数为 0 次或任意次。修饰匹配次数为至少 1 次。要匹修饰匹配次数为 0 次或 1 次。

 要

 = ! : | / / () 用于前向引用或向后引用 用于前向引用或向后引用 用于前向引用或向后引用 用于前向引用或向后引用 转义用 用于前向引用或向后引用 标记一个子表达式的开始和结束位置。要匹配小括号请使用 “/(“和 “/)” 用来自定义能够匹配 „多种字符‟的表达式。要匹配中括号请使用“/[“ 和 “/]” 修饰匹配次数的符号。要匹配大括号请使用 “/{“ 和 “/}” [] {} 元数据如要表示自身那么需要用‟/‟来辅助转义

  B字符类 单个的字符可以组成字符类其语法为用‟[‟与‟]‟组成例如[abcA-Z79]表示可以匹配 abc 与 A 到 Z79 的字符 其中‟-‟为连字符表示字符的跨度。

 „^‟在”[]”间也是特殊字符表示取反 其他的特殊字符如下表 表 2 字符类中的预定义字符类 预定义字符类 ^ 转义 - 示自身须紧接在‟[‟或‟[^‟之后 . 以外的任意一个字符 /d 符 /D 字字符 /s 等空白字符的其中任意一个 /S 字符以外的字符 /w 字或者下划线 /W 或者数字或者下划线以外的字特殊意义 在紧跟‟[‟表示取反 表示自身要在字符间表示连字符如要表小数点可以匹配除了换行符 /n可以匹配任何一个 0~9 数字字D 大写可以匹配任何一个非数可以匹配空格、制表符、换页符S 大写可以匹配任何一个空白可以匹配任何一个字母或者数W 大写 可以匹配任何一个字母

 符 JavaScript 无 POSIX 格式 C限定符重复 限定符有 2 种形式分别为‟*‟,‟+‟,‟?‟与‟ {‟与‟}‟来表示 表 3 限定符 限定符 * + ? {m,n} 特殊意义 表达式尽可能的多匹配 最少可以不匹配相当于 {0, } 表达式尽可能的多匹配 至少匹配 1 次相当于 {1, } 表达式尽可能匹配 1 次 也可以不匹配相当于 {0, 1} 表达式尽可能重复 n 次 至少重复 m 次 &quot;ba{1,3}&quot;可以匹配&quot;ba&quot;或&quot;baa&quot;或&quot;baaa&quot; 表达式固定重 m 次比如&quot;/w{2}&quot; 相当于 &quot;/w/w&quot; 表达式尽可能的多匹配 至少重复 m 次&quot;/w/d{2,}&quot;可以匹配&quot;a12&quot;,&quot;x456&quot;... {m} {m,}

  在正则中有贪婪与非贪婪之分默认的情况下正则是贪婪的 如果要把正则设置为非贪婪有 2 种方式 一种为设置在原先的限定符加上‟?‟就行另一种在设置 举例说明/.+/ 将匹配&quot;abdddd&quot;中的所有字符/.+?/ 只将匹配&quot;abdddd&quot;中的第一个 a也就是默认的尽可能多的匹配字符而非贪婪重复则尽可能上的匹配。

  D选择、分组和引用 选择的语法就是设置‟|‟如 a|bc那么要么 a 或 bc 都可以匹配如果(a|b)c则为匹配 ac 或 bc。

 如果我们在上例中设置了”()”那么这就是分组每个分组都可以被引用如(a|b)c*(e|f)/1/2/1 与/2 就是引用的语法/1 表示引用了(a|b)/2 表示引用(e|f)以此类推。

 这里要说明的是(a|b)c*(e|f)/1/2 与(a|b)c*(e|f)(a|b)(e|f)乍一看两者等同但实际上前一个不可以匹配 acebf而后一个可以。究其原因就是引用处的配平必须与被引用处一致此例中与之匹配的可以是 aceac。

  E定位符(锚)和前向引用 定位符如下表所示 表 4 定位符 限定符 ^ 匹配 &quot;^&quot; 字符本身 特殊意义 匹配输入字符串的开始位置。

 要

 $ 匹配输入字符串的结尾位置。

 要匹配 &quot;$&quot; 字符本身 表达式尽可能匹配 1 次 也可以不匹配相当于 {0, 1} 匹配单词边界例如一个/w 和/W 的位置或者一个/w 与字符串的开始和结尾的位置 ? /b /B 和上面的想法 匹配一个非单词边界 如果正则表达式的匹配模式为 MULTILINE 模式 ^ 可匹配一行文本的行首$ 可匹配一行文本的行末。当 /b 被包含于字符集合中时/b 代表退格符ASCII码 = 8。

 除了这些预定义的定位符还可以自定义定位符这种类型的定位符叫做前向引用(look-ahead anchor)和后向引用(look-behind anchorJavaScript 不支持)。

 前向引用使用(?=„)表示正的前向引用 (?!„)表示负的前向引用下面是一个前向引用的例子/Java(?!Script)([A-Z]/w*)/ 其中(?!Script)匹配后面不跟 Script 的位置而(?Script)匹配后面是 Script 的位置。

  以上讲解了 JavaScript 的语法规则下面我们来论述一下解析的过程。

 解析的过程是语法分析 Lexical Analysis 与词法分析 Grammar Analysis 。

 2 编译 编译Compile阶段主要的工作就是生成字节流Emit Byte Code。而生成 Byte Code 的算法规则JS 中就是 NFA。生成的 Byte Code 是归于执行Execute时做匹配利用。各个状态即为正则中的语义OPCODE的表示各个 OPCODE 以一定的格式与关系住成了状态机JS 中是组成 NFA 的状态机。

 下面介绍下在流行的两种算法 NFANondeterministic Finite Automaton与DFADeterministic Finite automatonPerlPythonJS 等都是 NFA 的而 awk与 grep 等用的是 DFA两种算法的具体实现如下 1有限状态机Finite Automation 状态机是一个有一组不同状态的集合的系统。有一个特殊状态――它描述了系统的初始状态。

 而其他的一个或多个状态为终止状态当一个事件将我们带到这样的一些状态时状态机将退出。状态是与转换相关联的每个转换都标注有输入事件的名称。

 当事件发生时 我们将随着相关的转换从当前状态移动到新的状态。

 一个有限状态机包含一组状态集states、一个起始状态start state、一组输入符号集alphabet、一个映射输入符号和当前状态到下一状态的转换函数transition function的计算模型。当输入符号串模型随即进入起始状态。它要改变到新的状态依赖于转换函数。

 假定一个输入符号(symbol)可以得到 2 个或者 2 个以上的可能状态那么这个 finite automaton 就是不确定的反之就是确定的。

 一个正则可以与一个 FA 等同其转化的规律如下 对于单个字符的

  两个状态的连接 e1e2 对于 e?

  对于 e1|e2

 对于 e*

 对于 e+

  2不确定有限状态机NFA 例如要匹配 abab|abbb,其 NFA 的状态是

  3确定性有限状态机DFA 以上例子的 DFA 如下

 其中 s1-s10 为各个的状态对应于 NFA 中的 s1-s10

  3 执行

 1NFA 那么一个 abbb 字符串的匹配过程如下

 一个更加高效的方式是同步匹配两者

 这里我们看到是利用正则表达式来扫描要匹配的字符串又由于此时是不确定状态机所以利用试探与 backing 的方式来做匹配的。NFA 是由正则来做驱动匹配的。这就像一个过程语言控制了解析器在匹配中的 try/fail。

 2DFA 而确定性状态机相反由于对于相应的输入都有一定的状态的迁移所以总的来说DFA 的匹配效率要高一些。DFA 是由字符串作驱动来匹配的在每个字符串中的每个字符只被扫描一次。

 这种方式就是尝试此状态时可能的每种输入同时进行匹配。

  4 实践 见 JS 1.6 与 PCRE7.2

  1JS1.6

 以 /.*ht*p{0,3}/ 为例来说明 JS1.6 与 PCRE7.2 的 NFA 组成

 JS1.6 中基本上以一个字符广义上的字符比如/n 我们认为是回车字符以一个节点建立 RENode。比如例子中我们建立了 7 个 RENode依次为‟.‟,‟*‟,‟h‟,‟t‟,‟*‟,‟p‟,” {0, 3}”。其中‟h‟,‟t‟,‟p‟分别为 REOP_FLAT而‟*‟,”{0,3}”为 REOP_QUANT(RE_STAR)。

  建立的节点的同时会调整节点间的关系主要是 ProcessOp()这个函数调整的关系为两种一种是 OP_CONCAT连接另一种为 OP_ALT选择。OP_CONCAT 是指两个 OP_FLAT 的 RENode 节点例如‟h‟与‟t‟是紧挨的那么我们把他们处理成“连接”关系。“连接”关系一种顺序关系。至于 OP_ALT则额外建立一个 OP_ALT 节点把两则建立起选择的关系。例如 a|b,那么建立OP_ALT 节点把节点‟a‟与‟b‟与节点 OP_ALT 建立选择关系。

 解析后 RENode 节点顺序如下图 * 0 4 . ENDCHILD FLAT h * 0 5 FLAT t END CHILD QUANT 0 3 0 5 FLAT1 P END 即

 JS1.6 中编译的过程就为生成 NFA 的过程主要是调整生成 OP_ALTOP_BACKREFOP_STAR 等跳转关系 编译后生成 NFA 注此例中上下行为父子关系 REOP_STAR REOP_DOT ‟.‟ 即 REOP_FLAT1 „h‟ REOP_STAR REOP_FLAT ‟t‟ REOP_QUANT REOP_FLAT „p‟

  执行匹配的过程我们以匹配字符串”xhtttpps” 匹配中的 OPCODE Start保存MatchBack用 | .* .* 匹配中的匹配位置与状态 |x h t t t p p s |x h t t t p p s &lt;x h t t t p p s x h t t t p p s 成功与否

  True True

 … .* h … h h … … False False … &lt;x h t t t p p s| &lt;x h t t t p p s| … &lt;x h |t t t p p s &lt;x |h t t t p p s &lt;x h |t t t p p s … &lt;x h t t t |p p s &lt;x h t t t |p p s &lt;x h t t t p |p s &lt;x h t t t p p&gt; s False则回朔 True True … False则回朔 True True True

 t

  … t p p Done 注其中‟|‟代表匹配所在的位置‟&lt;‟代表匹配成功开始‟&gt;‟代表匹配成功结束。

 所以上述正则可匹配上述字符串中的”xhtttpp”

  2PCRE7.2 以/ht*p{0,2}/为例 PCRE 的解析与编译是合而为一的也就是说解析编译后生成的 OPCODE即为最终的 NFA。这里 NFA 与 JS1.6 中的 NFA 是形式是一样的当然细节上有区别。因此其匹配的过程也是相似。

 当然 PCRE 也提供理论部分的 DFA 作为其状态机。待续 以上的正则解析编译后的以如下格式存在。

 OP BRA 由于其 NFA 与 JS 有一致性 这里不再重复倒是其 Match 时的一个消递归的方式比较不错下面来做一个小的说明。

 基本思想是这样的 因为我们递归的时候每次都要保存一些变量与 “栈” 上这样过多的嵌套就会引起很大的变量于 “栈” 上 而且由于某些操作系统对 “栈”的大小是有限制的这就在一定的时候会引起“栈”溢出从而到时程序运行问题常见的就是 Crash。

 一般比较常用的消递归的方式主要有 2 种其一是无限循环其二就是自己从“堆”上保存自己的变量。这里用了第二种方式。

 以函数直接调用自身这种方式来说明。那么在此函数中定有一处或几处是调用到自身的在调用自身处在“堆”上分配出空间 frame用于保存当前的变量的值并把当前 frame 压入自己的 frame 栈数据结构中的栈与上面提到的“栈”不同并且在此设定一个 label标签用于 RETURN 时候的 goto 到此用。并且 goto 至函数的入口处此时犹如一个函数的新调用而且可以减少调用函数的开销。

 当函数执行完比如匹配不成功需要回退或者 subpattern 执行完毕时候我们需要做“返回”。返回前我们必须保存执行到此时的一个“结果”0 11 OP CHAR h OP STAR t OP UPTO 0 2 p OP KET 0 11 OP END

 如函数的返回值类似。然后就是取出要返回的 label 的位置用 goto 到那里把当前的 frame 销毁继续执行上一步中未完成的部分。大体上就是这样。

  理解正则表达式 2 rex 注本文原作者孟岩原文转自孟岩 CSDN 博客。本文为《程序员》07 年 3 月号《七种武器》专题所做。rex 以前只是知道如何使用正则表达式而已在读 MRE 时读到 NFA、DFA 其实都是一头雾水不知所云。现在抓紧时间恶补基础知识学习了些编译原理这才有些明白。如今再看从源头讲正则表达式的文章就心有戚戚了呵呵。搜到好文章一篇与大家分享。

 在程序员日常工作中数据处理占据了...

篇九:,p:true,s:[

语句 语句解释

  result = result + Mid(p,

 s,

 1)

 后暗含 Else result = result

 If Mid(p,

 s,

 1)

 = k Then f = True 后暗含 If Mid(p,

 s,

 1)

 <> k Then f = False 本语句在 Private Sub Command1_Click()之外表示全局函数对所有程序段都有效定义变量 p 为字符串型

 定义变量 k 为字符串型 点击 Command1 按钮启动按钮单击事件 定义变量 s 为整数型、 变量 result 为字符串型、 变量 flag 为逻辑型 result 为空 p 为文本框 text 1 中的文本 k 为文本框 text 2 中的文本 就是循环从 1 到 p 变量包含的字符串的长度 flag 为自定义函数 f(s)

 因为 flag 不是为自定义函数 f(s) ,成条件成立, (把输入的每一个字符拿来和输入在第二文本框中的字母比较如果不一样, 条件成立)

 将该字母累加排到上一次循环后的result 中的字母之后并成为新的result (Mid(p, s, 1) 是返回 p 中的若干字符中第 s 位上的字符)

  条件结束(如果先输入的若干字符语新输入的一个字符相同的则不累加)

 循环结束 在 text_3 中显示出最终的 result 中的字符 程序结束

 子程序 f(s) 为逻辑型, s 为整数型 如果某个字符语新输入的字符相同 f为真 与 not flag 对应 f 为假(false)

  Dim p As String,

 k As String Private Sub Command1_Click()

 Dim s As Integer,

 result As String,

 flag As Boolean result = "" p = Text_1. Text k = Text_2. Text For s = 1 To Len(p)

 flag = f(s)

 If Not flag Then

 result = result + Mid(p,

 s,

 1)

  End If Next s

 Text 3. Text = result End Sub

 Function f(s As Integer)

 As Boolean

  If Mid(p,

 s,

 1)

 = k Then f = True End Function

 VB 要求从某一字符串中删除指定的字符

 (假设所含的英文字母均为小写字母)

 , 并将处理后的字符串重新输出。

 程序界面如图所示, 在文本框 Text_1 中输入原始字符串, 在文本框 Text_2 中输入需要删除的字符, 单击"删除此字符"按钮(Command1 )

 后, 在文本框 Text_3 中输出处理后的结果。

 上传不了图, 用字表示:

 字符删除程序 输入原始字符串(label1 )_________(text1 ) 输入需要删除的字符(label2)_______(text2)删除此字符(Command1 ) 处理后结果(label3)________(text3)

 解决此问题的算法流程图如图所示, 相应的 Visual Basic 程序如下:

 Dim p As String, k As String Private Sub Command1 _Click() Dim s As Integer, result As String, flag As Boolean result = "" p = Text_1 .Text k = Text_2.Text For s = 1

 To Len(p)

  flag = f(s)

  If Not flag Then

 result = result +

 ①

  End If Next s

 ②

 End Sub Function f(s As Integer) As Boolean

  If Mid(p, s, 1 ) = k Then f = True End Function (1 )

 解决此问题的算法是_顺序查找___。

 (选填:

 顺序查找 或 对分查找)

 在程序①和②划线处, 填入适当的语句或表达式, 把程序补充完整。

 (2)

 程序中①划线处应填入______________。

 (3)

 程序中②划线处应填入________________。

 Mid(p, s, 1 )

  "不是要找的字母, 那就添加到 result 中 text_3.text=result

 "显示结果

推荐访问: p:true s:[ true