1. 程式人生 > >資料結構》嚴蔚敏 串的ADT實現 用堆串儲存 演算法4.4

資料結構》嚴蔚敏 串的ADT實現 用堆串儲存 演算法4.4

跟前面的線性儲存是一個道理的,本質上還是順序儲存,只不過用了堆來動態分配,使串的長度不受限制,更加靈活
借用大佬一張圖:
在這裡插入圖片描述
在這裡插入圖片描述

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;
}