資料結構》嚴蔚敏 串的ADT實現 用堆串儲存 演算法4.4
阿新 • • 發佈:2019-01-13
跟前面的線性儲存是一個道理的,本質上還是順序儲存,只不過用了堆來動態分配,使串的長度不受限制,更加靈活
借用大佬一張圖:
4_4.h
#ifndef _4_4_H #define _4_4_H #include<stdio.h> #include<stdlib.h> #include<string.h> #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define OVERFLOW -1 #define MAXSIZE 40 #define MAXSTRLEN 10 typedef int Status; typedef struct { char *ch; int length; }Hstring; void InitString(Hstring *T); Status StrAssign(Hstring *T,char *chars); int StrLength(Hstring T); Status StrCopy(Hstring T,Hstring *S); Status StrEmpty(Hstring T); int StrCompare(Hstring S,Hstring T); Status ClearString(Hstring *T); Status SubString(Hstring *Sub,Hstring T,int pos,int len); Status StrConcat(Hstring *T,Hstring S1,Hstring S2); Status Replace(Hstring *S,Hstring T,Hstring V); Status DestroyString(Hstring *S); int Index(Hstring S,Hstring T,int pos); Status StrTraverse(Hstring T); Status StrDelete(Hstring *S,int pos,int len ); Status StrInsert(Hstring *S,int pos,Hstring T); #endif
4_4.c
//堆分配儲存串 //也是順序結構,不過每一次都重新分配空間,所以對串的長度就沒有限制 //查一下用堆分配是時間複雜度變低了嗎,還是就是這一個好處呢? #include "4_4.h" //初始化為空串 void InitString(Hstring *T) { (*T).ch = NULL; (*T).length = 0; } Status StrAssign(Hstring *T,char *chars) { int i,j; // if( (*T).ch != NULL ) // free( (*T).ch ); i = strlen(chars); if(!i) //這也是一個我打死都想不到的地方。。。 { (*T).ch = NULL; (*T).length = 0; } else { (*T).ch = (char*)malloc(i*sizeof(char));//注意這裡為i*sizeof if( !((*T).ch) ) exit(OVERFLOW); (*T).length = i; //話說也沒有給length分配空間的,所以他到哪裡去了? //這裡這是一個堆串,堆串是個結構體 //char指標指向動態分配的記憶體來儲存字元,length用來儲存串的長度。 for(j = 0;j < i;j++) { (*T).ch[j] = chars[j]; } } return OK; } int StrLength(Hstring T) { return T.length; } //由串T複製得到串S //複製肯定沒問圖的 為什麼打印不出來??? Status StrCopy(Hstring T,Hstring *S) { //這裡不太會寫 if( (*S).ch != NULL )//是這樣的,判斷S.ch 而不是S free( (*S).ch );//這裡不知道對不對 (*S).ch = (char*)malloc(T.length * sizeof(char)); //怎樣分配和T一樣大小的空間呢 //這邊 if( !(*S).ch ) exit(OVERFLOW); for(int i = 0;i<T.length;i++) { (*S).ch[i] = T.ch[i]; } (*S).length = T.length; //don't forget //StrTraverse((*S)); //真的很不明白,懂了 忘記給length賦值了。。。尷尬臉 return OK; } Status StrEmpty(Hstring T) { return T.length == 0; } int StrCompare(Hstring S,Hstring T) //這裡應該有點小問題 { // for(int i = 0;i < S.length;) // { // if(S.ch[i] == T.ch[i]) // i++; // else if(S.ch[i] > T.ch[i]) // return 1; // else // return -1; // } // if(T.length > S.length) // return -1; // else // return 0; // 這種方法簡潔,直接判斷當不等於的嘶吼返回,到最後如果都等於就比較字串長度 int i; for(i = 0;i<S.length && i<T.length;i++) { if(S.ch[i] != T.ch[i]) return S.ch[i]-T.ch[i]; } return S.length - T.length; } Status ClearString(Hstring *T) { if((*T).ch) //這一步我給忘記了。。 { free((*T).ch); (*T).ch = NULL; } (*T).length = 0; return OK; } Status SubString(Hstring *Sub,Hstring T,int pos,int len) { int i,j; //先判斷pos len是否合法。我已經忘記一百萬次了 if(pos<1 || pos>T.length || len<0 || pos+len-1>T.length) return ERROR; //釋放舊的空間,這個我也忘記一百萬次了,但是加上它會報錯誒 // if((*Sub).ch) // free((*Sub).ch); if(!len) { (*Sub).ch = NULL; (*Sub).length = 0; } else { (*Sub).ch = (char*)malloc(len * sizeof(char)); if(!(*Sub).ch) exit(OVERFLOW); for(i = 0; i<len; i++) { (*Sub).ch[i] = T.ch[i+pos-1];//oh,還沒有給他分配空間,所以有段錯誤 } Sub->length = len; } return OK; } //這塊不是很理解 int Index(Hstring S,Hstring T,int pos) { int s,t,i; Hstring tmp; InitString(&tmp); if(pos > 0) //我打死都想不起來要判斷一下。。 { s = StrLength(S); t = StrLength(T); i = pos; while(i+t-1 <= s) { SubString(&tmp,S,i,t); if(StrCompare(tmp,T) == 0) //直接就這樣比較,也不看看是不是都相等啊 return i; else i++; } } return 0; } //因為是動態分配,所以不存在截斷問題 Status StrConcat(Hstring *T,Hstring S1,Hstring S2) { int i; // if((*T).ch) //釋放舊的空間,這一步不要忘記了 // free((*T).ch); //看來這個得慎用。總是報錯 (*T).length = S1.length + S2.length; (*T).ch = (char*)malloc((*T).length*sizeof(char)); if(!(*T).ch) exit(OVERFLOW); for(i = 0;i<S1.length;i++) (*T).ch[i] = S1.ch[i]; for(i = 0;i<S2.length;i++) (*T).ch[S1.length+i] = S2.ch[i]; return OK; } Status Replace(Hstring *S,Hstring T,Hstring V) { int i; if(StrEmpty(T)) return ERROR; i = Index(*S,T,1); while(i != 0) { StrDelete(S,i,StrLength(T)); StrInsert(S,i,V); i += StrLength(V); i = Index(*S,T,i); } return OK; } Status StrDelete(Hstring *S,int pos,int len ) { int i; if(StrEmpty(*S)) return ERROR; if(pos < 1 || pos+len-1 > (*S).length || len<0) return ERROR; for(i = pos-1;i+len<=(*S).length;i++) (*S).ch[i] = (*S).ch[i+len]; (*S).length -= len; (*S).ch = (char*)realloc( (*S).ch, (*S).length*sizeof(char)); return OK; } Status StrInsert(Hstring *S,int pos,Hstring T) { int i; if(pos<1 || pos>(*S).length) return ERROR; if(StrEmpty(T)) return ERROR; else { (*S).ch = (char*)realloc((*S).ch, ((*S).length+T.length) *sizeof(char)); if(!(*S).ch) exit(OVERFLOW); for(i = (*S).length -1;i>pos-1;i--) (*S).ch[i+T.length] = (*S).ch[i]; for(i = 0;i<T.length;i++) (*S).ch[pos-1+i] = T.ch[i]; (*S).length += T.length; } return OK; } Status DestroyString(Hstring *S) { //堆串不能被銷燬 return ERROR; } Status StrTraverse(Hstring T) { for(int i = 0;i<T.length;i++) printf("%c",T.ch[i]); printf("\n"); return OK; }
測試用例(寫的比較水)
int main(int argc, char const *argv[]) { Hstring T,S,W,V,X,Y; char *chars = "hello,yannie~"; char *chars1 = "yannie"; char *chars2 = "*_*"; StrAssign(&T,chars); StrAssign(&V,chars1); StrAssign(&X,chars2); StrTraverse(T); int i = StrLength(T); printf("T's length is %d\n", i); printf("Now i will copy T to S\n"); StrCopy(T,&S); printf("S: "); StrTraverse(S); printf("judge the String W is empty or not: "); int tmp = StrEmpty(W); if(tmp == 1) printf("Yes!\n"); else printf("No!\n"); printf("test the T and S: "); int j = StrCompare(S,T); if(j == 0) printf("the same big!\n"); if(j > 0) printf("S is bigger!\n"); if(j < 0) printf("T is bigger!\n"); printf("from T find sit 2 to sit 4,and stored in W\n"); SubString(&W,T,2,4); printf("W: "); StrTraverse(W); printf("whether V in T after pos = 2 ?if yes,return the sitution: "); int k = Index(T,V,2); printf("%d\n",k); printf("delete S sit 2-5\n"); printf("origin S: "); StrTraverse(S); StrDelete(&S,2,5); printf("Now S: "); StrTraverse(S); printf("insert X into S(before sit 2) \n"); StrInsert(&S,2,X); printf("Now S: "); StrTraverse(S); printf("concat S and X:\n"); StrConcat(&Y,S,X); printf("Now Y: "); StrTraverse(Y); return 0; }