標籤:style blog color os ar for 資料 div 代碼
前面兩篇文章,分別介紹了字串的概念、抽象資料類型、KMP模式比對演算法。這篇文章,我們來學習字串的一些常用演算法。
字串的相關操作演算法
StrAssign:
/*功能:產生一個其值等於Chars的串T*/Status StrAssign(String T, char *chars){ int i; if (chars[0] > MAXSIZE) return ERROR; T[0] = chars[0]; //chars[0]存放的是字元chars的長度 T[0]存放著的是串T的長度 for (i = 1; i <= chars[0]; i++) T[i] = *(chars + i - 1); //將chars的字元依次存入T中 return OK;}
這個演算法的功能是建立字串,沒什麼複雜的地方。
StrCopy:
/*功能:由串S複製得串T*/Status StrCopy(String S, String T){ int i; for (i = 0; i <= S[0]; i++) T[i] = S[i]; //將S串的字元依次賦給T串 return OK;}
我們在C#中,需要複製某個字串給另一個字串,只需調用String類的Copy()方法即可。Copy()方法的具體演算法,其實就是上面的代碼所示範的。古語有云:”知其然,知其所以然”,編程需要鍛煉,不僅僅是鍛煉我們的編碼速度,而是要從編程中領悟編程的思想。學習經典演算法,就是領悟編程思想。
StrEmpty:
/*功能:判斷字串是否為空白串,是返回True,否則返回False*/Status StrEmpty(String S){ if (S[0] == 0) //字元長度為0,則為空白串 return TRUE; else return FALSE;}
判斷字串是否為空白的演算法,是不是感覺演算法其實也挺簡單的?簡單的需求就用簡單的演算法,其實演算法還是有難度的,特別是一些經典的演算法。但是不要氣餒,人生的樂趣就是在不斷克服苦難中得到的。只做簡單的事情,人生多無趣?
StrCompare:
/*功能:比較兩個字串操作:如果兩個串S>T,則傳回值>0;若S=T,則傳回值=0;若S<T,則傳回值<0*/int StrCompare(String S, String T){ int i; for (i = 1; i <= S[0] && i <= T[0]; ++i) { if (S[i != T[i]]) //判斷兩個字串中的字元是否相等 return S[i] - T[i]; //根據傳回值是否大於零,來判斷兩個串的大小 else return S[0] - T[0]; //如果兩個字串相等,返回0 }}
這個演算法,是判斷兩個字串是否相等。
ClearString:
/*功能:將串S清空為空白串*/Status ClearString(String S){ S[0] = 0; //將字元長度設定為0,串變為空白串。 return OK;}
這個演算法,是清Null 字元串。
StrConcat:
/*功能:用T返回S1和S2聯結而成的新串。若未截斷,返回True,否則返回FALSE*/Status Concat(String T, String S1, String S2){ int i; if (S1[0] + S2[0] <= MAXSIZE) //未截斷 { for (i = 1; i <= S1[0]; i++) T[i] = S1[i]; for (i = 1; i <= S2[0]; i++) T[S1[0] + i] = S2[i]; T[0] = S1[0] + S2[0]; return TRUE; } else //截斷 { for (i = 1; i <= S1[0]; i++) T[i] = S1[i]; for (i = 1; i <= MAXSIZE - S1[0]; i++) T[S1[0] + 1] = S2[i]; S1[0] = MAXSIZE; return FALSE; }}
這個演算法的功能是實現,兩個字串的拼接。需要注意的是,拼接時可能出現空間不足,截斷字串的可能。所以,演算法中要分情況來操作。
我們來看看SubString方法的實現,這個方法一定不陌生吧。
/*功能:用Sub返回S串中Pos位置起len個長度的字串初始條件:串S存在,1<=pos<=StrLength(S) 0<=len<=StrLength(S)-Pos+1*/Status SubString(String Sub, String S, int pos, int len){ int i; if (pos<1 || pos>S[0] || len<0 || len>S[0] - pos + 1) return FALSE; for ( i = 1; i <= len; i++) Sub[i] = S[pos + i - 1]; Sub[0] = len; return OK;}
Index:
/*功能:返回字串T在主串S的pos位置之後的位置,若不存在,傳回值為0;初始條件:串S、T存在,1<=Pos<=StrLength(S)*/int Index(String S, String T, int pos){ int i = pos; //i的當前位置 int j = 1; //子串T的當前位置 while (i <= S[0]) { if (S[i] == T[j]) //當前位置字元相等,繼續匹配 { ++i; ++j; } else //當前位置匹配不相等 { j = 1; // j回溯到字串的第一個位置 i = i - j + 2; //主串位置回溯到上次匹配成功位置的下個位置, } } if (j > T[0]) return i - T[0]; else return 0;}
其實這個方法就是我在資料結構與演算法---字串(中)文章中,講到的樸素模式比對的演算法。
我們再看一個通過調用其它字串方法來完成匹配的演算法:
/*功能:返回子串T在主串S中pos位置之後出現的位置,如不存在返回0初始條件:1<=pos<=StrLength(S) */int Index2(String S, String T, int pos){ int i = pos; int n, m; //n表示主串S的長度,m表示子串T的長度 if (i > 0) { n = strLength(S); //通過調用Strlength()來擷取主串S的長度 m = strLength(T); //通過調用Strlength()來擷取子串T的長度 while (i <= n - m + 1) { SubString( sub, S, i,n); //通過調用SubString()來擷取從i位置起n個長度的子串sub if (StrCompare(T, sub) == 0) //通過調用StrCompare方法,來判斷擷取的Sub子串是否已字串T相等 return i; //相等則返回i位 else i++; //不相等,則i回溯到下個位置 } } return 0;}
通過觀察這個演算法,調用了之前講到的一些演算法。其實,字串的基本操作也就是那麼幾個演算法。複雜的操作,就需要方法之間互相配合。
好了, 字串這章已經講完了。
資料結構與演算法---字串(下)