1. 程式人生 > >資料結構之串的基本操作

資料結構之串的基本操作

1.串的實現相比較而言簡單一些,但個人覺得有一些需要注意的地方,以下一 一列舉:

(1)串基本術語:

空串:空串指長度為0的串,其不包含任何字元;

空格串:不同於空串,它是由一個或多個空格構成的串。雖然是空格,但在計算長度時要把空格的個數算在內;

串比較:串的大小比較時以字元的ASCII碼值作為依據。

(2)串基本操作:賦值操作、連線操作、求串長、竄的比較和求子串。

(3)串的儲存結構:順序儲存和鏈式儲存。其中鏈式儲存可以指定節點大小,儲存若干個字元。

2.串的模式匹配演算法:求解子串在主串中首次出現的位置:Index(S,T,pos)

演算法的實現使具有暴力的性質,模式串和主串同時從第一個位置開始進行判斷,若對應位置字元相等則繼續向後判斷,若不相

等,則模式串回到串首,主串字元位置指標回退,重新匹配。

int Index(String s,String t,int pos){
    //返回子串t在主串s中第pos個字元之後的位置,若不存在,則返回0
    if(isEmpty(t) || pos<0 || pos>t.length-1) exit(0);
    int i=pos;
    int j=0;
    while(i<=s.length && j<=t.length){
        if(s.ch[i] == t.ch[j]){
            ++i;
            ++j;   //繼續比較後續的字元
        }
        else{
            i=i-j+1;j=0;//指標回退,重新開始匹配
        }
    }
    if(j>t.length) {
        return i-t.length;
    }
    else
        return 0;

}

串的模式匹配演算法優化:KMP演算法

此演算法可以在O(m+n)的數量級上完成串的匹配操作。其改進在於,每一趟匹配過程中出現字元比較不相等的時候,不需要回

退指標i,而是利用已經匹配到的部分結果將模式串向右滑動儘可能遠的距離,繼續匹配。

#include<iostream>
#include<cstdlib>
using namespace std;
#define MAXSTRLEN 100

typedef char SString[MAXSTRLEN+1];

//返回模式串T在主串中第pos位置之後的位置,若存在,返回1,否則返回0

int KMPindex(SString S,SString T,int pos){
    if(pos < 1 || pos>S[0]) exit(0);
    int i=pos;
    int j=1;
    int next[MAXSTRLEN];
    GetNext(T,next);
    while(i <= S[0] && j<= T[0]){
        if(S[i] == T[j]){
            i++;j++;
        }else{
            j=next[j];
        }
    }
    if(j >T[0]) return i-T[0];
    return 0;
}

//求子串next[i]的值
void GetNext(SString T,int next[]){
    int j=1,k=0;
    next[1]=0;
    while(j<T[0]){
        if(k==0 || T[j]==T[k]){ //子串自己與機子進行比較
            ++j;
            ++k;
            next[j]=k;
        }else{
            k = next[k];
        }
    }


}
int main()
{
    SString S = {13,'a','b','a','b','c','a','b','c','a','c','b','a','b'};  
    SString T = {5,'a','b','c','a','c'};  
    int pos;  
    pos = KMPindex( S,  T, 1);  
    cout<<"匹配位置為:"<<pos;
    return 0;
}

 

3.順序串與鏈式串的實現(C語言)

(1)順序串:

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
#define MAXSIZE 100
//串的順序儲存
typedef struct st{
    char *ch;//串存放的起始地址
    int length;//串的長度
    int strsize;//分配的儲存空間的大小
}String;

//1.串的初始化操作
String CreateNullString(){
    String str;
    str.length = 0;
    str.ch = (char *)malloc(MAXSIZE*sizeof(char));
    str.strsize = MAXSIZE;
    return str;
}

//2.判斷空串
int isEmpty(String str){
    if(str.length == 0){
        return 1;
    }else{
        return 0;
    }
}

//3.串的賦值操作
void StrAssign(String *str1,char str2[]){
    int i=0;
    while(str2[i] != '\0') i++;//計算str2的長度
    if(str1->length < i){   //結構指標成員的訪問
        //增加儲存空間,將較長的空間賦值為新的值
        str1->ch = (char *)malloc(sizeof(char));
        str1->strsize = i;
    }
    
    str1->length = i;
    for(i=0;i<str1->length;i++){
        str1->ch[i] = str2[i];//從第一個字元開始,著個賦值
        
    }
}
//4.串的拷貝
void StrCopy(String *str1,String str2){
    if(str1->strsize < str2.strsize){
        str1->ch = (char *)realloc(str1->ch,str2.length*sizeof(char));
        str1->strsize = str2.length;;
    }
    
    str1->length = str2.length;
    int i;
    for(i=0;i<str1->length;i++){
        str1->ch[i] = str2.ch[i];
    }
}

//5.串的長度
int StrLength(String str){
    return str.length;
}

//6.串的連線操作
void StrConcat(String *str,String str1,String str2){
    if(str->strsize < str1.strsize + str2.strsize){
        str->ch = (char *)realloc(str->ch,(str1.length+str2.length)*sizeof(char));
        str->strsize = str1.length+str2.length;
    }
    
    str->length = str1.length+str2.length;
    
    int i;
    for(i=0;i<str1.length;i++){
        str->ch[i] = str1.ch[i];
    }//將str1賦值到str
    for(;i<str->length;i++){
        str->ch[i] = str2.ch[i-str1.length];
    }//將str2賦值到str
}

//7.取子串
int SubStr(String s,int i,int len,String *t){
    /*
        i表示從字串s的第i個位置開始擷取(索引從1開始)
        len表示擷取字串的長度
    */
    
    //將s中從i位置起,len長度的串通過t返回
    if(i<=0 || i>s.length || len<0 || len>s.length-i+1){
        t->ch = (char *)realloc(t->ch,len*sizeof(char));
        t->strsize = len;
    }
    t->length = len;
    int k;
    for(k=0;k<t->length;k++){
        t->ch[k] = s.ch[i-1+k];
    }
    return 1;
}

//8.插入操作
int InsertString(String *str,int i,String str1){
    //將str1,插入str的第i個位置
    if(i <= 0 || i>str->length+1) return 0;
    
    if(str->strsize < str->length + str1.length){
        //空間不足
        str->ch = (char *)realloc(str->ch,(str->length+str1.length)*sizeof(char));
        str->strsize = str->length + str1.length;
    }
    int k;
    for(k=str->length-1;k>=i-1;k--){
        //將str中的後i個字元後移
        str->ch[k+str1.length] = str->ch[k];
    }
    str->length = str->length + str1.length;
    for(k=0;k<str1.length;k++){
        str->ch[k+i-1] = str1.ch[k];
    }
    
    return 1;
    
}
//9.刪除子串
int deleteStr(String *str,int i,int len){
    //從第i個位置開始,刪除len長度的子串
    if(i<=0 || i>str->length || len <0 || len > str->length-i+1){
        return 0;
    }
    int k;
    for(k=i+len-1;k<str->length;k++){
        //從str的i+len-1個位置開始將其後的所有字前移
        str->ch[k-len] = str->ch[k];
    }
    str->length -= len;
    return 1;
}

//10.輸出操作
void print(String *str){
    int i;
    for(i=0;i<str->length;i++){
        cout<<str->ch[i]<<" ";
    }
    cout<<endl;
}

//11.串的模式匹配
int Index(String s,String t,int pos){
    //返回子串t在主串s中第pos個字元之後的位置,若不存在,則返回0
    if(isEmpty(t) || pos<0 || pos>t.length-1) exit(0);
    int i=pos;
    int j=0;
    while(i<=s.length && j<=t.length){
        if(s.ch[i] == t.ch[j]){
            ++i;
            ++j;   //繼續比較後續的字元
        }
        else{
            i=i-j+1;j=0;//指標回退,重新開始匹配
        }
    }
    if(j>t.length) {
        return i-t.length;
    }
    else
        return 0;
}
int main()
{
    String str1 = CreateNullString();
    String str2 = CreateNullString();
    String str3 = CreateNullString();
    char ch[MAXSIZE];
    cout<<"請輸入主串"<<endl;
    gets(ch);
    StrAssign(&str1,ch);
    cout<<"主串為:";
    print(&str1);
    cout<<endl;
    StrCopy(&str2,str1);
    cout<<"拷貝得到的串為:";
    print(&str2);
    cout<<endl;
    
    SubStr(str1,4,4,&str3);
    cout<<"擷取的子串為:";
    print(&str3);
    cout<<endl;
    
    int pos = Index(str1,str2,0);
    cout<<"匹配位置為:"<<pos<<endl;
    return 0;

}

(2)鏈式串:

#include<iostream>
#include<cstdlib>
using namespace std;
//串的鏈式儲存
typedef struct node{
    char ch;   //字元域
    struct node *next; //指標域,存放下一個節點的指標
}node,*Linkstr;
//1.初始化一個空串
Linkstr CreateNullString()
{
    Linkstr str;
    str=(Linkstr)malloc(sizeof(node));
    if(str != NULL){
        str->next = NULL;
    }
    return str;
}

//2.判斷空串
int IsEmpty(Linkstr str)
{
    if(str->next ==NULL){
        return 1;
    }
    else{
        return 0;
    }
}

//3.賦值操作
void StringAssign(Linkstr str,char t[])
{
    Linkstr p,q,r;
    r=str;//r始終表示的尾節點(最後一個非空節點,而不是最後一個NULL節點)。
    q=str->next;
    int i;
    for(i=0;t[i] != '\0';i++){
        if(q!=NULL)
        {
            q->ch = t[i]; //一個一個的存入節點
            r=q;
            q=q->next;    
        }
        else{
            //(初始化時只給頭結點分配了儲存空間或者其他情況),如果需要繼續新增資料(其他節點沒分配空間)需要繼續分配
            p=(Linkstr)malloc(sizeof(node));
            //新增節點
            p->ch = t[i];
            r->next = p;
            r = p;
        }
        r->next = NULL;
        //將s中多餘的空間釋放掉
        while(q!=NULL){
            p=p->next;
            free(q);
            q=p;
        }
    }
 }
 
//2.串的拷貝
void Assign(Linkstr s,Linkstr t)
{
    ////將t串的值賦值給s串
    Linkstr p,q,r,u;
    p=t->next;
    q=s->next;
    r=s;
    while(p!=NULL){
        //串s已經分配了空間
        if(q!=NULL){
            q->ch = p->ch;
            r=q;
            q=q->next;
        }
        else{
            //串s中原先的空間不夠
            u=(Linkstr)malloc(sizeof(node));
            u->ch = p->ch;
            r->next =u;
            r=u;
        }
        //p節點後移
        p=p->next;
        //同理,若q的長度過長,可以釋放多餘的空間
        while(q!= NULL){
            p=p->next;
            free(q);
            q=p;
        }
        r->next = NULL;
    }
}

//3.求串長
int length(Linkstr s)
{
    Linkstr p;
    int len=0;
    p=s->next;
    while(p!=NULL){
        len++;
        p=p->next;
    }
    return len;
}
//4.串的連結操作
void contact(Linkstr s,Linkstr s1,Linkstr s2)
{
    Linkstr p,q,r,t;
    r=s;
    p=s1->next;
    q=s->next;
    while(p!=NULL){
        if(q!=NULL)  //s不是空串
        {
            q->ch = p->ch;
            q=q->next;
            r=q;
        }
        else{
            //串s原來沒有分配儲存空間,需要申請空間
            t=(Linkstr)malloc(sizeof(node));
            t->ch=p->ch;
            r->next=t;
            r=t;
        }
        p=p->next;
    }
    p=s2->next;
    while(p!=NULL){
        if(q!=NULL){
            q->ch=p->ch;
            q=q->next;
            r=q;
        }else{
            //串s原來沒有分配儲存空間,需要申請空間
            t=(Linkstr)malloc(sizeof(node));
            t->ch=p->ch;
            r->next=t;
            r=t;
        }
        p=p->next;
    }
    
    //將串s的多餘的空間清除掉(這個情況只可能發生在while的if迴圈中)
    while(q!=NULL){
        p=q->next;
        free(q);
        q=p;
    }
    r->next = NULL;
}  
//5.擷取子串
int subString(Linkstr s,int i,int len,Linkstr t)
{
    Linkstr p,q,r,u;
    if(i<=0||i>length(s) || i+len-1>length(s))
        return 0;
    //指標指向s的第i-1個位置
    int j,k;
    for(j=0,p=s;j<i;j++){
        p=p->next;
    }
    for(k=0,r=t,q=t->next;k<len;k++)
    {
        if(q!=NULL){
            q->ch=p->ch;
            r=q;
            q=q->next;
        }
        else{
            u=(Linkstr)malloc(sizeof(node));
            u->ch=p->ch;
            r->next=u;
            r=u;
        }
        p=p->next;
    }
    
    while(q!=NULL){
        p=q->next;
        free(q);
        q=p;
    }
    r->next=NULL;
    return 1;
}
//6.插入子串操作
int insert(Linkstr s,int i,Linkstr t)
{
    Linkstr p,q,r;
    if(i<=0 || i>length(s)+1)
    return 0;
    //指向i-1個位置
    int j;
    for(j=0,p=s;j<i-1;j++){
        p=p->next;
    }
    q=t->next;
    while(q!=NULL)
    {
        r=(Linkstr)malloc(sizeof(node));
        r->ch = q->ch;
        r->next=p->next;
        p->next=r;
        q=q->next;
        p=r;
    }
    return 1;
}
//7.刪除操作
int deleteStr(Linkstr s,int i,int len){
    Linkstr p,q,r;
    if(i<=0 || i>length(s) || i+len-1>length(s))
    return 0;
    int j;
    for(j=0,p=s;j<i-1;j++){
        p=p->next;
    }
    for(j=0;j<len;j++){
        q=p->next;
        p->next=q->next;
        free(q);
    }
    return 1;
}
//8.列印輸出
void print(Linkstr s)
{
    Linkstr p=s->next;
    while(p!=NULL)
    {
        cout<<p->ch<<" ";
        p=p->next;
    }
    cout<<endl;
 }
int main()
{
    Linkstr s1;
    Linkstr s2;
    Linkstr s3;
    s1=CreateNullString();
    s2=CreateNullString();
    s3=CreateNullString();
    char str[100];
    cout<<"請輸入字元:"<<endl;
    gets(str);
    StringAssign(s1,str);
    cout<<"串1:";
    print(s1);
    cout<<endl;
    cout<<"串1的長度為:"<<length(s1)<<endl;
    
    Assign(s2,s1);
    cout<<"串2:";
    print(s2);
    cout<<endl;
    cout<<"串2的長度為:"<<length(s2)<<endl;
    
    cout<<"串s2的刪除操作:"<<endl;
    deleteStr(s2,3,3);
    cout<<"串2:";
    print(s2);
    cout<<endl;
    cout<<"串2的長度為:"<<length(s2)<<endl;
    contact(s3,s1,s2);
    cout<<"串3為(串1和串2的連線):";
    
    print(s3);
    return 0;
}

相關推薦

資料結構基本操作的實現(c語言)

我們先一起來看串的一些概念… 字串(簡稱串),可以將其看作是種特殊的線性表,其特殊性在於線性表的資料元素的型別總是字元性,字串的資料物件約束為字符集。 串是由0個或多個字元組成的有限序列。一般記作:s = “s1 s2 s3 …. sn”,,其中,s是串名

資料結構基本操作

1.串的實現相比較而言簡單一些,但個人覺得有一些需要注意的地方,以下一 一列舉:(1)串基本術語:空串:空串指長度為0的串,其不包含任何字元;空格串:不同於空串,它是由一個或多個空格構成的串。雖然是空格,但在計算長度時要把空格的個數算在內;串比較:串的大小比較時以字元的ASC

python資料結構——概述和基本演算法

概述: 字串(string)簡稱串,也是一種線性結構。在python中和array差不多,因為py的陣列也可以包括各種字元(在C/Java一類的語法中,陣列必須是同一種資料型別的元素)。線性結構,有限序列,是主要特點。串其中可以包含各種元素,也是計算機主要處理的一類物件。因

資料結構連結串列操作(c++實現)

1、單向連結串列(頭結點不含資料,不佔長度),C++實現: #include <iostream> #include <stack> using namespace std; /*****定義節點****/ typedef struct node{ int va

java資料結構的定義

原始碼的github地址,可以下載到本地執行 串的介面定義 package Interface; import impl.ArrayString; /** * 串 是由零個或者多個字元組成的有限序列 * 串中字元的數目n稱為串的長度 零個字元的串稱為空串 它的長度為

資料結構棧的基本操作

#include<iostream> #define MAXSIZE 100 #define OVERFLOW -1 #define OK 1 #define ERROR 0 using namespace std; typedef int SElemType

資料結構樹的操作

話不多少 q:690217293  歡迎交流 //_____________________________demo.cpp #include <cstdio> #include "Tree.h" #include <iostream> using

案例3.2:括號匹配的檢驗(c++實現/資料結構/棧的基本操作

#include<iostream> #define MaxSize 100 #define OK 1 #define ERROR 0 using namespace std; typedef char ElemType; typedef int Status

python資料結構序列及其操作

序列       在Python中最基本的資料結構是序列(sequence)。序列中的每個元素被分配一個序號----即元素的位置,也稱索引。索引從0開始,0,1,2,3,...。也可以從最後一個數開始,標記為-1,依次為-1,-2,-3.... 列表與元組的區別

資料結構 圖的基本操作實現

實驗題目: 圖的基本操作實現        實驗環境:   Visual C++ 6.0                     實驗目的:掌握圖的鄰接矩陣和鄰接表兩個儲存結構及表示。           掌握圖的DFS和BFS兩種遍歷演算法。           理解並

資料結構-鏈佇列基本操作

都是些基本操作,有興趣的可以看看。 1 #include<stdio.h> 2 #include<stdlib.h> 3 typedef struct QNode { 4 int data; 5 struct QNode *next; 6 }QNod

資料結構的定義及實現

串的基本定義及實現 串型別的定義 定長順序儲存形式 堆分配儲存形式 1.1、串型別的定義 串(string)是零個或多個字元組成的有限序列 , S=‘a1a2…an’(n>=0) 其中,s是串名

演算法與資料結構-棧的基本操作C語言實現

序言 複習棧的基本操作及其C語言實現,主要以鏈式棧為例。 本文將介紹棧的以下基本操作: 棧的建立(順序棧和鏈式棧) 棧的初始化 棧遍歷 棧清空/銷燬 判斷棧是否為空 求棧的長度 返回並刪除棧頂元素 1. 棧建立 - 順序棧和鏈式棧 //順序棧的

資料結構的模式匹配(C語言實現)

一、暴力匹配演算法(BF) BF全稱為Brute-Force,最簡單直觀的模式匹配演算法。 1.演算法思想 兩個字串進行匹配時,一個主串和一個模式串,就是按照我們最容易想到的演算法來進行匹配。用兩個變數i,j分別記錄主串和模式串的匹配位置,如果兩者在某個字

資料結構連結串列操作

之前看資料結構時,以為連結串列操作很容易,真正寫程式碼時才發現被打臉了。。。經歷了各種錯誤後,現在總結一下走過的彎路。 這裡主要說下連結串列的增加刪除節點操作。 typedef struct l

資料結構——棧的基本操作(二進位制轉十進位制例項—c語言程式碼)

棧棧是一種重要的線性結構。棧必須通過線性表或者連結串列來實現,順序表點選開啟連結和連結串列點選開啟連結既可以向之前介紹的那樣獨立存在,同時它們也是一些特殊的資料結構(棧,佇列)的實現基礎。定義:棧是一個先進後出的線性表,只要求在表尾進行插入和刪除等操作,這是棧相對於連結串列和

資料結構—順序表基本操作(c語言程式碼)

順序表計算機內部儲存一張線性表是用一組連續地址記憶體單元,這種儲存結構即為順序儲存結構,這種結構下的線性表叫順序表。順序表有兩種定義方法:                                    1.靜態定義                           

演算法與資料結構-佇列的基本操作C語言實現

序言 佇列有順序佇列和鏈式佇列,順序佇列通過陣列方式來實現,鏈式佇列通過連結串列方式來實現。 陣列方式實現便於資料訪問(大小和空間確定),連結串列方式實現便於資料操作(插入和刪除靈活)。 這裡介紹

資料結構萬用字元匹配

採用順序結構儲存串,編寫一個實現串萬用字元匹配的演算法pattern_Index(),其中的萬用字元只有“?”,它可以和任一字元匹配成功,例如,pattern_Index(“?re",”there a

資料結構順序基本操作——C語言

#include <stdio.h> #include <stdlib.h> #define MaxSize 100 typedef struct { char data[MaxSize]; int len; }SqString; voi