第3講堆棧、隊列和字符串_第1頁
第3講堆棧、隊列和字符串_第2頁
第3講堆棧、隊列和字符串_第3頁
第3講堆棧、隊列和字符串_第4頁
第3講堆棧、隊列和字符串_第5頁
已閱讀5頁,還剩179頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

Stack、Queue&String棧和隊列是限定插入和刪除只能在表的“端點”進行的線性表。

線性表棧隊列Insert(L,

i,x)Insert(S,n+1,x)Insert(Q,n+1,x)

1≤i≤n+1Delete(L,i)Delete(S,n)Delete(Q,1)

1≤i≤n棧和隊列是兩種常用的數(shù)據(jù)類型Section1

Stack

只允許在一端插入和刪除的線性表允許插入和刪除的一端稱為棧頂

(top),另一端稱為棧底(bottom)特點后進先出(LIFO)棧(Stack)退棧進棧a0an-1an-2topbottom棧的抽象數(shù)據(jù)類型定義ADTStack

{

數(shù)據(jù)對象:

D={ai|ai∈ElemSet,i=1,2,...,n,n≥0}

數(shù)據(jù)關系:

R1={<ai-1,ai>|ai-1,ai∈D,i=2,...,n}

約定an

端為棧頂,a1端為棧底?;静僮鳎?/p>

}ADTStackInitStack(&S)DestroyStack(&S)ClearStack(&S)StackEmpty(s)StackLength(S)GetTop(S,&x)Push(&S,x)Pop(&S,&x)

InitStack(&S)

操作結(jié)果:構造一個空棧

S。

DestroyStack(&S)

初始條件:棧S已存在。

操作結(jié)果:棧S被銷毀。

StackEmpty(S)

初始條件:棧S已存在。

操作結(jié)果:若棧S為空棧,

則返回TRUE,

否則FALE。

StackLength(S)

初始條件:棧S已存在。

操作結(jié)果:返回S的元素

個數(shù),即棧的

長度。

GetTop(S,&x)

初始條件:棧S已存在且非空。

操作結(jié)果:用x返回S的棧頂

元素。a1a2an……

ClearStack(&S)

初始條件:棧S已存在。

操作結(jié)果:將S清為空棧。

Push(&S,x)

初始條件:棧S已存在。

操作結(jié)果:插入元素x為新

的棧頂元素。

a1a2anx……Pop(&S,&x)

初始條件:棧S已存在且非

空。

操作結(jié)果:刪除S的棧頂元

素,并用x返回

其值。a1a2anan-1

……

棧的數(shù)組表示

—順序棧

//-----棧的順序存儲表示

-----

#defineSTACK_INIT_SIZE100;

#defineSTACKINCREMENT10;

typedefstruct{

SElemType

*base;

SElemType

*top;

intstacksize;

}

SqStack;

類似于線性表的順序映象實現(xiàn),指向表尾的指針可以作為棧頂指針。

StatusInitStack(SqStack&S){//構造一個空棧SS.base=newElemType[STACK_INIT_SIZE];if(!S.base)exit(OVERFLOW);S.top=S.base;S.stacksize=STACK_INIT_SIZE;returnOK;}

StatusPush(SqStack&S,SElemTypee){if(S.top-S.base>=S.stacksize){//棧滿,追加存儲空間

S.base=(ElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*

sizeof(ElemType));

if(!S.base)exit(OVERFLOW);//存儲分配失敗

S.top=S.base+S.stacksize;S.stacksize+=STACKINCREMENT;

}

*S.top++=e;

returnOK;}StatusPop(SqStack&S,SElemType&e){//若棧不空,則刪除S的棧頂元素,

//用e返回其值,并返回OK;

//否則返回ERROR

if

(S.top

==

S.base)

returnERROR;

e=*--S.top;

returnOK;}template<classType>classStack{private:int

top;

Type*elements;

intmaxSize;public:Stack(ints

=10);~Stack(){delete[]elements;

}

intPush(Typex);

intPop(Type

&x);intGetTop(Type

&x);

voidMakeEmpty(){top=-1;

}

intIsEmpty()const{returntop==-1;

}

intIsFull()const{returntop==maxSize-1;

} }template<classType>Stack<Type>::Stack(ints){top=-1;maxSize=s;elements=newType[maxSize]; }

top空棧toptoptoptoptopa進棧b進棧aababcdee進棧abcdef進棧溢出abdee退棧ctopc退棧b退棧abaa退棧空棧topabdd退棧ctopabctoptoptemplate<classType>intStack<Type>::Push(Typex){

if(IsFull())

return0;elements[++top]=x;return1;}template<classType>intstack<Type>::Pop(Type&x){if(IsEmpty())return0;x=elements[top--];return1;}

template<classType>intstack<Type>::GetTop(Type&x){if(IsEmpty())

return0;x=elements[top];return1;}第一個例子:反轉(zhuǎn)表#include"sq_stack.h"voidmain()/*Pre:Theusersuppliesanintegernandndecimalnumbers.Post:Thenumbersareprintedinreverseorder.Uses:TheSTLclassstackanditsmethods*/{intn;doubleitem;stack<double>numbers;//declaresastackofnumberscout<<"Typeinanintegernfollowednnumbers."<<endl<<"Thenumberswillbeprintedinreverseorder."<<endl;cin>>n;for(inti=0;i<n;i++){

cin>>item;numbers.push(item);}cout<<endl<<endl;while(!numbers.empty()){cout<<numbers.top()<<"";numbers.pop();}cout<<endl;}棧的鏈接表示—鏈式棧鏈式棧無棧滿問題,空間可擴充插入與刪除僅在棧頂處執(zhí)行鏈式棧的棧頂在鏈頭top鏈式棧(LinkedStack)類的定義template<classType>classStack;template<classType>classStackNode{friendclassStack<Type>;private:

Typedata;StackNode<Type>*link;public:StackNode(Typed,StackNode<Type>

*l=NULL){ data=d;link=l;

}};template<classType>classStack{private:StackNode<Type>*top;public:Stack(){top=NULL}~Stack();

voidPush(Typex);

intPop(Type&x);

intGetTop(Type&x);

voidMakeEmpty();//實現(xiàn)與~Stack()同

intIsEmpty(){returntop==NULL;

}}template<classType>Stack<Type>::~Stack(){StackNode<Type>*p;

while(top!=NULL)

{p=top;top=top->link;

deletep;

}}template<classType>voidStack<Type>::Push(Typex){top=newStackNode<Type>(x,top);}template<classType>intStack<Type>::Pop(Type&x){if(IsEmpty())return

0; StackNode<Type>*p=top;top=top->link;x=p->data;

deletep;

return1;}

template<classType>intStack<Type>::GetTop(Type&x){if(IsEmpty())return0;x=top->data;return1;}

表達式求值一個表達式由操作數(shù)(亦稱運算對象)、操作符

(亦稱運算符)和分界符組成。算術表達式有三種表示:中綴(infix)表示

<操作數(shù)><操作符><操作數(shù)>,如A+B;前綴(prefix)表示

<操作符><操作數(shù)><操作數(shù)>,如+AB;后綴(postfix)表示

<操作數(shù)><操作數(shù)><操作符>,如AB+;表達式的中綴表示

表達式中相鄰兩個操作符的計算次序為:優(yōu)先級高的先計算;優(yōu)先級相同的自左向右計算;當使用括號時從最內(nèi)層括號開始計算。C++中操作符的優(yōu)先級

優(yōu)先級

操作符

1 單目+、-、!

2 *、/、% 3 +、-

4 <、<=、>、>=5==、!= 6 && 7 || 一般表達式的操作符有4種類型:算術操作符如雙目操作符(+、-、*、/和%)以及單目操作符(+、-)。關系操作符包括<、<=、==、!=、>=、>。這些操作符主要用于比較。邏輯操作符如與(&&)、或(||)、非(!)。括號‘(’和‘)’它們的作用是改變運算順序。

中綴表達式中各個算術操作符的優(yōu)先級isp叫做棧內(nèi)(instackpriority)優(yōu)先數(shù)icp叫做棧外(incomingpriority)優(yōu)先數(shù)。操作符優(yōu)先數(shù)相等的情況只出現(xiàn)在括號配對或棧底的‘=’號與輸入流最后的‘=’號配對時。上面討論的+、-為雙目運算符,如為單目運算符,編程實現(xiàn)時,可在前面加上0而轉(zhuǎn)化為雙目運算符。如在+、-的前一個字符(跳過空格,當前一個字符不是運算符時用‘0’表示)為‘=’或‘(’,則為單目運算符。中綴算術表達式求值中綴算術表達式求值使用兩個棧,操作符棧OPTR(operator),操作數(shù)棧OPND(operand),對中綴表達式求值的一般規(guī)則:(1)建立并初始化OPTR棧和OPND棧,然后在OPTR棧中壓入一個‘=’。(2)從輸入流獲取一字符ch,并跳過空格及回車。(3)取出OPTR的棧頂OPTR_top。(4)當OPTR_top!=‘=’或ch!=‘=’時,循環(huán)執(zhí)行以下工作,否則結(jié)束算法。此時在OPND棧的棧頂?shù)玫竭\算結(jié)果。

while(OPTR_top!=‘=’

||ch!=‘=’){

①若ch不是操作符,則將字符放回輸入流(cin.putback),讀操作數(shù)newoperand并進OPND棧,并讀入下一字符(跳過空格及回車)送入ch;②若ch是操作符,比較icp(ch)的優(yōu)先級和isp(OPTR_top)的優(yōu)先級:

若isp(OPTR_top)<icp(ch),則ch進OPTR棧,從中綴表達式取下一字符(跳過空格及回車)送入ch;

若isp(OPTR_top)>icp(ch),則從OPND棧退出a2和a1,從OPTR棧退出θ,形成運算指令(a1)θ(a2),結(jié)果進OPND棧;

若isp(OPTR_top)==icp(ch)且ch==

“)”,則從OPTR棧退出棧頂?shù)摹?”,對消括號,然后從中綴表達式取下一字符送入ch。

③取出OPTR的棧頂OPTR_top。}2023/2/5443.2棧的應用舉例

例1數(shù)制轉(zhuǎn)換問題

輾轉(zhuǎn)相除法如圖所示:

算法描述:

#defineLength10voidconversion(intN,intr){intS[Length],top;//定義一個順序棧

intx;top=-1;//初始化棧

while(N){S[++top]=N%r;//余數(shù)入棧

N=N/r;

//商作為被除數(shù)繼續(xù)

}while(top!=-1)

//出棧輸出

{x=s[top--];printf(“%d”,x);}}算法描述#defineLength10voidconversion(intN,intr){

intS[Length],top;//定義一個順序棧

intx;top=-1;//初始化

while(N)

{

S[++top]=N%r;

//余數(shù)入棧

N=N/r;//商作為被除數(shù)繼續(xù)

}

while(top!=-1)//出棧輸出

{

x=s[top--];

printf(“%d”,x);}}例2檢查一個表達式中的括號是否配對#defineSTRLEN255Boolcheak()

{charS[STRLEN];//初始化字符棧

inttop=-1;

charch=’#’

while(ch!=’\n’)//重復從鍵盤讀字符,直到讀到回車換行符

{scanf(“%c”,&ch);

switch(ch)//根據(jù)讀入字符的不同情況分別處理

{case’(’:

{S[++top=ch;break;}

例2續(xù)case’[’://ch是’(’或’[’時,入棧

{S[++top=ch;break;}case’)’://處理ch=’)’時的情況

{if(S[top]==’(’)top--;

elseif(S[top]==’[’)returnERROR;break;

}case’]’://處理ch=’]’時的情況

{if(S[top]==’[’)top--;

elseif(S[top]==’(’)returnERROR;break;

}}if(top<0)returnTRUE;//棧空時返回真,否則返回假

elsereturnERROR;}//算法結(jié)束例3表達式求值算法

OperandTypeExpressionEvaluate()//從鍵盤輸入中綴表達式,計算其值InitStack(OPTR);Push(OPTR,‘#’);//初始化運算符棧InitStack(OPND);//初始化操作數(shù)ch=getchar();while(ch!=‘#‘&&GetTop(OPTR)!=‘#‘)//逐個讀字符ch且不等于#

{if(!in(ch,OP))

Push(OPND,ch);//不是運算符入操作數(shù)棧

else{switch()//是運算符時分別做不同處理

{case‘<‘: //ch的優(yōu)先級高于棧頂運算符的優(yōu)先級

{Push(OPTR,ch);break;}例3續(xù)case‘=’://ch的優(yōu)先級等于棧頂運算符的優(yōu)先級

{Pop(OPTR,c);breck;}case‘>’://ch的優(yōu)先級低于棧頂運算符的優(yōu)先級

{Pop(OPTR,theta);

Pop(OPND,x);Pop(OPND,y);//彈出兩個操作數(shù)Push(OPND,Operate(x,theta,y);//計算、入操作數(shù)棧

}ch=getchar();//讀下一個字符ch

}

Pop(OPND,x);returnx;//返回結(jié)果

}//算法結(jié)束2023/2/550例4、后綴表達式求值。

OperandTypeexprEvaluatel(charA[])

//本函數(shù)返回由后綴表達式A表示的表達式運算結(jié)果{InitStack(S);ch=*A++;while(ch!=’#’){if(!In(ch,OP)Push(S,ch);//讀入的字符是操作數(shù)時入棧

else//是運算符,取出兩個操作數(shù)

{Pop(S,x);Pop(S,y);switch(ch)//對兩個操作數(shù)進行相應計算

{case’+’

:c=a+b;break;case’-’

:c=a-b;break;case’*’:c=a*b;break;case’/’:c=a/b;break;case’%’:c=a%b;break;}

Push(S,c);//計算結(jié)果入棧

}ch=*A++;

//讀下一個字符

}Pop(S,c);returnc;

//

返回結(jié)果

}

//算法結(jié)束2023/2/551例5、利用棧實現(xiàn)遞歸函數(shù)計算n!

設f(n)=n!,求f(n)可以遞歸地定義為:

f(n)=1

n=0時//遞歸終止條件

f(n)=n*f(n-1)n>0時//遞歸步驟遞歸函數(shù):

intfact(intn) {if(n==0)return1; elsereturn(n*fact(n-1)); }2023/2/552例:利用迭代實現(xiàn)遞歸函數(shù)計算n!

Intfact(intn,stack<int>&s){While(n>1)s.puch(n--)Intresult=1;Intval;While(s.pop(val))result=result*val;Return}2023/2/553例6

漢諾塔問題算法

voidhanoi(intn,charx,chary,charz)//將x柱上n個盤子借助y柱移到z柱上

{if(n==1)move(x,1,z);//將x柱上編號為1的盤子移動到z柱上

else{hanio(n-1,x,z,y);//將x柱上的n-1個盤子移動到y(tǒng)柱上

move(x,n,z);//將x柱上編號為n的盤子移動到z上

hanio(n-1,y,x,z);//將y柱上的n-1個盤子移動到z柱上

}}Section2

Queue隊列(

Queue)定義隊列是只允許在一端刪除,在另一端插入的順序表允許刪除的一端叫做隊頭(front),允許插入的一端叫做隊尾(rear)。特性先進先出(FIFO,FirstInFirstOut)a0

a1

a2

an-1frontrearADTQueue{

數(shù)據(jù)對象:

D={ai|ai∈ElemSet,i=1,2,...,n,n≥0}

數(shù)據(jù)關系:

R1={<ai-1,ai>|ai-1,ai∈D,i=2,...,n}

約定其中a1

端為隊列頭,an

端為隊列尾基本操作:隊列的抽象數(shù)據(jù)類型定義}

ADTQueue隊列的基本操作:InitQueue(&Q)DestroyQueue(&Q)QueueEmpty(Q)QueueLength(Q)GetHead(Q,&x)ClearQueue(&Q)DeQueue(&Q,&x)EnQueue(&Q,x)InitQueue(&Q)

操作結(jié)果:構造一個空隊列Q。

DestroyQueue(&Q)

初始條件:隊列Q已存在。

操作結(jié)果:隊列Q被銷毀,

不再存在。

QueueEmpty(Q)

初始條件:隊列Q已存在。

操作結(jié)果:若Q為空隊列,則

返回TRUE,否則

返回FALSE。

QueueLength(Q)

初始條件:隊列Q已存在。

操作結(jié)果:返回Q的元素個

數(shù),即隊列的長

度。

GetHead(Q,&x)

初始條件:Q為非空隊列。

操作結(jié)果:用x返回Q的隊頭

元素。a1a2an……

ClearQueue(&Q)

初始條件:隊列Q已存在。

操作結(jié)果:將Q清為空隊列。

EnQueue(&Q,x)

初始條件:隊列Q已存在。

操作結(jié)果:插入元素x為Q的

新的隊尾元素。a1a2anx……

DeQueue(&Q,&x)

初始條件:Q為非空隊列。

操作結(jié)果:刪除Q的隊頭元

素,并用x返回

其值。a1a2an……

循環(huán)隊列

(CircularQueue)隊列的進隊和出隊(C語言版)

frontrear空隊列frontrearA進隊AfrontrearB進隊ABfrontrearC,D進隊ABCDfrontrearA退隊BCDfrontrearB退隊CDfrontrearE,F,G進隊CDEFGCDEFGfrontrearH進隊,溢出隊列的進隊和出隊原則

進隊時將新元素按

rear指示位置加入再將隊尾指針先進一rear=rear+1。

出隊時將下標為

front的元素取出,再將隊頭指針先進一front=front+1。

隊滿時再進隊將溢出出錯;隊空時再出隊將隊空處理。解決辦法之一:將隊列元素存放數(shù)組首尾相接,形成循環(huán)(環(huán)形)隊列。

01234567front01234567front01234567frontrearAABCrearrear空隊列A進隊B,C進隊0123456701234567A退隊B退隊01234567D,E,F,G,H,I進隊frontBCrearAfrontBCrearfrontCrearDEFGHI隊列存放數(shù)組被當作首尾相接的表處理。隊頭、隊尾指針加1時從maxSize-1直接進到0,可用語言的取模(余數(shù))運算實現(xiàn)。隊頭指針進1:front=(front+1)%maxSize;隊尾指針進1:rear=(rear+1)%maxSize;隊列初始化:front=rear=0;隊空條件:front

==

rear;隊滿條件:(rear+1)%maxSize==front

循環(huán)隊列(CircularQueue)#defineMAXQSIZE100//最大隊列長度

typedefstruct{

QElemType*base;//動態(tài)分配存儲空間

intfront;//頭指針,若隊列不空,

//指向隊列頭元素

intrear;//尾指針,若隊列不空,指向

//隊列尾元素的下一個位置

}SqQueue;循環(huán)隊列——順序映象

StatusInitQueue(SqQueue&Q){//構造一個空隊列QQ.base=(ElemType*)malloc

(MAXQSIZE*sizeof(ElemType));

if(!Q.base)exit(OVERFLOW);//存儲分配失敗

Q.front=Q.rear=0;

returnOK;

}StatusEnQueue(SqQueue&Q,ElemTypee){//插入元素e為Q的新的隊尾元素

if((Q.rear+1)%MAXQSIZE==Q.front)

returnERROR;//隊列滿

Q.base[Q.rear]=e;Q.rear=(Q.rear+1)%MAXQSIZE;

returnOK;}

StatusDeQueue(SqQueue&Q,ElemType&e){

//若隊列不空,則刪除Q的隊頭元素,

//用e返回其值,并返回OK;否則返回ERRORif(Q.front==Q.rear)returnERROR;e=Q.base[Q.front];

Q.front=(Q.front+1)%MAXQSIZE;

returnOK;}隊列的進隊和出隊(C++語言版)

frontrear空隊列frontrearA進隊AfrontrearB進隊ABfrontrearC,D進隊ABCDfrontrearA退隊BCDfrontrearB退隊CDfrontrearE,F,G進隊CDEFGCDEFGfrontrearH進隊,溢出隊列的進隊和出隊原則

進隊時隊尾指針先進一rear=rear+1,

再將新元素按

rear指示位置加入。

出隊時隊頭指針先進一front=front+1,再將下標為

front的元素取出。

隊滿時再進隊將溢出出錯;隊空時再出隊將隊空處理。解決辦法之一:將隊列元素存放數(shù)組首尾相接,形成循環(huán)(環(huán)形)隊列。

隊列存放數(shù)組被當作首尾相接的表處理。隊頭、隊尾指針加1時從maxSize-1直接進到0,可用語言的取模(余數(shù))運算實現(xiàn)。隊頭指針進1:front=(front+1)%maxSize;隊尾指針進1:rear=(rear+1)%maxSize;隊列初始化:front=rear=0;隊空條件:front

==

rear;隊滿條件:(rear+1)%maxSize==front

循環(huán)隊列(CircularQueue)01234567front01234567front01234567frontrearAABCrearrear空隊列A進隊B,C進隊0123456701234567A退隊B退隊01234567D,E,F,G,H進隊frontBCrearAfrontBCrearfrontCrearDEFGHtemplate<classType>classQueue{ private:

intrear,front;

Type*elements;

intmaxSize;public:Queue(intsz=10);~Queue(){delete[]elements;

}

intEnQueue(Typex);

intDeQueue(Type&x);

intGetFront(Type&x);

voidMakeEmpty(){

front=rear;

}

intIsEmpty()const

{returnfront==rear;}

intIsFull()const{return(rear+1)%maxSize==front;}

intLength()const{return(rear-front+maxSize)%maxSize;}}template<classType>Queue<Type>::Queue(intsz){front=0;rear=0;maxSize=sz;elements=newType[maxSize]; }template<classType>intQueue<Type>::EnQueue(Typex){if(IsFull())return0;

rear=(rear+1)%MaxSize; elements[rear]=x;return1; }template<classType>intQueue<Type>::DeQueue(Type&x){if(IsEmpty())return

0; front=(front+1)%MaxSize;

x=elements[front];

return1;}template<classType>intQueue<Type>::GetFront(Type&x){if(IsEmpty())return0; x=elements[(front+1)%MaxSize];Return1;}隊列的鏈接表示—鏈式隊列

(C++語言版)

隊頭在鏈頭,隊尾在鏈尾。鏈式隊列在進隊時無隊滿問題,但有隊空問題。隊空條件為front==NULLfrontreartemplate<classType>classQueue;template<classType>classQueueNode{ friendclassQueue<Type>;private:

Typedata; QueueNode<Type>*link;public:QueueNode(Typed,QueueNode<Type>*l=NULL){data=d;link=l;}};

template<classType>classQueue{private:

QueueNode<Type>*front,*rear;public:Queue(){rear=NULL;front=NULL;}

~Queue();

voidEnQueue(Typex);intDeQueue(Type&x);

intGetFront(Type&x);

voidMakeEmpty();//實現(xiàn)與~Queue()同

intIsEmpty()const

{returnfront==NULL;

}

};

template<classType>Queue<Type>::~Queue(){QueueNode<Type>*p;

while(front!=NULL){p=front;front=front->link;

deletep;}}template<classType>voidQueue<Type>::EnQueue(Typex){if(front==NULL)front=rear=newQueueNode<Type>(x);

else{rear->link=newQueueNode<Type>(x);

rear=rear->link;

}}template<classType>intQueue<Type>::DeQueue(Type

&x){

if(IsEmpty())return0;QueueNode<Type>*p=front; front=front->link;x=p->data;

deletep;

return1; }template<classType>intQueue<Type>::GetFront(Type

&x){if(IsEmpty())return0; x=front->data;return1;}

顯示楊輝三角形的算法VoidyanghuiTriangle(intn){//結(jié)果顯示三角形的第1行—第n行l(wèi)inkQueue<int>q;ints,t;q.InQueue(1);q.InQueue(1);

//存儲第1行的兩個元素的值

cout<<1<<“\t”<<1;

//顯示第1行for(inti=2;i<=n;

i++){//依次顯示三角形的第2行到第n行

cout<<endl;

q.InQueue(1);

//第i行的第1個元素值為1cout<<1<<“\t”

//顯示第i行的第1個元素

q.OutQueue(s);

//取第i-1行的第1個元素

顯示楊輝三角形的算法(續(xù))for(intj=2;j<=i;j++){

q.OutQueue(t);

//取第i-1行的第j個元素q.InQueue(s+t);

//s+t為第i行第j個元素的值

cout<<s+t<<“\t”;

//顯示第i行第j個元素的值

s=t:}q.InQueue(1);//第i行第i+1個元素的值為1

cout<<1;

//顯示第i行第i+1個元素的值}

cout<<endl;

}

Section3

String串的定義n(n>=0)個字符的有限序列S=‘a(chǎn)1,a2,……,an’

串名:s

串值:ai(1<=i<=n)

串長:n術語空串n=0的串子串串中若干相鄰字符組成的子序列主串包含子串的串空格串僅含有空格字符的串(n不為0)串相等設s1=‘a(chǎn)11,…,an1’s2=‘a(chǎn)12,…,an2’

若n1=n2且ai1=ai2(1<=i<=n1)

則s1=s2

串的抽象數(shù)據(jù)類型ADTString{

數(shù)據(jù)對象:D={ai|ai∈CharacterSet,i=1,2,...,n,n≥0}數(shù)據(jù)關系:R1={<ai-1,ai>|ai-1,ai∈D,i=2,...,n}基本操作:

StrAssign(&T,chars)

StrCopy(&T,S)

DestroyString(&S)

StrEmpty(S)

StrCompare(S,T)

StrLength(S)

Concat(&T,S1,S2)SubString(&Sub,S,pos,len)Index(S,T,pos)Replace(&S,T,V)StrInsert(&S,pos,T)StrDelete(&S,pos,len)ClearString(&S)}ADTString

StrAssign(&T,chars)

初始條件:chars是字符串常量

操作結(jié)果:把chars賦為T的值

StrCopy(&T,S)

初始條件:串S存在

操作結(jié)果:由串S復制得串T

DestroyString(&S)

初始條件:串S存在

操作結(jié)果:串S被銷毀

StrEmpty(S)

始條件:串S存在

操作結(jié)果:若S為空串,則返回

TRUE,否則返回

FALSE

表示空串,空串的長度為零

StrCompare(S,T)

初始條件:串S和T存在

操作結(jié)果:若ST,則返回值

0

若ST,則返回值

0

若ST,則返回值

0例如:StrCompare(data,state)<0StrCompare(cat,case)>0

StrLength(S)

初始條件:串S存在

操作結(jié)果:返回S的元素個數(shù),

稱為串的長度

Concat(&T,S1,S2)

初始條件:串S1和S2存在

操作結(jié)果:用T返回由S1和S2

聯(lián)接而成的新串例如:

Concate(T,man,kind)

求得T=mankind

SubString(&Sub,S,pos,len)初始條件:

串S存在,1≤pos≤StrLength(S)

且0≤len≤StrLength(S)-pos+1操作結(jié)果:

用Sub返回串S的第pos個字符起長度為len的子串例如:

SubString(sub,commander,4,3)

求得sub=manSubString(sub,commander,1,9)求得sub=commanderSubString(sub,commander,9,1)求得sub=r子串為“串”中的一個字符子序列SubString(sub,commander,4,7)sub=?SubString(sub,beijing,7,2)=?sub=?SubString(student,5,0)=起始位置和子串長度之間存在約束關系長度為0的子串為“合法”串

Index(S,T,pos)

初始條件:串S和T存在,T是非空串,

1≤pos≤StrLength(S)

操作結(jié)果:若主串S中存在和串T值

相同的子串,則返回它在主

串S中第pos個

字符之后第一次出現(xiàn)的位

置;否則函數(shù)值為0

假設S=abcaabcaaabc,T=bca

Index(S,T,1)=2Index(S,T,3)=6Index(S,T,8)=0

“子串在主串中的位置”意指子串中的第一個字符在主串中的位序Replace(&S,T,V)

初始條件:串S,T和V均已存在,

且T是非空串

操作結(jié)果:用V替換主串S中出現(xiàn)

的所有與(模式串)T

相等的不重疊的子串假設S=abcaabcaaabca,T=bca若V=

x,則經(jīng)置換后得到

S=axaxaax若V=bc,則經(jīng)置換后得到

S=abcabcaabc

StrInsert(&S,pos,T)

初始條件:串S和T存在,

1≤pos≤StrLength(S)+1

操作結(jié)果:在串S的第pos個字符之前插入串T例如:S=chater,T=rac,則執(zhí)行StrInsert(S,4,T)之后得到

S=character

StrDelete(&S,pos,len)

初始條件:串S存在

1≤pos≤StrLength(S)-len+1

操作結(jié)果:從串S中刪除第pos個字符

起長度為len的子串

ClearString(&S)

初始條件:串S存在

操作結(jié)果:將S清為空串

對于串的基本操作集可以有不同的定義方法,在使用高級程序設計語言中的串類型時,應以該語言的參考手冊為準。

gets(str)輸入一個串;

puts(str)

輸出一個串;

strcat(str1,str2)串聯(lián)接函數(shù);

strcpy(str1,str2,k)串復制函數(shù);

strcmp(str1,str2)串比較函數(shù);

strlen(str)求串長函數(shù);例如:C語言函數(shù)庫中提供下列串處理函數(shù):在上述抽象數(shù)據(jù)類型定義的13種操作中串賦值StrAssign、等六種操作串復制Strcopy、構成串類型串比較StrCompare、的最小操作求串長StrLength、子集串聯(lián)接Concat求子串SubString

例如,可利用串比較、求串長和求子串等操作實現(xiàn)定位函數(shù)Index(S,T,pos)。

StrCompare(SubString(S,i,StrLength(T)),T)?

0

S串T串

T串iposn-m+1算法的基本思想為:intIndex(StringS,StringT,intpos){

//T為非空串。若主串S中第pos個字符之后存在與T相等的子串,則返回第一個這樣的子串在S中的位置,否則返回0

if(pos>0){n=StrLength(S);m=StrLength(T);i=pos;

while(i<=n-m+1){

SubString(sub,S,i,m);

if(StrCompare(sub,T)!=0)++i;

else

returni;

}//while

}//if

return0;//S中不存在與T相等的子串}//Index

串的邏輯結(jié)構和線性表極為相似,區(qū)別僅在于串的數(shù)據(jù)對象約束為字符集。

串的基本操作和線性表有很大差別。

在線性表的基本操作中,大多以“單個元素”作為操作對象;在串的基本操作中,通常以“串的整體”作為操作對象。

在程序設計語言中,串只是作為輸入或輸出的常量出現(xiàn),則只需存儲此串的串值,即字符序列即可。但在多數(shù)非數(shù)值處理的程序中,串也以變量的形式出現(xiàn)。串的表示和實現(xiàn)一、串的定長順序存儲表示二、串的堆分配存儲表示三、串的塊鏈存儲表示

#defineMAXSTRLEN255//用戶可在255以內(nèi)定義最大串長

typedef

unsignedcharSstring[MAXSTRLEN+1];//0號單元存放串的長度一、串的定長順序存儲表示

按這種串的表示方法實現(xiàn)的串的運算時,其基本操作為

“字符序列的復制”。

串的實際長度可在這個予定義長度的范圍內(nèi)隨意設定,超過予定義長度的串值則被舍去,稱之為“截斷”。特點:

typedefstruct{char*ch;

//若是非空串,則按串長分配存儲區(qū),

//否則ch為NULL

intlength;//串長度

}HString;二、串的堆分配存儲表示

通常,C語言中提供的串類型就是以這種存儲方式實現(xiàn)的。系統(tǒng)利用函數(shù)malloc()和free()進行串值空間的動態(tài)管理,為每一個新產(chǎn)生的串分配一個存儲區(qū),稱串值共享的存儲空間為“堆”。

C語言中的串以一個空字符為結(jié)束符,串長是一個隱含值。

這類串操作實現(xiàn)的算法為:先為新生成的串分配一個存儲空間,然后進行串值的復制。三、串的塊鏈存儲表示也可用鏈表來存儲串值,由于串的數(shù)據(jù)元素是一個字符,它只有8位二進制數(shù),因此用鏈表存儲時,通常一個結(jié)點中存放的不是一個字符,而是一個子串。存儲密度

=數(shù)據(jù)元素所占存儲位實際分配的存儲位

#defineCHUNKSIZE80

//可由用戶定義的塊大小

typedefstructChunk{

//

結(jié)點結(jié)構

charch[CUNKSIZE];

structChunk*next;

}Chunk;

typedefstruct{//串的鏈表結(jié)構

Chunk*head,*tail;//串的頭和尾指針

intcurlen;//串的當前長度

}LString;

這是串的一種重要操作,很多軟件,若有“編輯”菜單項的話,則其中必有“查找”子菜單項。串的模式匹配算法初始條件:串S和T存在,T是非空串,

1≤pos≤StrLength(S)。操作結(jié)果:若主串S中存在和串T值相同的子串返回它在主串S中第pos個字符之后第一次出

現(xiàn)的位置;否則函數(shù)值為0。首先,回憶一下串匹配(查找)的定義:INDEX(S,T,pos)

下面討論以定長順序結(jié)構表示串時的幾種算法。一、簡單算法二、首尾匹配算法三、KMP(D.E.Knuth,V.R.Pratt,J.H.Morris)算法intIndex(SStringS,SStringT,intpos){

//返回子串T在主串S中第pos個字符之后的位置。若不存在,

//則函數(shù)值為0。其中,T非空,1≤pos≤StrLength(S)。

i=pos;j=1;

while(i<=S[0]&&j<=T[0]){

if(S[i]==T[j]){++i;++j;}//繼續(xù)比較后繼字符

else

{i=i-j+2;j=1;}

//指針后退重新開始匹配

}

if(j>T[0])returni-T[0];

elsereturn0;}//Index一、

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論