数据结构-块链的操作

块链的基本操作

数据结构学习中关于块链的操作

以及块链insert算法的实现

1.块链的定义与初始化

#define CHUNKSIZE 100

/*块链定义*/
typedef struct Nodes{
    char data[CHUNKSIZE]; // 数据域
    struct Nodes* next; // 指针域
}block;

typedef struct{
    block *head, *tail; // 串的头指针、尾指针
    int cur_len; // 串的当前长度
}lstring;

char blank = '#'; // 用于填补空白


void init_string(){
    /*初始化字符串(产生空串)*/
    lstring* T = new lstring;
    T->cur_len = 0;
    T->head = NULL;
    T->tail = NULL;
}

int str_assign(lstring* T, char *chars){
    /*生成一个等于chars的串T(要求chars中不包含‘#’填补字符)*/
    int i, j, k, l;
    block *p, *q;
    i = strlen(chars);
    if(i == 0 || strchr(chars, blank))
        return 0; // 串长为零或chars中包含blank
    T->cur_len = i;
    j = i / CHUNKSIZE; // j为块链的结点数,块的个数
    if(i % CHUNKSIZE){ // 不足一块的,当成一个块处理(块数加1)
        j++;
    }
    for(k = 0;k < j; k++){
        p = new block;
        if(p == NULL){
            return 0;
        }
        if(k == 0){ //第一个块
            T->head = q = p;
        }
        else{
            q->next = p;
            q = p; // 尾插法思想
        }
        for(l = 0;l < CHUNKSIZE && *chars; l++){
            *(q->data+l) = *chars++;
        }
        if(!chars){ // 最后一个块链
            T->tail = q;
            q->next = NULL;
            while(l < CHUNKSIZE){ // 用'#'填补剩余位置
                *(q->data+l) = blank;
                l++;
            }
        }
    }
    return 1;
}

块链的基本处理操作

int str_copy(lstring* T, lstring* S){
    /*由串S复制得到串T*/
    block* h = S->head;
    block *p, *q;
    T->cur_len = S->cur_len;
    if(h != NULL){
        p = T->head = new block;
        *p = *h; // 复制1个结点(第一个)
        h = h->next;
        while(h){ // 复制结点,一直到队尾
            q = p;
            p = new block;
            q->next = p;
            *p = *h;
            h = h->next;
        }
        p->next = NULL;
        T->tail = p;
        return 1;
    }
    else{
        return 0;
    }
}

int is_str_empty(lstring* S){
    /*判断块链是否为空*/
    if(S->cur_len == 0){
        return 1; // 空
    }
    else{
        return 0;  //非空
    }
}

int str_cmp(lstring* S, lstring* T){
    /*块链串比较:
    若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0*/
    int i = 0;
    block *s = S->head, *t = T->head;
    //s 和 t分别指向S 和 T的待比较块
    int cs = 0, ct = 0; // cs,ct分别表示S和T的待比较字符在块中的次序
    while(i < S->cur_len && i < T->cur_len){
        i++; // 分别找S和T的第i个字符
        while(*(s->data+cs) == blank){// 跳过填补空余的字符
            cs++;
            if(cs == CHUNKSIZE){
                s = s->next;
                cs = 0;
            }
        } // *(cs->data+cs) 为S的第i个有效字符
        while(*(t->data+ct) == blank){// 跳过填补空余的字符
            ct++;
            if(ct == CHUNKSIZE){
                t = t->next;
                ct = 0;
            }
        } // *(ct->data+ct) 为T的第i个有效字符
        if(*(s->data+cs) != *(t->data+ct)){ //出现不等,返回
            return (*(s->data+cs) - *(t->data+ct));
        }
        else{ // 继续比较下一字符
            cs++;
            if(cs == CHUNKSIZE){
                s = s->next;
                cs = 0;
            }
            ct++;
            if(ct == CHUNKSIZE){
                t = t->next;
                ct = 0;
            }
        }
    }
    //如果全部比较完成(以较短的串为准),都相等,那就根据串的长度判断
    return S->cur_len - T->cur_len;
}

int str_length(lstring* S){
    /*返回串的长度*/
    return S->cur_len;
}

int clear_str(lstring* S){
    /*清空串*/
    block *p, *q;
    // 释放空间,置空
    p = S->head;
    while(p){
        q = p->next;
        delete p;
        p = q;
    }
    S->head = NULL;
    S->tail = NULL;
    S->cur_len = 0;
    return 1;
}

int str_concat(lstring* T, lstring* S1, lstring* S2){
    /*用T接收由S1和S2连接而成的新串并返回*/
    lstring a1, a2;
    init_string(&a1);
    init_string(&a2);
    str_copy(&a1, S1);
    str_copy(&a2, S2);
    T->cur_len = S1->cur_len + S2->cur_len;
    T->head = a1.head;
    a1.tail->next = a2.head;
    T->tail = a2.tail;
    return 1;
}


int sub_str(lstring* sub, lstring* S, int pos, int len){
    /*用Sub返回串S的第pos个字符起长度为len的子串*/
    block* p, *q;
    int i,k,n,flag = 1; // 用于标志复制是否完成
    if(pos < 1 || pos > S->cur_len || len < 0 || len > S->cur_len-pos+1){
        return 0;
    }
    n = len / CHUNKSIZE;
    if(len % CHUNKSIZE){
        n++; // n为块的个数
    }
    p = new block;
    sub->head = p; // 生成空的sub串
    for(i = 1;i < n; i++){
        q = new block;
        p->next = q;
        p = q; //尾插法方法
    }
    p->next = NULL;
    sub->tail = p;
    sub->cur_len = len;
    for(i = len % CHUNKSIZE;i < CHUNKSIZE; i++){
        *(p->data+i) = blank; // 填充sub尾部的多余空间
    }
    q = sub->head; // q指向sub串即将复制的块
    i = 0;
    p = S->head;
    n = 0;
    while(flag){
        for(k = 0; k < CHUNKSIZE; k++){ // k指示当前字符在块中的位置 
            if(*(p->data+k) != blank){
                n++;
                if(n >= pos && n <= pos+len-1){ // 复制
                    if(i == CHUNKSIZE){
                        //到下一块
                        q = q->next;
                        i = 0;
                    }
                    *(q->data+i) = *(p->data+k);
                    i++;
                    if(n == pos+len-1){
                        flag = 0;
                        break;
                    }
                }
            }
        }
        p = p->next;
    }
    return 1;
}

int index(lstring* S, lstring* T, int pos){
    /*模式匹配: T为非空串。若主串S中第pos个字符之后存在与T相等的子串, 
    则返回第一个这样的子串在S中的位置,否则返回0 */
    int i, n, m;
    lstring sub;
    if(pos >= 1 && pos <= str_length(S)){
        n = str_length(S); //主串长度
        m = str_length(T); // T串长度
    }
    while(i <= n-m+1){
        sub_str(&sub, S, i, m); // sub为从S的第i个字符起,长度为m的字符串
        if(str_cmp(&sub, T) != 0){
            i++; // 若不相等 则往后迭代
        }
        else{
            return i; //相等返回
        }
    }
    return 0;
}

void zip_str(lstring* S){
    /*压缩块链串(清除其中不必要的填补空余的字符)*/
    int j, n = 0;
    block *h = S->head;
    char* q;
    q = new char[S->cur_len+1];
    while(h){ // // 将LString类型的字符串转换为char[]类型的字符串
        for(j = 0;j < CHUNKSIZE; j++){
            if(*(h->data+j) != blank){
                *(q+n) = *(h->data+j);
                n++;
            }
            h = h->next; // h指向下一个块       
        }
        *(q+n) = 0; // 串结束符
        clear_str(S); // 清空S
        str_assign(S, q); // 重新生成S
    }
}

int str_insert(lstring* S, int pos, lstring* T){
    /*在串S的第pos个字符之前插入串T*/
    int i, j, k;
    block *p, *q;
    lstring t;
    if(pos < 1 || pos > str_length(S)+1){ //pos超出范围
        return 0;
    }
    str_copy(&t, T); // 复制T为t
    zip_str(S); // 去掉S中多余的填补空余字符
    i = (pos - 1) / CHUNKSIZE; // 到达插入点要移动的块数
    j = (pos - 1) % CHUNKSIZE; // 到达插入点在最后一块上要移动的字符数 
    p = S->head;
    if(pos == 1){ // 插在S串前
        t.tail->next = S->head;
        S->head = t.head;
    }
    else if(j == 0){ // 插在块之间
        for(k = 1;k < i; k++){
            p = p->next; // p指向插入点的左块
        }
        q = p->next; // q指向插入点的右块
        p->next = t.head; // 插入t
        t.tail->next = q;
        if(q == NULL){
            S->tail = t.tail; // 改变尾指针
        }
    }
    else{ // 插在一块内的两个字符之间
        for(k = 1;k <= i; k++){
            p = p->next; // p指向插入点所在块
        }
        q = new block;
        for(i = 0;i < j; i++){
            *(q->data+i) = blank; // 块q的前j个字符为填补空余的字符
        }
        for(i = j;i < CHUNKSIZE; i++){
            *(q->data+i) = *(p->data+i); //复制插入点后的字符到q
            *(p->data+i) = blank; // p的该字符为填补空余的字符
        }
        q->next = p->next;
        p->next = t.head;
        t.tail->next = q;
    }
    S->cur_len += t.cur_len;
    zip_str(S); // 进行压缩
    return 1;
}

void str_print(lstring* T){
    int i = 0, j;
    block *h;
    h = T->head;
    while(i < T->cur_len){
        for(j = 0;j < CHUNKSIZE; j++){
            if(*(h->data+j) != blank){
                printf("%c", *(h->data+j));
                i++;
            }
        }
        h = h->next;
    }
    printf("\n");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值