[数据结构] - 串
?
簡介
字符串(String)是由字符組成有限序列,是常用的一種非數值數據,串的邏輯結構是線性表,串是一種特殊的線性表,限制其元素類型是字符,串的操作特點與線性表不同,主要對子串進行操作,通常采用順序存儲結構存儲。
?
串的基本概念
串定義:一個串是由n(n>=0) 個字符組成的有限序列 記做s="s0 s1 s2" ,其中s是串名,一對雙引號括起來的字符序列 s0 s1 s2 是串值,s1(i=0,1,n-1) 為特定字符集中的一個字符,一個串中包含的字符數稱為串的長度,例如,字符串 “data” 長度是4,雙引號不計入長度,長度為0的串稱為空串, 記做“”,由多個空格字符構成的字符串 “” 稱為 空格串。
一個字符在串中的位置稱為該字符在串中的序號(Index),用一個整數表示,約定串中的第一個字符的序號為0,-1表示該字符不在指定串中。
?
子串:由串s中任意連續字符組成的一個子序列 sub稱為s的子串(Substring),s稱為sub的主串。例如 “at” 是“data” 的子串,特別的,空串是任意串的子串,任意串s都是他自身的子串,除了自身之外,s的其他子串稱為s的真子串。
子串序號是指該子串首字符在主串中的序號。例如 “dat” 在 “data” 中序號是0
?
串比較規則與字符比較規則有關,字符比較規則猶豫所屬字符集的編碼決定,通常在字符集中同意字母的大小寫形式有不同的編碼。
兩個串相等是指,串長度相等且哥哥對應位置是上的字符也相等。
兩個串的大小由對應位置的收個不同字符的大小決定,字符比較次序是從頭開始依次向后。當兩個串長度不等而對應位置的字符都相同時候,較長的串定義為較大。
?
串的抽象數據類型
串與線性表是不同的抽象數據類型,兩者操作不同,串的基本操作有:創建 求長度 讀取設置字符,求子串,插入,刪除,連接,判斷等,查找,替換,其中求子串,插入,查找等操作1以子串為單位,一次操作處理多個字符。
?
串的存儲結構
串有順序存儲和鏈式存儲兩種存儲結構。
java語言字符串類有常量字符串類String,和變量字符串類 StringBuffer,這兩種字符串類都采用順序存儲結構。能存儲任意長度的字符串,實現串的基本操作,并且能夠識別序號越界等錯誤,對數組占用的存儲空間進行控制,具有健壯,安全性好等特點。
順序存儲結構:采用字符數組將串中的字符序列一次連續存存儲在數組中的相鄰但愿中,常量串和變量串的存儲結構不同,數組容量length分半等于或者大于串長度n.
?
順序存儲的串具有隨機存取特效,存取指定位置字符的時間復雜度為 O(1) ,缺點是插入和刪除元素時需要移動元素,平均移動數據量是串長度的一半,當數組容量不夠時,需要重新申請一個更大的數組,并復制原來數組中的所有元素,插入和刪除操作的時間復雜度為O(n)
?
串的鏈式存儲結構:有單字符串鏈表和塊鏈表兩種,但字符串鏈表是每個節點的數據域只包含一個字符的單鏈表,塊鏈表是每個節點的數據域包含若干個字符的單鏈表。
鏈式存儲的串,存取指定位置字符的時間復雜度為 O(n),單字符鏈表雖然插入/刪除操作不需要移動元素,但是占用存儲空間太多,塊鏈表的插入和刪除操作需要移動元素,效率低。
?
?
Java String 類
String是由雙引號括起來的字符序列,其中可包含轉義字符,如 “hello” "漢字\n" ""(空串) 等等,字符串只能在一行。
字符常量采用單引號括起來? ‘a’ '汗' 數據類型是char,占用2個字節存儲字符的 Unicode編號,無論字符或者漢字,字符長度都是1.注意 只有空串 “” 沒有空字符''
String字符串類,屬于引用數據類型,提供構造串對象,求串長度取字符,求子串,連接串,比較串,比較大小等,如果charAt? substring? 方法序號越界將拋出 StringIndexOutOfBoundsException 字符串序號越界異常。
String是Java的一個特殊類,java不僅為之約定了常量形式,還重載賦值運算符 = 和 連接運算符 +? +=? 使得String變量能夠像基本數據類型變量一樣,進行賦值和運算,
Java的字符串對象不是字符數組,不能以數組下表個數 s[i] 對指定 I 位置的字符進行操作
String類特點:
String類是最終類,不能被繼承
String類以常量串方式存儲和實現字符串的操作,采用字符數組存儲字符序列,數組容量等于串長度,串尾部沒有 \0 作為串結束符。
聲明字符數組是最終變量,串中各個字符是只讀的,當構造串對象時候,對字符數組進行一次賦值后,不能修改
構造串,求子串和連接串的操作,都是深度拷貝,重新申請字符串占用的字符數組,復制字符串數組,不會改變原來的串。
?
Java StringBuffer
String類存儲常量字符串,一旦創建了實例,就不能修改它,這是線程安全的,但是每次連接等運算結果都將創建新的實例,頻繁進行連接等操作將增加使用空間并降低運算效率,因此,java還聲明StringBuffer類,采用緩沖區存儲可變的字符串,避免在運算時頻繁申請內存。
提供構造串對象,求串長度,取字符,求子串,等操作 提供修改字符,插入串,刪除子串,若序號越界,將拋出字符串序號越界異常。
StringBuffer是最終類,不能被繼承
StringBuffer 類以變量串方式存儲和實現字符串操作,數組容量大于串長度 串尾沒有\0 作為串結束符,當數組容量不能滿足要求時,將自動擴容。
StringBuffer類的插入,刪除等方法是線程互斥的。通過加互斥鎖,控制多個線程修改同一個共享字符串變量的次序是串行的不能并行交替的進行修改,否則將產生與時間有關的錯誤,不能保證結果的正確性。
?
模式匹配算法:
在進行文本編輯時候,我們經常查找和替換,在文檔的指定范圍內查找一個單詞的位置,用另一個單詞替換,替換操作的前提是查找操作,如果查找到指定單詞,則確定了操作位置,可以將指定單詞用另一個單詞替換掉,否則不能進行替換操作,每進行一次替換操作,都需要執行一次查找操作,那么如何快速查找指定單詞在文檔中的位置呢,就是串的模式批評算法需要姐姐的問題,
設有2個串,目標串target 和模式串 pattern ,在目標串target中查找與模式串pattern相等的一個子串并確定該子串的操作稱為 串的模式批評,兩個子串相等指的是:長度相等且對應各個字符相同,匹配結果有兩種? 如果target存在pattern相等的子串,則批評成功 獲得該子串在target中的位置,否則匹配失敗給出失敗信息。
?
模式匹配應用:
要對目標串target 與模式串pattern 匹配的子串進行刪除或者替換操作,必須先執行串的模式匹配算法,在target串中查找與pattern匹配的子串序號,確定刪除或者替換操作的起始位置,如果匹配失敗,則不進行替換或者刪除操作,因此,串的模式匹配算法是替換和刪除子串的基礎。
?
Brute - force 算法描述
已知目標串,target = "t0,t1,t2,tn-1" , 模式串 pattern = "p0 p1 p2 pn-1"? , 0 < m <= n? Brute-Force 算法將目標串中的每個長度為 m的子串? “t0 tm-1” "t1? tm-1" ...? "tn-m? tn-1"? 依次與模式串進行匹配操作,設 target="aababcd" pattern = "abcd"? 匹配四次,? 匹配層高返回子串序號3 ,字符比較10次。
?
KMP算法簡介:
KMP是一種無回溯的模式匹配算法,他改進了Brute-Force 算法,目標串不回溯。
已知目標串 “t0 t1 t2 tn-1” 與模式串 pattern = "p0 p1 p2 pn-1" 0<m<=n KMP算法每次匹配依次比較p1 與pj, (0<=i<n 0<=j<m).
若t=p 則繼續比較 t+1 與 p+1,直到ti+m+1...ti = p0...pm-1 則匹配成功,返回模式串在目標串中匹配子串序號 i-m+1.
若ti!=pj 表示ti-j ...ti 與 p0...pj? 匹配失敗,目標串不回溯,下次匹配ti 將與模式串pk(0<=k<j)比較,對于每個pj, k取值不同,因此,如何求得這個k,就成了KMP算法核心問題。
? 目標不回溯:
Brute-Force算法的目標串存在回朔,兩個串逐級比較,如果t1!=p1 (0<=i<n ||? 0<=j<m)則下次匹配目標串從ti 退回到 ti-j+1,開始于模式串p0 比較,實際上 目標串回朔是不必要的,ti-j+1 與p0 的比較結果可由前一次匹配結果得到.
設t0 t1 t2 與 p0 p1 p2 匹配一次,有t0 = p0? t1 = p1? t2 != p2
1.若p1 != p0? 那么 t1 也不等于 p0 下次匹配從t2 與 p0 開始匹配。
2.若p1 = p0? 那么 t1 = p0? 下次匹配 從 t2 與 p1 開始。
總之,當t2 != p2 時,無論p1 p0 是否相等,目標下次匹配都從t2開始比較,不回溯,而模式串要根據p1 和p0 是否相同,確定從p0或者p1 開始比較。
轉載于:https://www.cnblogs.com/gwyy/p/11033077.html
總結
以上是生活随笔為你收集整理的[数据结构] - 串的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基本数据类型对象包装类
- 下一篇: 时点现有量JOB