浙江中醫藥大學-《資料結構》(C語言版)-棧、佇列、串、陣列
阿新 • • 發佈:2019-01-05
ZCMU-Data Structure (C language)
Part 1 Stack and Queue
1、棧和佇列也是線性表,特殊性在於棧和佇列的基本操作是線性表操作的子集,是操作受限的線性表。
2、棧是限定僅在表尾(棧頂)進行插入或者刪除操作的線性表,它是先進後出(後進先出)的線性表。
3、佇列是一種先進先出的線性表。只允許在隊尾進行插入,在隊頭進行刪除。
4、順序棧的表示與實現
1)初始化
1)初始化
無需設頭結點
1)迴圈佇列初始化
1)初始化
12、特殊矩陣的壓縮儲存(資料結構 嚴蔚敏 P100-102)
2)入棧s.base=new SElemType[MAXSIZE];//為順序棧動態分配一個最大容量為MAXSIZE的陣列空間 if(!s.base) exit(OVERFLOW);//儲存分配失敗 s.top=s.base;//top初始為base,空棧 s.stacksize=MAXSIZE;//置棧的最大容量為MAXSIZE return OK;
if(s.top-s.base==s.stacksize) return ERROR;//棧滿
*s.top++=e;
return OK;
3)出棧
if(s.top==s.base) return ERROR;//棧空
e=*--s.top;//棧頂指標減1,將棧頂元素賦給e
return OK;
4)取棧頂元素
if(s.top!=s.base)//棧非空
return *(s.top-1);//返回棧頂元素的值,棧頂指標不變
5、鏈棧的表示與實現
通常,鏈棧用單鏈表表示,由於棧主要的操作是在棧頂進行插入或刪除操作,顯然連結串列最好,且沒必要向單鏈表一樣附加一個頭結點。s=NULL;
return OK;
2)入棧
鏈棧入棧前不需要判斷棧是否滿,只需要為入棧元素動態分配一個結點空間。
p=new StackNode;//生成新結點
p->data=e;//將新結點資料域置為e
p->next=s;//將新結點插入棧頂
s=p;//修改棧頂指標為p;
return OK;
3)出棧
鏈棧在出棧前需要判斷棧是否為空,但是鏈棧在出棧後需要釋放棧元素的棧頂空間。
4)取棧頂元素if(s==NULL) return ERROR;//棧空 e=s->data;//將棧頂元素賦給e p=s;//將p臨時儲存棧頂元素空間,以備釋放 s=s->next;//修改棧頂指標 delete p; return OK:
if(S!=NULL)
return s->data; //返回棧頂元素的值,棧頂指標不變
6、迴圈佇列-佇列的順序表示和實現
在非空佇列中,頭指標始終指向佇列頭元素,尾指標始終指向佇列尾元素的下一個位置1)迴圈佇列初始化
q.base=new QElemType[MAXSIZE];
if(!q.base) exit(OVERFLOW);
q.front=q.rear=0;//頭指標和尾指標為0,佇列為空
return OK;
2)求迴圈佇列的長度
return (q.rear-q.front+MAXSIZE)%MAXSIZE;
3)入隊
if((q.rear+1)%MAXSIZE==q.front)//判斷隊滿
return ERROR;
q.base[q.rear]=e;//新元素插入隊尾
q.rear=(q.rear+1)%MAXSIZE;//隊尾指標+1
return OK;
4)出隊
if(q.front==q.rear) return ERROR;//隊空
e=q.base[q.front];//保持隊頭元素
q.front=(q.front+1)%MAXSIZE;//隊頭指標+1
return OK;
5)取隊頭元素
if(q.front!=q.rear)//佇列非空
return q.base[q.front];//返回隊頭元素的值,隊頭指標不變
7、鏈隊-佇列的鏈式表示和實現
示意圖:
1)初始化
Q.rear=(QueuePtr)malloc(sizeof(QNode) );
Q.front = Q.rear;
if(!Q.front) return(OVERFLOW);
Q.front -> next = NULL;
return OK;
2)入隊
鏈隊在入隊前不需要判斷隊是否滿,需要為入隊元素動態分配一個結點
p = ( QueuePtr )malloc(sizeof(QNode));
if(!p) return(OVERFLOW);
p->data = e;
p -> next = NULL;
Q.rear ->next = p;
Q.rear = p;
return OK;
3)出隊
if(Q.front == Q.rear) retrun ERROR;
p = Q.front -> next;
e = p->data;
Q.front->next = p->next;
if(Q.rear == p) Q.rear = Q.front ;
free(p);
return OK;
鏈隊出隊操作時還需要考慮當佇列最後一個元素被刪後,佇列尾指標也丟失,因此需要對隊尾指標重新賦值(指向頭結點)。
4)取隊頭元素
if(Q.front!=Q.rear)
return Q.front->next->data;//隊頭指標不變
Part 2 String and Array
8、串是一種內容受限的線性表,特殊性在於資料元素是一個字元,串中任意個連續的字元組成的子序列稱為子串;只有當兩個串的長度相等並且各個對應位置的字元都相等時才相等。在串的基本操作中,通常以“串的整體”作為操作物件。
9、串的模式匹配演算法
例如
T=“abcac”; S=“ababcabcacbab”
- 第一趟匹配 a b a b c a b c a c b a b (i=3)
- a b c (j=3)
- 第二趟匹配 a b a b c a b c a c b a b (i=2)
- a (j=1)
- 第三趟匹配 a b a b c a b c a c b a b (i=7)
- a b c a c (j=5)
- 第四趟匹配 a b a b c a b c a c b a b (i=4)
- a (j=1)
- 第五趟匹配 a b a b c a b c a c b a b (i=5)
- a (j=1)
- 第六趟匹配 a b a b c a b c a c b a b (i=11)
- a b c a c (j=6) 成功!
- KMP演算法的改進在於:
- 每一趟匹配過程中出現字元比較不等時,不需要回朔i指標
- 只要利用已經“部分匹配”結果,調整j指標,即將模式向右滑動儘可能遠的一段距離,來個提高演算法效率。
- 上例的KMP演算法匹配過程示意如下
- 第一趟匹配 a b a b c a b c a c b a b (i=3)
- a b c (j=3)
- 第二趟匹配 a b a b c a b c a c b a b (i=3 -> 7)
- a b c a c (j=1 -> 5)
- 第三趟匹配 a b a b c a b c a c b a b (i=7 -> 11)
- (a)b c a c (j=2 -> 6)
- 顯然演算法複雜度為O(n+m)
int Index_KMP(SString S, SString T, int pos)
{ // 利用模式串T的next函式求T在主串
// S中第pos個字元之後第一次出現的位置;否則返回0。
i = pos; j = 1;
while(i<=S[0] && j <= T[0]){
if(j == 0 || S[i] == T[j]){ ++i; ++j;} // 繼續比較後續字元
else j = next[j]; // 模式串向後移
}
if(j > T[0]) return i-T[0]; // 匹配成功
else return 0; // 匹配不成功
} // Index_KMP
10、陣列是型別相同的資料元素構成的有序集合,其特點是結構中的元素本身是具有某種結構的資料,但屬於同一資料型別。由於陣列一般不做插入或者刪除的操作,採用順序儲存結構最合適。
11、陣列計算方法以例題形式給出
12、特殊矩陣的壓縮儲存(資料結構 嚴蔚敏 P100-102)