【C語言】資料結構C語言版 實驗4 棧與字串
阿新 • • 發佈:2020-12-09
/* 利用順序棧結構,編寫演算法函式void Dto16(unsigned int m)實現十進位制無符號整數m到十六進位制數的轉換功能。 */ /**********************************/ /*檔名稱:lab4_01.c */ /**********************************/ #include "seqstack.h" /*請將本函式補充完整,並進行測試*/ void Dto16(int m) { seqstack s; /*定義順序棧*/ init(&s); printf("十進位制數%u對應的十六進位制數是:",m); //%d 輸出有符號十進位制數 %u 輸出無符號十進位制數 while (m) { push(&s,m%16); m=m/16; } while (!empty(&s)) printf("%x",pop(&s)); printf("\n"); } int main() { int m; printf("請輸入待轉換的十進位制數:\n"); scanf("%u",&m); Dto16(m); return 0; }
/* 利用鏈式棧結構,編寫演算法函式void Dto16(unsigned int m)實現十進位制無符號整數m到十六進位制數的轉換功能。 */ /**********************************/ /*檔名稱:lab4_02.c */ /**********************************/ #include "linkstack.h" /*請將本函式補充完整,並進行測試*/ void Dto16(unsigned int m) { linkstack s; s=init(); printf("十進位制數%u對應的十六進位制數是:",m); while (m) { s=push(s,m%16); m/=16; } while (!empty(s)) { printf("%x",read(s)); s=pop(s); } printf("\n"); } int main() { unsigned int m; printf("請輸入待轉換的十進位制數:\n"); scanf("%u",&m); Dto16(m); return 0; }
#include <stdio.h> #include "stack.h" /*引入自定義的字元棧結構*/ /**********************/ /* 判斷是否為運算子 */ /*********************/ int is_op(char op) { switch(op) { case '+': case '-': case '*': case '/':return 1; default:return 0; } } /****************************/ /* 判斷運算子的優先順序 */ /****************************/ int priority(char op) { switch(op) { case '(':return 0; case '+': case '-':return 1; case '*': case '/':return 2; default: return -1; } } /*********************************/ /*中綴表示式,轉換為字尾表示式 */ /*********************************/ void postfix(char e[],char f[]) {seqstack opst; int i,j; initstack(&opst); push(&opst,'\0'); i=j=0; while (e[i]!='\0') { if ((e[i]>='0' && e[i]<='9') || e[i]=='.') f[j++]=e[i]; /*數字*/ else if (e[i]=='(') /*左括號*/ push(&opst,e[i]); else if (e[i]==')') /*右括號*/ { while (stacktop(&opst)!='(') f[j++]=pop(&opst); pop(&opst); /*'('出棧*/ } else if (is_op(e[i])) /* '+ ,-, *, /' */ {f[j++]=' '; /*用空格分開兩個運算元*/ while (priority(stacktop(&opst))>=priority(e[i])) f[j++]=pop(&opst); push(&opst,e[i]); /*當前元進棧*/ } i++; /*處理下一元*/ } while (!stackempty(&opst)) f[j++]=pop(&opst); f[j]='\0'; } /****************************************/ /* 將數字字串轉變成數值 */ /****************************************/ float readnumber(char f[],int *i) {float x=0.0; int k=0; while (f[*i]>='0' && f[*i]<='9') /*處理整數部分*/ { x=x*10+(f[*i]-'0'); (*i)++; } if (f[*i]=='.') /*處理小數部分*/ { (*i)++; while (f[*i]>='0' && f[*i]<='9') { x=x*10+(f[*i]-'0'); (*i)++; k++; } } while (k!=0) { x=x/10.0; k=k-1; } printf("\n*%f*",x); return(x); } /****************************************/ /* 字尾表示式求值程式 */ /****************************************/ double evalpost(char f[]) { double obst[50]; /*運算元棧*/ int i=0,top=-1; /*請將本函式補充完整*/ float x; while(f[i]!='\0') { if(f[i]>='0'&&f[i]<='9') obst[++top]=readnumber(f,&i); else if(f[i]==' ') i++; else if(f[i]=='+') { x=obst[top--]; obst[top]=x+obst[top]; i++; } else if(f[i]=='-') { x=obst[top--]; obst[top]=x-obst[top]; i++; } else if(f[i]=='*') { x=obst[top--]; obst[top]=x*obst[top]; i++; } else if(f[i]=='/') { x=obst[top--]; obst[top]=x/obst[top]; i++; } } return obst[top]; } /* 主程式:輸入中綴表示式,經轉換後輸出字尾表示式 */ int main() { char e[50],f[50]; int i,j; printf("\n\n請輸入中綴表示式:\n"); gets(e); postfix(e,f); i=0; printf("\n\n對應的字尾表示式為: ["); while (f[i]!='\0') printf("%c",f[i++]); printf("]"); printf("\n\n計算結果為 :"); printf("\n\n%f",evalpost(f)); return 0; }
/* 已知字串採用帶結點的鏈式儲存結構(詳見linksrting.h檔案), 請編寫函式linkstring substring(linkstring s,int i,int len), 在字串s中從第i個位置起取長度為len的子串,函式返回子串連結串列。 */ #include "linkstring.h" /*請將本函式補充完整,並進行測試*/ linkstring substring(linkstring s, int i, int len) { linkstring head,pos=s->next,makenode,newlist; int cnt=0; head=(linkstring)malloc(sizeof(linknode)); head->next=NULL; newlist=head; while(pos) { if(cnt>=i&&cnt<=i+len-1) { makenode=(linkstring)malloc(sizeof(linknode)); makenode->data=pos->data,makenode->next=NULL; newlist->next=makenode; newlist=makenode; } if(cnt>=i+len) break; cnt++; pos=pos->next; } return head; } int main() { linkstring str1,str2; str1=creat(); /*建字串連結串列*/ print(str1); str2=substring(str1,3,5); /*測試,從第3個位置開始取長度為5的子串,請自行構造不同測試用例*/ print(str2); /*輸出子串*/ delList(str1); delList(str2); return 0; }
/* 字串採用帶頭結點的連結串列儲存,設計演算法函式void delstring(linkstring s, int i,int len) 在字串s中刪除從第i個位置開始,長度為len的子串。 */ /**********************************/ /*檔名稱:lab4_05.c */ /**********************************/ #include "linkstring.h" /*請將本函式補充完整,並進行測試*/ void delstring(linkstring s, int i, int len) { linkstring p,q,r; int k=1; p=s->next; while(k<i&&p) //查詢待刪除子串的起始位置 { q=p; p=p->next; k++; } if(!p) //如果s串長度小於i,則無法刪除 return; else { k=1; while(k<len&&p) //從第i個位置開始查詢待刪除子串的終點 { p=p->next; k++; } if(!p) //如果s串中i後面的長度小於len,則無法刪除 return ; else { if(!q) //如果待刪除子串位於s最前面 { r=s; s=p->next; } else //子串位於中間或者後面 { r=q->next; q->next=p->next; } p->next=NULL; //待刪除子串最後置為空 while(r) { p=r; r=r->next; free(p); //逐個釋放子串中的結點 } } } } int main() { linkstring str; str=creat(); /*建字串連結串列*/ print(str); delstring(str,2,3); /*測試,從第2個位置刪除長度為3的子串,請自行構造不同的測試用例 */ print(str); /*輸出*/ delList(str); return 0; }
/* 字串採用帶頭結點的連結串列儲存,編寫函式linkstring index(linkstring s, linkstring t), 查詢子串t在主串s中第一次出現的位置,若匹配不成功,則返回NULL。 */ #include "linkstring.h" /*請將本函式補充完整,並進行測試*/ linkstring index(linkstring s, linkstring t) { linkstring p,s1,t1; p=s->next; while(p) //p記錄匹配的起點 { s1=p; //s1記錄s比較的當前位置 t1=t->next; //s2記錄t比較的當前位置 while(s1&&t1&&s1->data==t1->data) { s1=s1->next; t1=t1->next; } if(!t1) return p; //如果匹配成功,則返回p p=p->next; } return NULL; } int main() { linkstring s,t,p=NULL; s=creat(); /*建立主串連結串列*/ t=creat(); /*建立子串連結串列*/ print(s); print(t); p=index(s,t); if(p) printf("匹配成功,首次匹配成功的位置結點值為%c\n",p->data); else printf("匹配不成功!\n"); delList(s); delList(t); return 0; }
/* 利用樸素模式匹配演算法,將模式t在主串s中所有出現的位置儲存在帶頭結點的單鏈表中。 */ #include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct node { int data; struct node *next; }linknode; typedef linknode *linklist; /*樸素模式匹配演算法,返回t中s中第一次出現的位置,沒找到則返回-1,請將程式補充完整*/ int index(char *s,char *t) { int m,n,i,j,k; m=strlen(s); n=strlen(t); for(i=0;i<=m-n;i++) { k=i; j=0; while(j<n) { if(s[k]==t[j]) { k++; j++; } else break; } if(j==n) return i; } return -1; } /*利用樸素模式匹配演算法,將模式t在s中所有出現的位置儲存在帶頭結點的單鏈表中,請將函式補充完整*/ linklist indexall(char *s,char *t) { linklist head,p,r; int m,n,i,j,k; head=(linklist)malloc(sizeof(linknode)); r=head; m=strlen(s); n=strlen(t); for(i=0;i<=m-n;i++) { k=i; j=0; while(j<n) { if(s[k]==t[j]) { k++; j++; } else break; } if(j==n) { p=(linklist)malloc(sizeof(linknode)); p->data=i; r->next=p; r=p; } } r->next=NULL; return head; } /*輸出帶頭結點的單鏈表*/ void print(linklist head) { linklist p; p=head->next; while(p) { printf("%5d",p->data); p=p->next; } printf("\n"); } int main() { char s[80],t[80]; linklist head; printf("請輸入主串:\n"); gets(s); printf("請輸入模式串:\n"); gets(t); int k=index(s,t); printf("k=%d",k); head=indexall(s,t); printf("\n[ %s ]在[ %s ]中的位置有:\n",t,s); print(head); return 0; }
/* 編寫快速模式匹配KMP演算法,請將相關函式補充完整。 */ #define maxsize 100 typedef struct{ char str[maxsize]; int length ; } seqstring; /*求模式p的next[]值,請將函式補充完整*/ void getnext(seqstring p,int next[]) { int i,j; i=0;j=-1; next[0]=-1; while(i<p.length) { if(j==-1||p.str[i]==p.str[j]) { ++i; ++j; next[i]=j; } else j=next[j]; } for(i=0;i<p.length;i++) printf("%3d",next[i]); } /*快速模式匹配演算法,請將函式補充完整*/ int kmp(seqstring t,seqstring p,int next[]) { int i=0,j=0; while(i<t.length&&j<p.length) { if(j==-1||t.str[i]==p.str[j]) { i++; j++; } else j=next[j]; } return j==p.length?i-p.length:-1; } int main() { seqstring t, p; int next[maxsize],pos; printf("請輸入主串:\n"); gets(t.str); t.length=strlen(t.str); printf("請輸入模式串:\n"); gets(p.str); p.length=strlen(p.str); getnext(p,next); pos=kmp(t,p,next); printf("\n"); printf("%d",pos); return 0; }