1. 程式人生 > >數據結構(六)串

數據結構(六)串

單引號 線性 ear true pty 基本操作 運算 管理 舉例

串的基本概念

1、串的基本概念

  字符串(String)是由零個或多個字符組成的有限序列。記為: S = ′a1 a2 … an′( n ≥ 0 ) 其中 S 是串的名字,用單引號括起來的字符序列是串的值,每個 ai( 1 ≤ i≤ n)可 以是字母、數字或其他字符。 n 是串中字符的個數,稱為串的長度,n=0 時的串稱為空串( Null String)。

  需要特別指出的是,串值必須用一對單引號括起來( C 語言中是雙引號),但單引號是界限符,它不屬於串,其作用是避免與變量名或常量混淆。

  ·子串:串中任意個連續的字符組成的子序列稱為該串的子串。

  ·主串:包含子串的串相應地稱為主串。可見,子串是主串的一部分。

  · 子串在主串中的位置:通常將字符在串中的序號稱為該字符在串中的位置。子串在主串中的位置則以子串的第一個字符在主串中的位置 來表示

  串相等:當且僅當兩個串的值相等時,稱這兩個串是相等的,即只有當 兩個串的長度相等,並且每個對應位置的字符都相等時才相等。

  串也是一種特定的線性表,串的邏輯結構和線性表極為相似,其特定性僅在於串的數據對象限定為字符集

2、串的抽象數據類型定義如下:

ADT String {

數據對象: D={ ai | ai∈ CharacterSet,記為 V,i=1 ,2 ,…, n,n≥ 0 }

結構關系: R={< ai,ai + 1 >| ai,ai + 1 ∈ V,i=1 ,…, n-1 ; n-1 ≥ 0 }

基本操作:

( 1 ) StrAsign( S,chars)

操作前提: chars 是字符串常量。

操作結果:生成一個值等於 chars 的串 S。

( 2 ) StrInsert( S,pos,T)

操作前提:串 S 存在,1 ≤ pos≤ StrLength( S)+ 1 。

操作結果:在串 S 的第 pos 個字符之前插入串 T。

( 3 ) StrDelete( S,pos,len)

操作前提:串 S 存在,1 ≤ pos≤ StrLength( S)+ 1 。

操作結果:從串 S 中刪除第 pos 個字符起長度為 len 的子串。

( 4 ) StrCopy( S,T)

操作前提:串 S 存在。

操作結果:由串 T 復制得串 S。

( 5 ) StrEmpty( S)

操作前提:串 S 存在。

操作結果:若串 S 為空串,則返回 TRUE,否則返回 FALSE。

( 6 ) StrCompare( S,T)

操作前提:串 S 和 T 存在。 操作結果:若 S>T,則返回值>0 ;如 S=T,則返回值=0 ;若 S<T,則返回值<0 。

( 7 ) StrLength( S)

操作前提:串 S 存在。

操作結果:返回串 S 的長度,即串 S 中的字符個數。

( 8 ) StrClear( S)

操作前提:串 S 存在。

操作結果:將 S 清為空串。

( 9 ) StrCat( S,T)

操作前提:串 S 和 T 存在。

操作結果:將串 T 的值連接在串 S 的後面。

( 10 ) SubString( Sub,S,pos,len)

操作前提:串 S 存在,1 ≤ pos≤ StrLength( S)且 1 ≤ len≤ StrLength( S)- pos+1 。

操作結果:用 Sub 返回串 S 的第 pos 個字符起長度為 len 的子串。

( 11 ) StrIndex( S,pos,T)

操作前提:串 S 和 T 存在,T 是非空串,1 ≤ pos≤ StrLength( S)。

操作結果:若串 S 中存在和串 T 相同的子串,則返回它在串 S 中第 pos 個字符 之 後第一次出現的位置;否則返回 0 。

( 12 ) StrReplace( S,T,V)

操作前提:串 S、 T 和 V 存在且 T 是非空串。

操作結果:用 V 替換串 S 中出現的所有與 T 相等的不重疊的子串。

( 13 ) StrDestroy( S)

操作前提:串 S 存在。

操作結果:銷毀串 S。

}ADT string

串的順序存儲結構

串的順序存儲結構有定長順序串、堆串。

1、定長順序串

  定長順序串是將串設計成一種靜態結構類型,串的存儲分配是在編譯時完成的

1)定長順序串存儲結構

定長順序串類型定義如下:

#define MAXLEN 40 
typedef struct 
{      /*串結構定義*/ 
    char ch[ MAXLEN]; 
    int len; 
}SString; 

  其中 MAXLEN 表示串的最大長度,ch 是存儲字符串的一維數組,每個分量存儲一 個字符, len 是字符串的長度。

2).定長順序串基本操作的實現

( 1 )串插入函數

【問題分析】在進行順序串的插入時,插入位置 pos 將串分為兩部分(假設為 A、 B,長度為 LA、 LB)及待插入部分(假設為 C,長度為 LC),則串由插入前的 AB 變為 ACB,由於是順序串, 插入會引起元素的移動。可能出現以下三種情況:

  ①插入後串長( LA+LC +LB)≤ MAXLEN,則將 B 後移 LC 個元素位置,再將 C 插入。

  ②插入後串長>MAXLEN 且 pos+LC≤ MAXLEN,則 B 後移時會有部分字符被舍棄。

  ③插入後串長> MAXLEN 且 pos +LC >MAXLEN,則 B 的全部字符被舍棄(不需後移),並 且 C 在插入時也有部分字符被舍棄。

【算法描述】

 StrInsert(SString *s, int pos, SString t) 
 /*在串 s 中下標為 pos 的字符之前插入串 t */ 
 { int i; 
    if (pos<0 || pos>s->len) return(0); /*插入位置不合法*/ 
    if (s->len + t.len<=MAXLEN)
    {   /*插入後串長≤MAXLEN*/     
        for (i=s->len + t.len-1;i>=t.len + pos;i--)     
            s->ch[i]=s->ch[i-t.len];     
        for (i=0;i<t.len;i++) s->ch[i+pos]=t.ch[i];       
            s->len=s->len+t.len;     
    } 
    else if (pos+t.len<=MAXLEN) 
    {/*插入後串長>MAXLEN,但串 t 的字符序列可以全部插入*/     
        for (i=MAXLEN-1;i>t.len+pos-1;i--) 
            s->ch[i]=s->ch[i-t.len];     
        for (i=0;i<t.len;i++) s->ch[i+pos]=t.ch[i];     
        s->len=MAXLEN;     
    } 
    else {  /*插入後串長>MAXLEN,並且串 t 的部分字符也要舍棄     
        for (i=0;i<MAXLEN-pos;i++) s->ch[i+pos]=t.ch[i];     
        s->len=MAXLEN;     
        } 
        return(1); 
}

  實現順序串插入的算法其實現復雜度為: O( s->len+t.len)。

2、堆串

  字符串包括串名與串值兩部分,而串值采用堆串存儲方法存儲,串名用符號表 存儲。

  堆串存儲方法:仍以一組地址連續的存儲單元順序存放串中的字符,但它們的 存儲空間是在程序執行過程中是動態分配的

  串名符號表:所有串名的存儲映像構成一個符號表。借助此結構可以在串名和 串值之間建立一個對應關系,稱為串名的存儲映像。  

1)堆串存儲表示: C 語言已經有一個稱為“堆”的自由存儲空間,並可用函數 malloc()和函數 free()完成動態存儲管理。

串的鏈式存儲與串的應用

1、塊鏈串

  由於串也是一種線性表,因而也可以采用鏈式存儲。因為串是一個特殊的線性表(表中每 個元素就是一個字符)。在具體實現時,一個鏈表存放一個串值,每個結點既可以存放一個字符, 也可以存放多個字符。每個結點稱為塊,整個鏈表稱為塊鏈結構,為便於操作,再增加一個尾指 針。

塊鏈結構可定義如下:

#define  BLOCK_SIZE  4 /*每結點存放字符個數 4*/ 
typedef struct Block{ 
    char  ch[BLOCK_SIZE]; 
    struct Block   *next;
} Block; 
?
typedef struct { 
    Block   *head; 
    Block   *tail; 
    int     len; 
} BLString; 

  結點大小:鏈表中的結點分成兩個域data和link,其中結點大小是指data域中存放字符的個數,鏈域大小是指 link 域中占用字符的個數。

  存儲密度=串值占用的存儲位/實際為串分配存儲位

  顯然,串的存儲密度越小,運算處理就越方便,但存儲占用的量較大。應根據具體情況來確 定使用串的何種存儲結構。

  結點大小等於 1 :當 BLOCK_SIZE 等於 1 時,每個結點存放 1 個字符,結構同線性鏈表,存 儲結構可定義如下,插入、刪除的處理方法和線性鏈表一樣,算法處理簡單,但存儲密度較低。

  結點大於 1 :當 BLOCK_SIZE 大於 1 時,每個結點存放多個字符,當最後一個結點未存滿 時,不足處可用特定字符(如#)補齊。雖然存儲密度相對結點大小等於 1 的存儲方法來說,存儲 密度較高,但此時插入、刪除的處理方法比較復雜,需要考慮結點的分拆和合並。

2、串的應用舉例:簡單的行編輯器

數據結構(六)串