三木社区

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 304|回复: 0
打印 上一主题 下一主题

C语言数据结构-bo4-3.c

[复制链接]

1562

主题

1564

帖子

4904

积分

博士

Rank: 8Rank: 8

积分
4904
跳转到指定楼层
楼主
发表于 2017-9-1 08:39:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. /* bo4-3.c 串采用块链存储结构(由c4-3.h定义)的基本操作(16个) */
  2. void InitString(LString *T)
  3. { /* 初始化(产生空串)字符串T。另加 */
  4.    (*T).curlen=0;
  5.    (*T).head=NULL;
  6.    (*T).tail=NULL;
  7. }

  8. Status StrAssign(LString *T,char *chars)
  9. { /* 生成一个其值等于chars的串T(要求chars中不包含填补空余的字符) */
  10.    /* 成功返回OK,否则返回ERROR */
  11.    int i,j,k,l;
  12.    Chunk *p,*q;
  13.    i=strlen(chars); /* i为串的长度 */
  14.    if(!i||strchr(chars,blank)) /* 串长为0或chars中包含填补空余的字符 */
  15.      return ERROR;
  16.    (*T).curlen=i;
  17.    j=i/CHUNKSIZE; /* j为块链的结点数 */
  18.    if(i%CHUNKSIZE)
  19.      j++;
  20.    for(k=0;k<j;k++)
  21.    {
  22.      p=(Chunk*)malloc(sizeof(Chunk));
  23.      if(!p)
  24.        return ERROR;
  25.      if(k==0) /* 第一个链块 */
  26.        (*T).head=q=p;
  27.      else
  28.      {
  29.        q->next=p;
  30.        q=p;
  31.      }
  32.      for(l=0;l<CHUNKSIZE&&*chars;l++)
  33.        *(q->ch+l)=*chars++;
  34.      if(!*chars) /* 最后一个链块 */
  35.      {
  36.        (*T).tail=q;
  37.        q->next=NULL;
  38.        for(;l<CHUNKSIZE;l++) /* 用填补空余的字符填满链表 */
  39.          *(q->ch+l)=blank;
  40.      }
  41.    }
  42.    return OK;
  43. }

  44. Status StrCopy(LString *T,LString S)
  45. { /* 初始条件:串S存在。操作结果:由串S复制得串T(连填补空余的字符一块拷贝) */
  46.    Chunk *h=S.head,*p,*q;
  47.    (*T).curlen=S.curlen;
  48.    if(h)
  49.    {
  50.      p=(*T).head=(Chunk*)malloc(sizeof(Chunk));
  51.      *p=*h; /* 复制1个结点 */
  52.      h=h->next;
  53.      while(h)
  54.      {
  55.        q=p;
  56.        p=(Chunk*)malloc(sizeof(Chunk));
  57.        q->next=p;
  58.        *p=*h;
  59.        h=h->next;
  60.      }
  61.      p->next=NULL;
  62.      (*T).tail=p;
  63.      return OK;
  64.    }
  65.    else
  66.     return ERROR;
  67. }

  68. Status StrEmpty(LString S)
  69. { /* 初始条件:串S存在。操作结果:若S为空串,则返回TRUE,否则返回FALSE */
  70.    if(S.curlen) /* 非空 */
  71.      return FALSE;
  72.    else
  73.      return TRUE;
  74. }

  75. int StrCompare(LString S,LString T)
  76. { /* 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0 */
  77.    int i=0; /* i为当前待比较字符在S,T串中的位置 */
  78.    Chunk *ps=S.head,*pt=T.head; /* ps,pt分别指向S和T的待比较块 */
  79.    int js=0,jt=0; /* js,jt分别指示S和T的待比较字符在块中的位序 */
  80.    while(i<S.curlen&&i<T.curlen)
  81.    {
  82.      i++; /* 分别找S和T的第i个字符 */
  83.      while(*(ps->ch+js)==blank) /* 跳过填补空余的字符 */
  84.      {
  85.        js++;
  86.        if(js==CHUNKSIZE)
  87.        {
  88.          ps=ps->next;
  89.          js=0;
  90.        }
  91.      }; /* *(ps->ch+js)为S的第i个有效字符 */
  92.      while(*(pt->ch+jt)==blank) /* 跳过填补空余的字符 */
  93.      {
  94.        jt++;
  95.        if(jt==CHUNKSIZE)
  96.        {
  97.          pt=pt->next;
  98.          jt=0;
  99.        }
  100.      }; /* *(pt->ch+jt)为T的第i个有效字符 */
  101.      if(*(ps->ch+js)!=*(pt->ch+jt))
  102.        return *(ps->ch+js)-*(pt->ch+jt);
  103.      else /* 继续比较下一个字符 */
  104.      {
  105.        js++;
  106.        if(js==CHUNKSIZE)
  107.        {
  108.          ps=ps->next;
  109.          js=0;
  110.        }
  111.        jt++;
  112.        if(jt==CHUNKSIZE)
  113.        {
  114.          pt=pt->next;
  115.          jt=0;
  116.        }
  117.      }
  118.    }
  119.    return S.curlen-T.curlen;
  120. }

  121. int StrLength(LString S)
  122. { /* 返回S的元素个数,称为串的长度 */
  123.    return S.curlen;
  124. }

  125. Status ClearString(LString *S)
  126. { /* 初始条件: 串S存在。操作结果: 将S清为空串 */
  127.    Chunk *p,*q;
  128.    p=(*S).head;
  129.    while(p)
  130.    {
  131.      q=p->next;
  132.      free(p);
  133.      p=q;
  134.    }
  135.    (*S).head=NULL;
  136.    (*S).tail=NULL;
  137.    (*S).curlen=0;
  138.    return OK;
  139. }

  140. Status Concat(LString *T,LString S1,LString S2)
  141. { /* 用T返回由S1和S2联接而成的新串 */
  142.    LString a1,a2;
  143.    InitString(&a1);
  144.    InitString(&a2);
  145.    StrCopy(&a1,S1);
  146.    StrCopy(&a2,S2);
  147.    (*T).curlen=S1.curlen+S2.curlen;
  148.    (*T).head=a1.head;
  149.    a1.tail->next=a2.head;
  150.    (*T).tail=a2.tail;
  151.    return OK;
  152. }

  153. Status SubString(LString *Sub, LString S,int pos,int len)
  154. { /* 用Sub返回串S的第pos个字符起长度为len的子串。 */
  155.    /* 其中,1≤pos≤StrLength(S)且0≤len≤StrLength(S)-pos+1 */
  156.    Chunk *p,*q;
  157.    int i,k,n,flag=1;
  158.    if(pos<1||pos>S.curlen||len<0||len>S.curlen-pos+1)
  159.      return ERROR;
  160.    n=len/CHUNKSIZE; /* 生成空的Sub串 */
  161.    if(len%CHUNKSIZE)
  162.      n++; /* n为块的个数 */
  163.    p=(Chunk*)malloc(sizeof(Chunk));
  164.    (*Sub).head=p;
  165.    for(i=1;i<n;i++)
  166.    {
  167.      q=(Chunk*)malloc(sizeof(Chunk));
  168.      p->next=q;
  169.      p=q;
  170.    }
  171.    p->next=NULL;
  172.    (*Sub).tail=p;
  173.    (*Sub).curlen=len;
  174.    for(i=len%CHUNKSIZE;i<CHUNKSIZE;i++)
  175.      *(p->ch+i)=blank; /* 填充Sub尾部的多余空间 */
  176.    q=(*Sub).head; /* q指向Sub串即将复制的块 */
  177.    i=0; /* i指示即将复制的字符在块中的位置 */
  178.    p=S.head; /* p指向S串的当前块 */
  179.    n=0; /* n指示当前字符在串中的序号 */
  180.    while(flag)
  181.    {
  182.      for(k=0;k<CHUNKSIZE;k++) /* k指示当前字符在块中的位置 */
  183.        if(*(p->ch+k)!=blank)
  184.        {
  185.          n++;
  186.          if(n>=pos&&n<=pos+len-1) /* 复制 */
  187.          {
  188.            if(i==CHUNKSIZE)
  189.            { /* 到下一块 */
  190.              q=q->next;
  191.              i=0;
  192.            }
  193.            *(q->ch+i)=*(p->ch+k);
  194.            i++;
  195.            if(n==pos+len-1) /* 复制结束 */
  196.            {
  197.              flag=0;
  198.              break;
  199.            }
  200.          }
  201.        }
  202.      p=p->next;
  203.    }
  204.    return OK;
  205. }

  206. int Index(LString S,LString T,int pos)
  207. { /* T为非空串。若主串S中第pos个字符之后存在与T相等的子串, */
  208.    /* 则返回第一个这样的子串在S中的位置,否则返回0 */
  209.    int i,n,m;
  210.    LString sub;
  211.    if(pos>=1&&pos<=StrLength(S)) /* pos满足条件 */
  212.    {
  213.      n=StrLength(S); /* 主串长度 */
  214.      m=StrLength(T); /* T串长度 */
  215.      i=pos;
  216.      while(i<=n-m+1)
  217.      {
  218.        SubString(&sub,S,i,m); /* sub为从S的第i个字符起,长度为m的子串 */
  219.        if(StrCompare(sub,T)!=0) /* sub不等于T */
  220.          ++i;
  221.        else
  222.          return i;
  223.      }
  224.    }
  225.    return 0;
  226. }

  227. void Zip(LString *S)
  228. { /* 压缩串(清除块中不必要的填补空余的字符)。加 */
  229.    int j,n=0;
  230.    Chunk *h=(*S).head;
  231.    char *q;
  232.    q=(char*)malloc(((*S).curlen+1)*sizeof(char));
  233.    while(h) /* 将LString类型的字符串转换为char[]类型的字符串 */
  234.    {
  235.      for(j=0;j<CHUNKSIZE;j++)
  236.        if(*(h->ch+j)!=blank)
  237.        {
  238.          *(q+n)=*(h->ch+j);
  239.          n++;
  240.        }
  241.      h=h->next;
  242.    }
  243.    *(q+n)=0; /* 串结束符 */
  244.    ClearString(S); /* 清空S */
  245.    StrAssign(S,q); /* 重新生成S */
  246. }

  247. Status StrInsert(LString *S,int pos,LString T)
  248. { /* 1≤pos≤StrLength(S)+1。在串S的第pos个字符之前插入串T */
  249.    int i,j,k;
  250.    Chunk *p,*q;
  251.    LString t;
  252.    if(pos<1||pos>StrLength(*S)+1) /* pos超出范围 */
  253.      return ERROR;
  254.    StrCopy(&t,T); /* 复制T为t */
  255.    Zip(S); /* 去掉S中多余的填补空余的字符 */
  256.    i=(pos-1)/CHUNKSIZE; /* 到达插入点要移动的块数 */
  257.    j=(pos-1)%CHUNKSIZE; /* 到达插入点在最后一块上要移动的字符数 */
  258.    p=(*S).head;
  259.    if(pos==1) /* 插在S串前 */
  260.    {
  261.      t.tail->next=(*S).head;
  262.      (*S).head=t.head;
  263.    }
  264.    else if(j==0) /* 插在块之间 */
  265.    {
  266.      for(k=1;k<i;k++)
  267.        p=p->next; /* p指向插入点的左块 */
  268.      q=p->next; /* q指向插入点的右块 */
  269.      p->next=t.head; /* 插入t */
  270.      t.tail->next=q;
  271.      if(q==NULL) /* 插在S串后 */
  272.        (*S).tail=t.tail; /* 改变尾指针 */
  273.    }
  274.    else /* 插在一块内的两个字符之间 */
  275.    {
  276.      for(k=1;k<=i;k++)
  277.        p=p->next; /* p指向插入点所在块 */
  278.      q=(Chunk*)malloc(sizeof(Chunk)); /* 生成新块 */
  279.      for(i=0;i<j;i++)
  280.        *(q->ch+i)=blank; /* 块q的前j个字符为填补空余的字符 */
  281.      for(i=j;i<CHUNKSIZE;i++)
  282.      {
  283.        *(q->ch+i)=*(p->ch+i); /* 复制插入点后的字符到q */
  284.        *(p->ch+i)=blank; /* p的该字符为填补空余的字符 */
  285.      }
  286.      q->next=p->next;
  287.      p->next=t.head;
  288.      t.tail->next=q;
  289.    }
  290.    (*S).curlen+=t.curlen;
  291.    Zip(S);
  292.    return OK;
  293. }

  294. Status StrDelete(LString *S,int pos,int len)
  295. { /* 从串S中删除第pos个字符起长度为len的子串 */
  296.    int i=1; /* 当前字符是S串的第i个字符(1~S.curlen) */
  297.    Chunk *p=(*S).head; /* p指向S的当前块 */
  298.    int j=0; /* 当前字符在当前块中的位序(0~CHUNKSIZE-1) */
  299.    if(pos<1||pos>(*S).curlen-len+1||len<0) /* pos,len的值超出范围 */
  300.      return ERROR;
  301.    while(i<pos) /* 找第pos个字符 */
  302.    {
  303.      while(*(p->ch+j)==blank) /* 跳过填补空余的字符 */
  304.      {
  305.        j++;
  306.        if(j==CHUNKSIZE) /* 应转向下一块 */
  307.        {
  308.          p=p->next;
  309.          j=0;
  310.        }
  311.      }
  312.      i++; /* 当前字符是S的第i个字符 */
  313.      j++;
  314.      if(j==CHUNKSIZE) /* 应转向下一块 */
  315.      {
  316.        p=p->next;
  317.        j=0;
  318.      }
  319.    }; /* i=pos,*(p->ch+j)为S的第pos个有效字符 */
  320.    while(i<pos+len) /* 删除从第pos个字符起到第pos+len-1个字符 */
  321.    {
  322.      while(*(p->ch+j)==blank) /* 跳过填补空余的字符 */
  323.      {
  324.        j++;
  325.        if(j==CHUNKSIZE) /* 应转向下一块 */
  326.        {
  327.          p=p->next;
  328.          j=0;
  329.        }
  330.      }
  331.      *(p->ch+j)=blank; /* 把字符改成填补空余的字符来"删除"第i个字符 */
  332.      i++; /* 到下一个字符 */
  333.      j++;
  334.      if(j==CHUNKSIZE) /* 应转向下一块 */
  335.      {
  336.        p=p->next;
  337.        j=0;
  338.      }
  339.    };
  340.    (*S).curlen-=len; /* 串的当前长度 */
  341.    return OK;
  342. }

  343. Status Replace(LString *S,LString T,LString V)
  344. { /* 初始条件: 串S,T和V存在,T是非空串(此函数与串的存储结构无关) */
  345.    /* 操作结果: 用V替换主串S中出现的所有与T相等的不重叠的子串 */
  346.    int i=1; /* 从串S的第一个字符起查找串T */
  347.    if(StrEmpty(T)) /* T是空串 */
  348.      return ERROR;
  349.    do
  350.    {
  351.      i=Index(*S,T,i); /* 结果i为从上一个i之后找到的子串T的位置 */
  352.      if(i) /* 串S中存在串T */
  353.      {
  354.        StrDelete(S,i,StrLength(T)); /* 删除该串T */
  355.        StrInsert(S,i,V); /* 在原串T的位置插入串V */
  356.        i+=StrLength(V); /* 在插入的串V后面继续查找串T */
  357.      }
  358.    }while(i);
  359.    return OK;
  360. }

  361. void StrPrint(LString T)
  362. { /* 输出字符串T。另加 */
  363.    int i=0,j;
  364.    Chunk *h;
  365.    h=T.head;
  366.    while(i<T.curlen)
  367.    {
  368.      for(j=0;j<CHUNKSIZE;j++)
  369.        if(*(h->ch+j)!=blank) /* 不是填补空余的字符 */
  370.        {
  371.          printf("%c",*(h->ch+j));
  372.          i++;
  373.        }
  374.      h=h->next;
  375.    }
  376.    printf("\n");
  377. }

  378. void DestroyString()
  379. { /* 块链类型的字符串无法销毁 */
  380. }
复制代码


回复

使用道具 举报

Archiver|手机版|小黑屋|三木电子社区 ( 辽ICP备11000133号-4 )

辽公网安备 21021702000620号

GMT+8, 2025-12-8 00:50 , Processed in 0.029506 second(s), 23 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表