串的链块表示,操作复杂,不实用

串的链块表示

#include <stdio.h>
#include <stdlib.h>

#define OK 1
#define ERROR 0
#define SRUE 1
#define FALSE 0

typedef int Status;

#define CHUNKSIZE 5

typedef struct Chunk
{
    char ch[CHUNKSIZE];
    struct Chunk *next;
}Chunk;

typedef struct 
{
    Chunk * head, *tail;    /* 串的头和尾指针*/
    int curlen;             /* 串的当前长度 */ 
}LString;

/* 生成一个其值等于chars的串S */
Status StrAssign(LString *S, char * chars)
{
    if(!S->head) {  /* 头结点不存在 */ 
        S->head = (Chunk *)malloc(sizeof(Chunk));   /* 创建头结点 */
        S->tail = S->head;
        S->head->next = NULL;
    }
    if(!S->head->next) {
        S->head->next = (Chunk *)malloc(sizeof(Chunk)); /* 创建第一个结点 */
        S->tail = S->head->next;           /* 尾指针指向第一个结点 */
        S->head->next->next = NULL;
        S->curlen = 0;                    /* 字符元素清零 */
    }

    Chunk * p = S->head->next;        /* 指向第一个结点 */ 
    int chunklen = 0;
    for(int i=0; chars[i] != '\0'; i++,S->curlen++) {
        p->ch[chunklen++] = chars[i];   
        if(chunklen % CHUNKSIZE == 0) { /* 数组到达末尾,则新开结点 */
            Chunk * q = (Chunk *)malloc(sizeof(Chunk));
            q->next = p->next;
            p->next = q;    /* 插入到末尾 */
            S->tail = q;    /* 尾指针指向末尾结点 */
            p = q;          /* 指向新插入点 */
            chunklen = 0;
        } 
    }
    while(chunklen < CHUNKSIZE)
        p->ch[chunklen++] = '#'; /* 最后剩余空间填满 # */
    return OK;
}


/* 返回串S的元素个数 */
int StrLength(LString S)
{
    return S.curlen;
}


/* 清空字符串,并释放S所占的空间 */
Status ClearString(LString *S)
{
    int index = 0;
    while(S->head) {
        S->tail = S->head->next;
        free(S->head);
        index++;
        S->head = S->tail;
    }
    printf("free %d\n",index);
    S->curlen = 0;
    return OK;
}


/* 比较S,T,若S>T返回值>0 ,若S=T,返回0,若S<T,返回值<0 */
int StrCompare(LString S, LString T)
{
    if(!S.head->next || !T.head->next)
        return 0;
    int chunklen = 0;
    Chunk * pS = S.head->next;  /* 指向第一个结点 */
    Chunk * pT = T.head->next;
    for(int i=0; i<S.curlen && i<S.curlen; i++) {
        if(pS->ch[chunklen] != pT->ch[chunklen]) 
            return pS->ch[chunklen] - pT->ch[chunklen];
        chunklen++;
        if(chunklen % CHUNKSIZE == 0) {
            pS = pS->next;
            pT = pT->next;
            chunklen = 0;
        }
    }
    return S.curlen - T.curlen;
}

/* 用T返回由S1,S2拼接成的串 */
Status Concat(LString *T, LString S1, LString S2)
{
    // ... 未完成,这链块拼接真的不是那么简单,纠结在于最后的结点并不匹配,
    // 直接链表指指针的方式根本无法完成嘛
    if(!T->head) {  /* 头结点不存在 */ 
        T->head = (Chunk *)malloc(sizeof(Chunk));   /* 创建头结点 */
        T->tail = T->head;
        T->head->next = NULL;
    }
    T->head->next = S1.head->next;
    S1.tail->next = S2.head->next;
    T->curlen = S1.curlen + S2.curlen;
    return OK;
}

void PrintStr(LString S)
{
    if(!S.head) return;
    Chunk * p = S.head->next;   /* 指向第一个结点 */
    
    for(int chunklen=0,i=0; p && i<S.curlen; i++) {
        printf("%c",p->ch[chunklen++]);
        if(chunklen % CHUNKSIZE == 0)  { /* 当前结点已经遍历,指向下一个结点 */
            p = p->next;
            chunklen = 0;
        }
    }
    printf("\n");
}

int main()
{
    LString S1,S2,T;
    S1.head = NULL;
    S2.head = NULL;
    T.head = NULL;

    StrAssign(&S1,"Hello World");
    StrAssign(&S2,"This is a hello world");
    PrintStr(S1);
    PrintStr(S2);
    printf("compare %d\n",StrCompare(S1,S2));
    Concat(&T,S1,S2);
    PrintStr(T);
    ClearString(&T);
    ClearString(&S1);
    ClearString(&S2);
    printf("OK");
}

可以看输出结果

最后一个结点填充#号,而拼接的时候如果只是把链表指向重新定向一下是不行的,没法去掉最后一个结点问题。而如果用一个一个复制的方法,那还不如用数组。强行改造也不行,一样效率低。

posted @ 2019-10-06 23:07  wjundong  阅读(164)  评论(0编辑  收藏  举报