数据结构 study 5: typedef 结构体 数组 作为形参

本文详细介绍了C语言实现的动态单链表数据结构,包括内存分配、回收、初始化、操作函数(如插入、删除、遍历),以及用于比较两个集合并创建差集的算法。通过实例展示了如何使用这些函数处理集合A和B。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码

在这里插入图片描述
page43
数据结构-- 严蔚敏 – 第1版

/* c1.h (程序名) */
#include<string.h>
#include<ctype.h>
#include<malloc.h> /* malloc()等 */
#include<limits.h> /* INT_MAX等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<stdlib.h> /* atoi() */
#include <sys/io.h> /* eof() */
#include<math.h> /* floor(),ceil(),abs() */

#include<pthread.h> /* exit() */
/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
/* #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 */
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */


#if 0
请输入集合A和B的元素个数m,n:6,4
请输入集合A的元素(共6个):cbegfd
请输入集合B的元素(共4个):abnf
c e g d n a
#endif 


#define N 2
typedef char ElemType;

/* c2-3.h 线性表的静态单链表存储结构 */
#define MAXSIZE 12 /* 链表的最大长度 */
typedef struct
{
  ElemType data;
  int cur;
}component,SLinkList[MAXSIZE];


/* bo2-3.c 实现算法2.15、2.16的程序 (数据结构由c2-3.h定义) (3个) */
int Malloc(SLinkList space) /* 算法2.15 */
{ /* 若备用链表非空,则返回分配的结点下标(备用链表的第一个结点),否则返回0 */
  int i=space[0].cur;
  if(i) /* 备用链表非空 */
    space[0].cur=space[i].cur; /* 备用链表的头结点指向原备用链表的第二个结点 */
  return i; /* 返回新开辟结点的坐标 */
}

void Free(SLinkList space,int k) /* 算法2.16 */
{ /* 将下标为k的空闲结点回收到备用链表(成为备用链表的第一个结点) */
  space[k].cur=space[0].cur; /* 回收结点的"游标"指向备用链表的第一个结点 */
  space[0].cur=k; /* 备用链表的头结点指向新回收的结点 */
}

void DestroyList()
{ /* 静态数组不能被销毁 */
}



/* bo2-32.c 一个数组可生成若干静态链表(数据结构由c2-3.h定义)的基本操作(12个) */
void InitSpace(SLinkList L) /* 算法2.14。另加 */
{ /* 将一维数组L中各分量链成一个备用链表,L[0].cur为头指针。“0”表示空指针 */
  int i;

  for(i=0;i<MAXSIZE-1;i++){
    L[i].cur=i+1;
    L[i].data = ' ';
  }
  L[MAXSIZE-1].data = ' ';
  L[MAXSIZE-1].cur=0;

  #if 1
  printf("MAXSIZE = %d\n",MAXSIZE);
    i=0;   
    while(i < MAXSIZE) /* 输出教科书中图2.10(a)的状态 */
    {
     printf("%3d",i); /* 输出链表的当前值 */
     printf("%3s"," ");
     i++ ;
    }    

    printf("\n");

    i=0;   
    while(i < MAXSIZE) /* 输出教科书中图2.10(a)的状态 */
    {
     printf("%3d",L[i].cur); /* 输出链表的当前值 */
     printf("%3s"," ");
     i++ ;
    }    

    printf("\n");    

  #endif   
}

int InitList(SLinkList L)
{ /* 构造一个空链表,返回值为空表在数组中的位序 */
  int i;
  i=Malloc(L); /* 调用Malloc(),简化程序 */
  L[i].cur=0; /* 空链表的表头指针为空(0) */
  return i;
}

Status ClearList(SLinkList L,int n)
{ /* 初始条件:L中表头位序为n的静态链表已存在。操作结果:将此表重置为空表 */
  int j,k,i=L[n].cur; /* 链表第一个结点的位置 */
  L[n].cur=0; /* 链表空 */
  k=L[0].cur; /* 备用链表第一个结点的位置 */
  L[0].cur=i; /* 把链表的结点连到备用链表的表头 */
  while(i) /* 没到链表尾 */
  {
    j=i;
    i=L[i].cur; /* 指向下一个元素 */
  }
  L[j].cur=k; /* 备用链表的第一个结点接到链表的尾部 */
  return OK;
}

Status ListEmpty(SLinkList L,int n)
{ /* 判断L中表头位序为n的链表是否空,若是空表返回TRUE;否则返回FALSE */
  if(L[n].cur==0) /* 空表 */
    return TRUE;
  else
    return FALSE;
}

int ListLength(SLinkList L,int n)
{ /* 返回L中表头位序为n的链表的数据元素个数 */
  int j=0,i=L[n].cur; /* i指向第一个元素 */
  while(i) /* 没到静态链表尾 */
  {
    i=L[i].cur; /* 指向下一个元素 */
    j++;
  }
  return j;
}

Status GetElem(SLinkList L,int n, int i,ElemType *e)
{ /* 用e返回L中表头位序为n的链表的第i个元素的值 */
  int l,k=n; /* k指向表头序号 */
  if(i<1||i>ListLength(L,n)) /* i值不合理 */
    return ERROR;
  for(l=1;l<=i;l++) /* 移动i-1个元素 */
    k=L[k].cur;
  *e=L[k].data;
  return OK;
}

int LocateElem(SLinkList L,int n,ElemType e)
{ /* 在L中表头位序为n的静态单链表中查找第1个值为e的元素。 */
  /* 若找到,则返回它在L中的位序,否则返回0 */
  int i=L[n].cur; /* i指示表中第一个结点 */
  while(i&&L[i].data!=e) /* 在表中顺链查找(e不能是字符串) */
    i=L[i].cur;
  return i;
}

Status PriorElem(SLinkList L,int n,ElemType cur_e,ElemType *pre_e)
{ /* 初始条件:在L中表头位序为n的静态单链表已存在 */
  /* 操作结果:若cur_e是此单链表的数据元素,且不是第一个, */
  /*           则用pre_e返回它的前驱,否则操作失败,pre_e无定义 */
  int j,i=L[n].cur; /* i为链表第一个结点的位置 */
  do
  { /* 向后移动结点 */
    j=i;
    i=L[i].cur;
  }while(i&&cur_e!=L[i].data);
  if(i) /* 找到该元素 */
  {
    *pre_e=L[j].data;
    return OK;
  }
  return ERROR;
}

Status NextElem(SLinkList L,int n,ElemType cur_e,ElemType *next_e)
{ /* 初始条件:在L中表头位序为n的静态单链表已存在 */
  /* 操作结果:若cur_e是此单链表的数据元素,且不是最后一个, */
  /* 则用next_e返回它的后继,否则操作失败,next_e无定义 */
  int i;
  i=LocateElem(L,n,cur_e); /* 在链表中查找第一个值为cur_e的元素的位置 */
  if(i) /* 在静态单链表中存在元素cur_e */
  {
    i=L[i].cur; /* cur_e的后继的位置 */
    if(i) /* cur_e有后继 */
    {
      *next_e=L[i].data;
      return OK; /* cur_e元素有后继 */
    }
  }
  return ERROR; /* L不存在cur_e元素,cur_e元素无后继 */
}

Status ListInsert(SLinkList L,int n,int i,ElemType e)
{ /* 在L中表头位序为n的链表的第i个元素之前插入新的数据元素e */
  int l,j,k=n; /* k指向表头 */
  if(i<1||i>ListLength(L,n)+1)
    return ERROR;
  j=Malloc(L); /* 申请新单元 */
  if(j) /* 申请成功 */
  {
    L[j].data=e; /* 赋值给新单元 */
    for(l=1;l<i;l++) /* 移动i-1个元素 */
      k=L[k].cur;
    L[j].cur=L[k].cur;
    L[k].cur=j;
    return OK;
  }
  return ERROR;
}

Status ListDelete(SLinkList L,int n,int i,ElemType *e)
{ /* 删除在L中表头位序为n的链表的第i个数据元素e,并返回其值 */
  int j,k=n; /* k指向表头 */
  if(i<1||i>ListLength(L,n))
    return ERROR;
  for(j=1;j<i;j++) /* 移动i-1个元素 */
    k=L[k].cur;
  j=L[k].cur;
  L[k].cur=L[j].cur;
  *e=L[j].data;
  Free(L,j);
  return OK;
}

Status ListTraverse(SLinkList L,int n,void(*vi)(ElemType))
{ /* 依次对L中表头位序为n的链表的每个数据元素,调用函数vi()。一旦vi()失败,则操作失败 */
  int i=L[n].cur; /* 指向第一个元素 */
  while(i) /* 没到静态链表尾 */
  {
    vi(L[i].data); /* 调用vi() */
    i=L[i].cur; /* 指向下一个元素 */
  }
  printf("\n");
  return OK;
}


void show_space_content(SLinkList space)
{ int i ;
  printf("\n\n\nMAXSIZE = %d\n",MAXSIZE);
    i=0;   
    while(i < MAXSIZE) /* 输出教科书中图2.10(a)的状态 */
    {
     printf("%3d",i); /* 输出链表的当前值 */
     printf("%3s"," ");
     i++ ;
    }    

    printf("\n");
    
    i=0;   
    while(i < MAXSIZE) /* 输出教科书中图2.10(a)的状态 */
    {
     printf("%3c",space[i].data); /* 输出链表的当前值 */
     printf("%3s"," ");
     i++ ;
    }        
    printf("\n");  

    i=0;   
    while(i < MAXSIZE) /* 输出教科书中图2.10(a)的状态 */
    {
     printf("%3d",space[i].cur); /* 输出链表的当前值 */
     printf("%3s"," ");
     i++ ;
    }    

    printf("\n");        
}


void difference_abc(SLinkList space, 
                          int *pt_start,
                          char *ArrayA, 
                          int arraya_len, 
                          char *ArrayB,
                          int arrayb_len
                          )
                          
{
        int head ; //静态链表 头结点
        int tail ; //静态链表 尾结点
        int i ; 

        int index = 0 ;
        
        InitSpace(space);
        show_space_content(space);        
        head = Malloc(space);
        show_space_content(space);  
        *pt_start = head ;
        tail = head ;

        
        for(i=0;i<arraya_len;i++)
        {
             index = Malloc(space);
             show_space_content(space);  
             space[index].data = ArrayA[i];
             space[tail].cur = index ;

             tail = index ;
        }
        
        space[tail].cur = 0 ;

        show_space_content(space);

        int pos = 0 ;
        int pre_pos =0  ;

        printf("\n\n begin to compare: \n\n");

        for(i=0; i< arrayb_len; i++)
        {

            pos = space[head].cur ;
            pre_pos = pos ;
            while(pos !=space[tail].cur){

                if(space[pos].data == ArrayB[i]){

                    break ;
                }
                pre_pos = pos ;
                pos = space[pos].cur ;
            }

            if(pos == space[tail].cur){
                /* 当前表中不存在该元素,插入在tail所指结点之后,且tail的位置不变 */
                printf("new %c\n", ArrayB[i]);    
                  index=Malloc(space);
                  space[index].data=ArrayB[i];
                  space[index].cur=space[tail].cur;
                  space[tail].cur=index;   
                  show_space_content(space);

            }else{/* 该元素已在表中,删除之 */

              space[pre_pos].cur=space[pos].cur;
              printf("delete %c\n", ArrayB[i]);  
              Free(space,pos);
              show_space_content(space);
              if(tail==pos){
                tail=pre_pos; /* 若删除的是尾元素,则需修改尾指针 */
              }                

            }
            

            
        }
        
        show_space_content(space);
}

void difference(SLinkList space,int *S) /* 算法2.17 */
{ /* 依次输入集合A和B的元素,在一维数组space中建立表示集合(A-B)∪(B-A) */
  /* 的静态链表,S为其头指针。假设备用空间足够大,space[0].cur为备用空间的头指针 */
  int r,p,m,n,i,j,k;
  ElemType b;
  ElemType ch ;
  InitSpace(space); /* 初始化备用空间 */
  *S=Malloc(space); /* 生成S的头结点 */
  r=*S; /* r指向S的当前最后结点 */
  printf("r = %d\n",r);
  printf("请输入集合A的元素个数m:\n");
  scanf("%d",&m);
  scanf("%*c"); /* %*c吃掉回车符 */
  printf("m = %d\n",m);  
  //printf("请输入集合A和B的元素个数m,n:");
  //scanf("%d,%d%*c",&m,&n); /* %*c吃掉回车符 */
  printf("请输入集合A的元素(共%d个):\n",m);

  for(j=1;j<=m;j++) /* 建立集合A的链表 */
  {
    i=Malloc(space); /* 分配结点 */
    scanf("%c",&ch); /* 输入A的元素值 */
    printf("%c -- %d\n",ch,i);
    space[i].data = ch ;
    space[r].cur=i; /* 插入到表尾 */
    printf("i = %d,r = %d, ch = %c\n",i, r,ch);
    
    r=i;
  
  }
  printf("i = %d,r = %d, ch = %c\n",i, r,ch);
  
  scanf("%*c"); /* %*c吃掉回车符 */
  space[r].cur=0; /* 尾结点的指针为空 */

  printf("请输入集合B的元素个数n:\n");
  scanf("%d",&n);
  scanf("%*c"); /* %*c吃掉回车符 */
  printf("n = %d\n",n);
  printf("请输入集合B的元素(共%d个):\n",n);
  for(j=1;j<=n;j++)
  { /* 依次输入B的元素,若不在当前表中,则插入,否则删除 */
    scanf("%c",&b);

    printf("b = %c\n",b);    
    p=*S;
    k=space[*S].cur; /* k指向集合A中的第一个结点 */
    printf("k = %d\n",k);
    while(k!=space[r].cur&&space[k].data!=b)
    { /* 在当前表中查找 */
      p=k;
      k=space[k].cur;
    }

    printf("refer data  :  cbegfd\n");
    printf("p=%d,k=%d,r =%d, space[r].cur = %d\n\n\n",p,k,r,space[r].cur);
    
    if(k==space[r].cur)
    { /* 当前表中不存在该元素,插入在r所指结点之后,且r的位置不变 */
      i=Malloc(space);
      space[i].data=b;
      space[i].cur=space[r].cur;
      space[r].cur=i;
      printf("\n not exist \n");
    }
    else /* 该元素已在表中,删除之 */
    {
      space[p].cur=space[k].cur;
      
      Free(space,k);
      
      if(r==k){
        r=p; /* 若删除的是尾元素,则需修改尾指针 */
      }

      printf("\n exist \n");
    }
  }
  scanf("%*c"); /* %*c吃掉回车符 */
}

void visit(ElemType c)
{
  printf("%c ",c);
}

void main()
{
  int k;
  SLinkList s;
  int m ;
  int n ;
  int i ;
  int ch ;
  char ArrayA[MAXSIZE];
  int arrayA_cnt = 0 ;
  char ArrayB[MAXSIZE];
  int arrayB_cnt = 0 ;  

  printf("请输入集合A的元素个数m: %d\n",6);
  printf("请输入集合A的元素(共6个):cbegfd\n");
  
  printf("请输入集合B的元素个数n:%d\n",4);
  printf("请输入集合B的元素(共4个):abnf\n");

  printf("c e g d n a\n");


  printf("请输入集合A的元素个数m--(eg:6):\n");
  scanf("%d",&m);
  scanf("%*c"); /* %*c吃掉回车符 */
  printf("m = %d\n",m); 
  printf("请输入集合A的元素(共%d个):(eg:cbegfd)\n",m);

  for(i=0; i<m;i++){

    ch = getchar();
    ArrayA[i] = ch ;
    arrayA_cnt++ ;
  }

  printf("请输入集合B的元素个数n:(eg:4)\n");
  scanf("%d",&n);
  scanf("%*c"); /* %*c吃掉回车符 */
  printf("n = %d\n",n);
  printf("请输入集合B的元素(共%d个): (eg: abnf)\n",n);

  for(i=0; i<n;i++){

    ch = getchar();
    ArrayB[i] = ch ;
    arrayB_cnt++ ;
  }  
  
  
 // difference(s,&k);
  //printf("\nk = %d\n", k);

  difference_abc(s,&k,ArrayA,arrayA_cnt,ArrayB,arrayB_cnt);

  
  ListTraverse(s,k,visit);
}


运行效果:
请输入集合A的元素个数m: 6
请输入集合A的元素(共6个):cbegfd
请输入集合B的元素个数n:4
请输入集合B的元素(共4个):abnf
c e g d n a
请输入集合A的元素个数m--(eg:6):
6
m = 6
请输入集合A的元素(共6个):(eg:cbegfd)
cbegfd
请输入集合B的元素个数n:(eg:4)
4
n = 4
请输入集合B的元素(共4个): (eg: abnf)
abnf
MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11
  1     2     3     4     5     6     7     8     9    10    11     0



MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11

  1     2     3     4     5     6     7     8     9    10    11     0



MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11

  2     2     3     4     5     6     7     8     9    10    11     0



MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11

  3     2     3     4     5     6     7     8     9    10    11     0



MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11
              c
  4     2     3     4     5     6     7     8     9    10    11     0



MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11
              c     b
  5     2     3     4     5     6     7     8     9    10    11     0



MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11
              c     b     e
  6     2     3     4     5     6     7     8     9    10    11     0



MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11
              c     b     e     g
  7     2     3     4     5     6     7     8     9    10    11     0



MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11
              c     b     e     g     f
  8     2     3     4     5     6     7     8     9    10    11     0



MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11
              c     b     e     g     f     d
  8     2     3     4     5     6     7     0     9    10    11     0


 begin to compare:

new a



MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11
              c     b     e     g     f     d     a
  9     2     3     4     5     6     7     8     0    10    11     0
delete b



MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11
              c     b     e     g     f     d     a
  3     2     4     9     5     6     7     8     0    10    11     0
new n



MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11
              c     n     e     g     f     d     a
  9     2     4     8     5     6     7     3     0    10    11     0
delete f



MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11
              c     n     e     g     f     d     a
  6     2     4     8     5     7     9     3     0    10    11     0



MAXSIZE = 12
  0     1     2     3     4     5     6     7     8     9    10    11
              c     n     e     g     f     d     a
  6     2     4     8     5     7     9     3     0    10    11     0
c e g d n a

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值