第一章   绪论
P8 
例:  计算f=1!+2!+3!+…+n!,用C语言描述。
void  factorsum(n)
int  n;
{
int  i,j;
int  f,w;
f=0;
for (i=1;i〈=n;i++)
{
w=1;
for (j=1;j〈=i;j++)
w=w*j;
f=f+w;
}
return;
}


第二章  线性表
P16【算法2.1  顺序表的插入】
int Insert(Elemtype List[],int *num,int i,Elemtype x)
{/*在顺序表List[]中,*num为表尾元素下标位置,在第i个元素前插入数据元素x,若成功,返回TRUE,否则返回FALSE。*/
int j;
  if (i<0||i>*num+1)
    {printf("Error!");       /*插入位置出错*/
    return FALSE;}
  if (*num>=MAXNUM-1)
    {printf("overflow!");
    return FALSE;}     /*表已满*/
for (j=*num;j>=i;j--)
List[j+1]=List[j];     /*数据元素后移*/
List[i]=x;         /*插入x*/
(*num)++;      /*长度加1*/
return TRUE;}

P18【算法2.2  顺序表的删除】
int Delete(Elemtype List[],int *num,int i)
{/*在线性表List[]中,*num为表尾元素下标位置,删除第i个长度,线性表的长度减1,若成功,则返回TRUE;否则返回FALSE。*/
int j;
if(i<0||i>*num)
{printf("Error!");  return FALSE; }   /*删除位置出错!*/
for(j=i+1;j<=*num;j++)
List[j-1]=List[j];      /*数据元素前移*/
   (*num)--;      /*长度减1*/
return  TRUE; }

P19 例:将有序线性表La={2,4,6,7,9},Lb={1,5,7,8},合并为Lc={1,2,4,5,6,7,7,8,9}。
void merge(Elemtype La[],Elemtype Lb[],Elemtype **Lc)
{  int i,j,k; 
   int La_length,Lb_length;
   i=j=0;k=0;
   La_length=Length(La);Lb_length=Length(Lb); /*取表La,Lb的长度*/
   Initiate(Lc);        /*初始化表Lc*/
   While (i<=La_length&&j<=Lb_length)
     {  a=get(La,i);b=get(Lb,j);
        if(a<b) {insert(Lc,++k,a);++i;}
        else {insert(Lc,++k,b);++j;}
      }          /*将La和Lb的元素插入到Lc中*/
while (i<=La_length) { a=get(La,i);insert(Lc,++k,a);}
while (j<=lb_length) { b=get(La,j);insert(Lc,++k,b);  }   }

P21例如:下面定义的结点类型中,数据域包含三个数据项:学号、姓名、成绩。
Struct student
{ char num[8];           /*数据域*/
har name[8];         /*数据域*/
  int score;            /*数据域*/
  struct student *next;  /*指针域*/
}

P21单链表结点结构定义为:
Typedef struct slnode
{ Elemtype data;
   struct slnode *next;
}slnodetype;
slnodetype *p,*q,*s;

P21 【算法2.3  单链表的初始化】
 int Initiate(slnodetype * *h)
 { if((*h=(slnodetype*)malloc(sizeof(slnodetype)))==NULL) return FALSE;
   (*h)->next=NULL;
   return TRUE; }

P22 【算法2.4  单链表的后插入】
{ s=(slnodetype*)malloc(sizeof(slnodetype));
   s->data=x;
   s->next=p->next;p->next=s;}

P22 【算法2.5  单链表的结点插入】
{q=head;
  while(q->next!=p) q=q->next;
  s=(slnodetype*)malloc(sizeof(slnodetype));
  s->data=x;
  s->next=p;
  q->next=s;}

P23【算法2.6  单链表的前插入】
int insert(slnodetype *h,int i,Elemtype x)
{/*在链表h中,在第i个数据元素前插入一个数据元素x */
  slnodetype *p,*q,*s;
  int j=0;
  p=h;
  while(p!=NULL&&j<i-1) { p=q->next;j++;    /*寻找第i-1个结点*/ }
  if ( j!=i-1) {printf("Error!");return FALSE;   /*插入位置错误*/}
  if ((s=(slnodetype*)malloc(sizeof(slnodetype)))==NULL) return FALSE;
  s->data=x;
  s->next=p->next;
  q->next=s;
  return TRUE;}

P23例:下面C程序中的功能是,首先建立一个线性链表head={3,5,7,9},其元素值依次为从键盘输入正整数(以输入一个非正整数为结束);在线性表中值为x的元素前插入一个值为y的数据元素。若值为x的结点不存在,则将y插在表尾。
#include "stdlib.h"
#include "stdio.h"
struct slnode
{int data;
struct slnode *next;}   /*定义结点类型*/
main()
{int x,y,d;
struct slnode *head,*p,*q,*s;
  head=NULL;    /*置链表空*/
  q=NULL;  
  scanf("%d",&d); /*输入链表数据元素*/
  while(d>0)
  {p=(struct slnode*)malloc(sizeof(struct slnode)); /*申请一个新结点*/
   p->data=d;
   p->next=NULL;
   if(head==NULL) head=p; /*若链表为空,则将头指针指向当前结点p*/
   else q->next=p;   /*链表不为空时,则将新结点链接在最后*/
   q=p;  /*将指针q指向链表的最后一个结点*/
  scanf("%d",&d);}
  scanf("%d,%d",&x,&y);
  s=(struct slnode*)malloc(sizeof(struct slnode));
  s->data=y;
  q=head;p=q->next;
  while((p!=NULL)&&(p->data!=x)) {q=p;p=p->next;} /*查找元素为x的指针*/
  s->next=p;q->next=s;  /*插入元素y*/
}

P24【算法2.7  单链表的删除】
int Delet(slnodetype *h,int i)
{ /*在链表h中删除第i个结点*/
  slnodetype *p,*s;
   int j;
   p=h;j=0;
  while(p->next!=NULL&&j<i-1)
{ p=p->next;j=j+1; /*寻找第i-1个结点,p指向其前驱*/}
  if(j!=i-1)
     {printf("Error!"); /*删除位置错误!*/
       return FALSE; }
  s=p->next;
  p->next=p->next->next;  /*删除第i个结点*/
  free(s);  /*释放被删除结点空间*/
  return TRUE;
}

P25例:假设已有线性链表La,编制算法将该链表逆置。
void converse(slnodetype *head)
{slnodetype *p,*q;
  p=head->next;
  head->next=NULL;
  while(p!=NULL)
   { q=p->next;
     p->next=head->next;
     head->next=p;
     p=q; }
}

P27例:将两个循环链表首尾相接。La为第一个循环链表表尾指针,Lb为第二个循环链表表尾指针。合并后Lb为新链表的尾指针。
Void merge(slnodetype *La,slnodetype *Lb)
  { slnodetype *p;
   p=La->next;
   Lb->next= La->next;
   La->next=p->next;
   free(p);
  }

P29【算法2.8  双向链表的插入】
int insert_dul(dlnodetype *head,int i,Elemtype x)
{/*在带头结点的双向链表中第i个位置之前插入元素x*/
  dlnodetype *p,*s;
  int j;
  p=head;
  j=0;
  while (p!=NULL&&j<i)
  { p=p->next;
   j++; }
if(j!=i||i<1)
{ printf("Error!");
    return FALSE;}
if((s=(dlnodetype *)malloc(sizeof(dlnodetype)))==NULL) return FALSE;
s->data=x;
s->prior=p->prior; /*图中步骤①*/
p->prior->next=s; /*图中步骤②*/
s->next=p; /*图中步骤③*/
p->prior=s; /*图中步骤④*/
return TRUE;}

P30【算法2.9  双向链表的删除】
int  Delete_dl(dlnodetype *head,int i)
{ dlnodetype *p,*s;
  int j;
  p=head;
  j=0;
  while (p!=NULL&&j<i)
 { p=p->next;
   j++; }
if(j!=i||i<1)
{ printf("Error!");
   return FALSE;}
s=p;
p->prior->next=p->next; /*图中步骤①*/
p->next->prior=p->prior; /*图中步骤②*/
free(s);
return TRUE;}

P32【算法2.10  多项式相加】
struct poly *add_poly(struct poly *Ah,struct poly *Bh)
{struct poly *qa,*qb,*s,*r,*Ch;
qa=Ah->next;qb=Bh->next;  /*qa和qb分别指向两个链表的第一结点*/
r=qa;Ch=Ah;  /*将链表Ah作为相加后的和链表*/
while(qa!=NULL&&qb!=NULL)   /*两链表均非空*/
{ if (qa->exp==qb->exp)    /*两者指数值相等*/
      {x=qa->coef+qb->coef;
        if(x!=0)
            { qa->coef=x;r->next=qa;r=qa;
             s=qb++;free(s);qa++;
             }        /*相加后系数不为零时*/
        else {s=qa++;free(s);s=qb++;free(s);}   /*相加后系数为零时*/
        }
  else if(qa->exp<qb->exp){ r->next=qa;r=qa;qa++;} /*多项式Ah的指数值小*/
       else {r->next=qb;r=qb;qb++;}     /*多项式Bh的指数值小*/
}
if(qa==NULL) r->next=qb;
else r->next=qa;         /*链接多项式Ah或Bh中的剩余结点*/
return (Ch);
}


第三章  栈和队列
P35相应的C语言函数是:
float fact(int n)
{float s;
 if (n= =0||n= =1)  s=1;
 else s=n*fact(n-1);
 return (s); }

P38用C语言定义的顺序存储结构的栈如下:
# define MAXNUM <最大元素数>
typedef struct {
Elemtype stack[MAXNUM];
int top; } sqstack;

P39【算法3.1  栈的初始化】
int initStack(sqstack *s)
{/*创建一个空栈由指针S指出*/
  if ((s=(sqstack*)malloc(sizeof(sqstack)))= =NULL) return FALSE;
  s->top= -1;
return TRUE;
}

P39【算法3.2  入栈操作】
int push(sqstack *s, Elemtype x)
{/*将元素x插入到栈s中,作为s的新栈顶*/
  if(s->top>=MAXNUM-1)  return FALSE;  /*栈满*/
  s->top++;
  s->stack[s->top]=x;
return  TRUE;
}

P39【算法3.3  出栈操作】
Elemtype pop(sqstack *s)
{/*若栈s不为空,则删除栈顶元素*/
Elemtype  x;
 if(s->top<0) return NULL;   /*栈空*/
x=s->stack[s->top];
s->top--;
return x;
}

P39【算法3.4  取栈顶元素】
Elemtype getTop(sqstack *s)
{/*若栈s不为空,则返回栈顶元素*/
  if(s->top<0) return NULL;   /*栈空*/
return (s->stack[s->top]);
}

P40【算法3.5  判栈空操作】
int Empty(sqstack *s)
{/*栈s为空时,返回为TRUE;非空时,返回为FALSE*/
  if(s->top<0) return TRUE;
  return FALSE;
}

P40【算法3.6  栈置空操作】
void setEmpty(sqstack *s)
{/*将栈s的栈顶指针top,置为-1*/
s->top= -1;
}

P40  C语言定义的这种两栈共享邻接空间的结构如下:
Typedef struct {
  Elemtype stack[MAXNUM];
  int  lefttop;    /*左栈栈顶位置指示器*/
  int  righttop;   /*右栈栈顶位置指示器*/
  } dupsqstack;

P41【算法3.7  共享栈的初始化】
int initDupStack(dupsqstack *s)
{/*创建两个共享邻接空间的空栈由指针S指出*/
 if (s=(dupsqstack*)malloc(sizeof(dupsqstack)))= =NULL) return FALSE;
 s->lefttop= -1;
s->righttop=MAXNUM;
return TRUE;
}

P41【算法3.8  共享栈的入栈操作】
int pushDupStack(dupsqstack *s,char status,Elemtype x)
{*把数据元素x压入左栈(status='L')或右栈(status='R')*/
  if(s->lefttop+1= =s->righttop) return FALSE;   /*栈满*/
  if(status='L')  s->stack[++s->lefttop]=x;    /*左栈进栈*/
    else if(status='R')  s->stack[--s->righttop]=x;  /*右栈进栈*/
    else return FALSE;       /*参数错误*/
return TRUE;
}

P42【算法3.9  共享栈的出栈操作】
Elemtype  popDupStack(dupsqstack *s,char status)
{/*从左栈(status='L')或右栈(status='R')退出栈顶元素*/
   if(status= ='L')
    { if (s->lefttop<0)
        return NULL;      /*左栈为空*/
else return (s->stack[s->lefttop--]);     /*左栈出栈*/ 
}
   else if(status= ='R')
   { if (s->righttop>MAXNUM-1)
        return NULL;      /*右栈为空*/
else return (s->stack[s->righttop++]);   /*右栈出栈*/ 
}
   else  return NULL;      /*参数错误*/
}

P42链栈的C语言定义为:
typedef struct Stacknode
{
Elemtype data;
Struct Stacknode *next;
}slStacktype;

P43【算法3.10  单个链栈的入栈操作】
int pushLstack(slStacktype *top,Elemtype x)
{/*将元素x压入链栈top中*/
slStacktype *p;
if((p=(slStacktype *)malloc(sizeof(slStacktype)))= =NULL) return FALSE; /*申请一个结点*/
p->data=x; p->next=top; top=p; return TRUE;
}

P43【算法3.11  单个链栈的出栈操作】
Elemtype popLstack(slStacktype *top)
{/*从链栈top中删除栈顶元素*/
slStacktype *p;
Elemtype x;
if (top= =NULL) return NULL;   /*空栈*/
p=top; top=top->next;
x=p->data;free(p);return x;
}

P44【算法3.12  多个链栈的入栈操作】
int pushDupLs(slStacktype *top[M],int i,Elemtype x)
{/*将元素x压入链栈top[i]中*/
slStacktype *p;
if((p=(slStacktype *)malloc(sizeof(slStacktype)))= =NULL) return FALSE; /*申请一个结点*/
p->data=x; p->next=top[i]; top[i]=p; return TRUE;
}

P44【算法3.13  多个链栈的出栈操作】
Elemtype popDupLs(slStacktype *top[M],int i)
{/*从链栈top[i]中删除栈顶元素*/
slStacktype *p;
Elemtype x;
if (top[i]= =NULL) return NULL;    /*空栈*/
p=top[i]; top[i]=top[i]->next;
x=p->data;free(p);return x;
}

P47【算法3.14  中缀表达式变为后缀表达式】
# define MAXNUM 40
# define FALSE 0
# define TRUE 1
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
  typedef struct {
  char stack[MAXNUM];
  int top; } sqstack;
  int initStack(sqstack *s)
{/*初始化栈*/
  s->top=-1;
return TRUE;
}
int push(sqstack *s,char x)
{/*将元素x插入到栈s中,作为s的新栈顶*/
  if(s->top>=MAXNUM-1) return FALSE;  /*栈满*/
    s->top++;
s->stack[s->top]=x;
return TRUE;
}
char pop(sqstack *s)
{/*若栈s不为空,则删除栈顶元素*/
char  x;
  if(s->top<0) return NULL;    /*栈空*/
    x=s->stack[s->top];
s->top--;
return x;
}
char gettop(sqstack *s)
{/*若栈s不为空,则返回栈顶元素*/
   if(s->top<0) return NULL;    /*栈空*/
return (s->stack[s->top]);
}
char precede(char x1,char x2)
{/*比较运算符x1与x2的优先*/
char result='<';
char sting[2];
sting[0]=x2;
sting[1]='/0';
if (((x1=='+'||x1=='-')&&(strstr("+-)#",sting)!=NULL))||
((x1=='*'||x1=='/')&&strstr("+-*/)#",sting)!=NULL)||
(x1==')'&&strstr("+-*/)#",sting)!=NULL))
   {result='>';}
else if(x1=='('&&x2==')'||x1=='#'&&x2=='#')
   {result='=';}
else if (x1==')'&&x2=='('||x1=='#'&&x2==')')
   {result=' ';}
  return result;   }
  main()
   {sqstack *optr;
     char s[80],c,y; int i=0;
     optr=(sqstack *)malloc(sizeof(sqstack));
     gets(s);
     initStack(optr); push(optr,'#');
     c=s[i];
     while(c!='#'||gettop(optr)!='#')
     {if(c!='+'&&c!='-'&&c!='*'&&c!='/'&&c!='('&&c!=')'&&c!='#')
        {printf("%c",c);c=s[++i];
        if(c=='/0') break;
        }
    else
       switch (precede(gettop(optr),c))
        {case '<':{push(optr,c);c=s[++i];break;}
         case '=':{pop(optr);c=s[++i];break; }
         case '>':{y=pop(optr);
                 printf("%c",y);
                 break;}}
       } printf("%c",'#');
}

P51 用C语言定义的顺序存储结构的队列如下:
# define MAXNUM <最大元素数>
typedef struct {
 Elemtype queue[MAXNUM];
 int front;  /*队头指示器*/
 int rear; /*队尾指示器*/
 } sqqueue;

P51【算法3.15  顺序队列的初始化】
int initQueue(sqqueue *q)
{/*创建一个空队列由指针q指出*/
  if ((q=(sqqueue*)malloc(sizeof(sqqueue)))= =NULL) return FALSE;
  q->front= -1;
  q->rear=-1;
return TRUE;
}

P52【算法3.16  顺序队列的入队列操作】
int append(sqqueue *q,Elemtype x)
{/*将元素x插入到队列q中,作为q的新队尾*/
  if(q->rear>=MAXNUM-1) return FALSE;   /*队列满*/
  q->rear++;
q->queue[q->rear]=x;
return TRUE;
}

P52【算法3.17  顺序队列的出队列操作】
Elemtype delete(sqqueue *q)
{/*若队列q不为空,则返回队头元素*/
Elemtype  x;
if(q->rear= =q->front) return NULL;     /*队列空*/
x=q->queue[++q->front];
return x;
}

P52【算法3.18  顺序队列的取头元素操作】
Elemtype getHead(sqqueue *q)
{/*若队列q不为空,则返回队头元素*/
  if(q->rear= =q->front) return NULL;    /*队列空*/
return (q->queue[s->front+1]);
}

P52【算法3.19  顺序队列的非空判断操作】
int Empty(sqqueue *q)
{/*队列q为空时,返回TRUE;否则返回FALSE*/
  if (q->rear= =q->front) return TRUE;
  return FALSE;
}

P53【算法3.20  顺序队列的求长度操作】
int length(sqqueue *q)
{/*返回队列q的元素个数*/
  return(q->rear-q->front);
}

P54用C语言定义循环队列结构如下:
typedef struct
{Elemtype queue[MAXNUM];
int front; /*队头指示器*/
int rear; /*队尾指示器*/
int s; /*队列标志位*/
}qqueue;

P54【算法3.21  循环队列的初始化】
int initQueue(qqueue *q)
{/*创建一个空队列由指针q指出*/
  if ((q=(qqueue*)malloc(sizeof(qqueue)))= =NULL) return FALSE;
  q->front= MAXNUM;
  q->rear=MAXNUM;
q->s=0;  /*置队列空*/
return TRUE;
}

P55【算法3.22  循环队列的入队列操作】
int append(qqueue *q,Elemtype x)
{/*将元素x插入到队列q中,作为q的新队尾*/
if (( q->s= =1)&&(q->front= =q->rear)) return FALSE;  /*队列满*/
  q->rear++;
  if (q->rear= =MAXNUM) q->rear=0;
  q->queue[q->rear]=x;
  q->s=1;       /*置队列非空*/
return TRUE;
}

P55【算法3.23  循环队列的出队列操作】
Elemtype delete(qqueue *q)
{/*若队列q不为空,则返回队头元素*/
Elemtype  x;
if (q->s= =0) retrun NULL;    /*队列为空*/
q->front++;
if (q->front= =MAXNUM) q->front=0;
x=q->queue[q->front];
if (q->front = =q->rear) q->s=0;   /*置队列空*/
return x; }

P56 用C语言定义链队列结构如下:
typedef struct Qnode
{Elemtype data;
struct Qnode *next;
}Qnodetype; /*定义队列的结点*/
typedef struct
{ Qnodetype *front;/*头指针*/
Qnodetype *rear; /*尾指针*/
}Lqueue;

P56【算法3.24  链队列的初始化】
int initLqueue(Lqueue *q)
{/*创建一个空链队列q*/
 if ((q->front=(Qnodetype*)malloc(sizeof(Qnodetype)))= =NULL) return FALSE;
 q->rear=q->front;
q->front->next=NULL;
 return TRUE;
}

P56【算法3.25  链队列的入队列操作】
int Lappend(Lqueue *q,Elemtype x)
{/*将元素x插入到链队列q中,作为q的新队尾*/
Qnodetype *p;
if ((p=(Qnodetype*)malloc(sizeof(Qnodetype)))= =NULL) return FALSE;
p->data=x;
p->next=NULL;   /*置新结点的指针为空*/
q->rear->next=p;   /*将链队列中最后一个结点的指针指向新结点*/
q->rear=p;    /*将队尾指向新结点*/
return TRUE;
}

P57【算法3.26  链队列的出队列操作】
Elemtype Ldelete(Lqueue *q)
{/*若链队列q不为空,则删除队头元素,返回其元素值*/
Elemtype  x;
Qnodetype *p;
if(q->front->next= =NULL) return NULL;   /*空队列*/
P=q->front->next;       /*取队头*/
q->front->next=p->next;      /*删除队头结点*/
x=p->data;
free(p);
return x;
}


第四章 串
P62 用字符数组存放字符串时,其结构用C语言定义如下:
#define MAXNUM <允许的最大的字符数>

typedef struct {
  char str[MAXNUM];
  int length; /*串长度*/
} stringtype; /* 串类型定义*/

P62 用链表存放字符串时,其结构用C语言定义如下:
typedef struct node{
char str;
struct node  *next;
} slstrtype;

P63 用块链存放字符串时,其结构用C语言定义如下:
typedef struct node{
char str[4];
struct node  *next;
} slstrtype;

P63 用堆存放字符串时,其结构用C语言定义如下:
typedef struct{
char *str;
int length;
} HSstrtype;

P65  C语言中用字符数组存储字符串时,结构定义如下:
#define MAXNUM  80
typedef struct {
  char str[MAXNUM];
  int length; /*串长度*/
} stringtype; /* 串类型定义*/

P65【算法4.1 在静态存储方式中求子串】
int substr(stringtype s1,stringtype * s2,int m,int n)
{int j,k;j=s1.length;
if(m<=0||m>j||n<0) {(*s2).str[0]='/0';(*s2).length=0;return FALSE;  } /*参数错误*/
k=strlen(&s1.str[m-1]) ;    /*求子串的长度*/
if (n>k) (*s2).length=k;
else (*s2).length=n;      /*置子串的串长*/
for(j=0;j<=(*s2).length;j++,m++) (*s2).str[j]=s1.str[m-1];
(*s2).str[j]='/0';      /*置结束标记*/
return TRUE;
}

P66 假设链表中每个结点仅存放一个字符,则单链表定义如下
typedet struct node{
char str;
struct node  *next;
} slstrtype;

P66【算法4.2 在链式存储方式中求子串】
int substr(slstrtype s1,slstrtype *s2,int m,int n)
{slstrtype *p,*q,*v;
 int length1,j;
 p=&s1;
 for(lenght1=0;p->next!=NULL;p=p->next) length1++;  /*求主串和串长*/
 if(m<=0||m>length1||n<0) {s2=NULL;return FALSE;}  /*参数错误*/
 p=s1.next;
 for(j=0;j<m;j++) p=p->next;      /*找到子串和起始位置*/
 s2=(slstrtype *)malloc(sizeof(slstrtype));    /*分配子串和第一个结点*/
 v=s2;q=v;
 for(j=0;j<n&&p->next!=NULL;j++)      /*建立子串*/
{ q->str=p->str;
p=p->next;
q=(slstrtype *)malloc(sizeof(slstrtype));
v->next=q;
v=q;
}
q->str='/0';q->next=NULL;       /*置子串和尾结点*/
return TRUE;
}

P67 堆存储结构用C语言定义为:
typedet struct{
char *str;
int length;
} HSstrtype;

P67【算法4.3 共享法求子串】
int substr(HSstrtype s1,HSstrtype *s2,int m,int n)
{ int j,k;
 j=s1.length;
 if(m<=0||m>j||n<0) {s2->length=0;return FALSE;}  /*参数错误*/
 k=strlen(s1.str+m);      /*主串第m个位置开始之后的串长*/
if (n>k) s2->length=k;
else s2->length=n;      /*置子串的串长*/
s2->str=s1.str+m;      /*置子串的串首地址
return TRUE;
}

P67【算法4.4 重新赋值法求子串】
int substr(HSstrtype s1,HSstrtype *s2,int m,int n)
{ int j,k;
 j=s1.length;
 if(m<=0||m>j||n<0) {s2->length=0;return FALSE;} /*参数错误*/
 k=strlen(s1.str+m);       /*主串第m个位置开始之后的串长*/
if (n>k) s2->length=k;
else s2->length=n;        /*置子串的串长*/
k=s2->length;
for(j=0;j<k;j++)
s2->str[j]=s1.str[m++];     /*复制字符*/
s2->str[j]='/0';       /*置结束符*/
return TRUE;
}

P68 例
main()
{int a,b,c;
scanf(〃%d,%d〃,&a,&b);
c=a+b;
printf("%d",c);
}


第五章 多维数组和广义表
P77 三元组表
#define  maxsize  100   /*定义非零元的最大数目*/
struct  node             /*定义一个三元组*/ 
 {          
int      i , j;            /*非零元行、列号*/
int      v;                /*非零元值*/
}; 
struct   sparmatrix          /*定义稀疏矩阵*/
{  
int rows,cols ;              /*稀疏矩阵行、列数*/
int  terms;                 /*稀疏矩阵非零元个数*/
node data [maxsize];         /*三元组表*/
};

P79 十字链表的数据类型描述如下:
struct  linknode
{ int    i, j;
struct  linknode  *cptr, *rptr;
union  vnext               /*定义一个共用体*/
{   int   v;                    /*表结点使用V域,表示非零元值*/
struct  linknode   next;             /*表头结点使用next域*/
}  k; }

P81 (1)按照A的列序进行转置
#define maxsize 100
struct node
{
 int i,j;          /*定义三元组的行、列号*/
 int v;           /*三元组的值*/
 };
 struct sparmatrix
 {
    int rows,cols;       /*稀疏矩阵的行、列数*/
    int terms;          /*稀疏矩阵的非零元个数*/
    struct node data[maxsize];    /*存放稀疏矩阵的三元组表*/
    };
void  transpose(struct sparmatrix a)
{    
struct sparmatrix b;          /*b为a的转置*/
int ano,bno=0,col,i;
b.rows=a.cols;  b.cols=a.rows;
b.terms=a.terms;
if   (b.terms>0)
{
for ( col=0;  col<a.cols; col++)        /*按列号扫描*/
  for( ano=0;ano<a.terms;ano++)      /*对三元组扫描*/
if  (a.data[ano].j==col)              /*进行转置*/
{  b.data[bno].j=a.data[ano].i;
b.data[bno].i=a.data[ano].j;
b.data[bno].v=a.data[ano].v;
bno++;
}
}
 for( i=0;i<a.terms;i++)      /*输出转置后的三元组结果*/
    printf("%5d%5d%5d/n",b.data[i].i,b.data[i].j,b.data[i].v);
 }
void main()
{
int i;
struct sparmatrix a;
 scanf("%d%d%d",&a.rows,&a.cols,&a.terms); /*输入稀疏矩阵的行、列数及非零元的个数*/
 for(  i=0;i<a.terms;i++)
   scanf("%d%d%d",&a.data[i].i,&a.data[i].j,&a.data[i].v);  /*输入转置前的稀疏矩阵的三元组*/
 for(i=0;i<a.terms;i++)
 printf("%5d%5d%5d/n",a.data[i].i,a.data[i].j,a.data[i].v);  /*输出转置前的三元组结果*/
 transpose( a);                                 /*调用转置算法*/
}


P83  M稀疏矩阵的转置矩阵N的三元组表
#define maxsize 100
struct node
{
 int i,j;
 int v;
 };
 struct sparmatrix
 {
    int rows,cols;
    int terms;
    struct node data[maxsize];
    };

void  fastrans(struct sparmatrix a)
{
struct sparmatrix b;
 int pot[maxsize],col,ano,bno,t,i;
b.rows=a.cols;  b.cols=a.rows;
b.terms=a.terms;
if(b.terms>0)
{
 for(col=0;col<=a.cols;col++)
               pot[col]=0;
  for( t=0;t<a.terms;t++)       /*求出每一列的非零元个数*/
{
  col=a.data[t].j;
    pot[col+1]=pot[col+1]+1;
 }
 pot[0]=0;
  for(col=1;col<a.cols;col++)     /*求出每一列的第一个非零元在转置后的位置*/
      pot[col]=pot[col-1]+pot[col];
  for( ano=0;ano<a.terms;ano++)     /*转置*/
  { col=a.data[ano].j;
    bno=pot[col];
  b.data[bno].j=a.data[ano].i;
b.data[bno].i=a.data[ano].j;
b.data[bno].v=a.data[ano].v;
pot[col]=pot[col]+1;
}
}
 for( i=0;i<a.terms;i++)
  printf("%d/t%d/t%d/n",b.data[i].i,b.data[i].j,b.data[i].v);   /*输出转置后的三元组*/
 }
void main()
{ struct sparmatrix a;
  int i;
 scanf("%d%d%d",&a.rows,&a.cols,&a.terms); /*输入稀疏矩阵的行、列数及非零元的个数*/
     for(  i=0;i<a.terms;i++)
     scanf("%d%d%d",&a.data[i].i,&a.data[i].j,&a.data[i].v);   /*输入转置前的三元组*/
     for(i=0;i<a.terms;i++)
     printf("%d/t%d/t%d/n",a.data[i].i,a.data[i].j,a.data[i].v);   /*输出转置前的三元组*/
     fastrans(a);                                       /*调用快速转置算法*/
}

P85第二步,生成表中结点。算法描述如下:
#include<stdio.h>
#define maxsize 100
struct linknode
{
 int i,j;
 struct linknode *cptr,*rptr;
union vnext
{ int v;
 struct linknode *next;} k;
};

struct linknode  *creatlindmat( )      /*建立十字链表*/
{   int   x,  m, n, t, s, i, j, k;
struct linknode   *p , *q, *cp[maxsize],*hm;
printf("请输入稀疏矩阵的行、列数及非零元个数/n");
scanf("%d%d%d",&m,&n,&t);
if (m>n)  s=m;  else  s=n;
hm=(struct linknode*)malloc(sizeof(struct linknode)) ;
hm->i=m; hm->j=n;
cp[0]=hm;
for (i=1; i<=s;i++)
{  p=(struct linknode*)malloc(sizeof(struct linknode)) ;
   p->i=0;  p->j=0;
p->rptr=p;  p->cptr=p;
cp[i]=p;
cp[i-1]->k.next=p;
}
cp[s]->k.next=hm;
for( x=1;x<=t;x++)
{    printf("请输入一个三元组(i,j,v)/n");
 scanf("%d%d%d",&i,&j,&k);        /*输入一个非零元的三元组*/
p=(struct linknode*)malloc(sizeof(struct linknode));  /*生成一个三元组的结点*/
p->i=i; p->j=j;  p->k.v=k;
/*以下是将p插入到第i行链表中 */
q=cp[i];
while ((q->rptr!=cp[i]) &&( q->rptr->j<j))
q=q->rptr;
p->rptr=q->rptr;
q->rptr=p;
/*以下是将P插入到第j列链表中*/
q=cp[j];
while((q->cptr!=cp[j]) &&( q->cptr->i<i))
q=q->cptr;
p->cptr=q->cptr;
q->cptr=p;
}
return hm;
}
void main()
{    struct linknode *p,*q;
    struct linknode  *hm;
hm=creatlindmat( );               /*生成十字链表*/
p=hm->k.next;
while(p->k.next!=hm)    /*输出十字链表*/
{ q=p->rptr;
   while(q->rptr!=p)
      { printf("%3d%3d%3d/t",q->i,q->j,q->k.v);
         q=q->rptr;
                        }
if(p!=q)
 printf("%3d%3d%3d",q->i,q->j,q->k.v);
   printf("/n");
   p=p->k.next;
}
 q=p->rptr;
   while(q->rptr!=p)
 { printf("%3d%3d%3d/t",q->i,q->j,q->k.v);
  q=q->rptr;
      }
 if(p!=q)
 printf("%3d%3d%3d",q->i,q->j,q->k.v);
  printf("/n");
}

 

P88  稀疏矩阵十字链表相加算法如下:
/*假设ha为A稀疏矩阵十字链表的头指针,hb为B稀疏矩阵十字链表的头指针*/
#include<stdio.h>
#define maxsize 100
struct linknode
{ int i,j;
 struct linknode *cptr,*rptr;
union vnext
{ int v;
 struct linknode *next;} k;
};

struct linknode  creatlindmat( )     /*建立十字链表*/
{   int   x,  m, n, t, s, i, j, k;
struct linknode   *p , *q, *cp[maxsize],*hm;
printf("请输入稀疏矩阵的行、列数及非零元个数/n");
scanf("%d%d%d",&m,&n,&t);
if (m>n)  s=m;  else  s=n;
hm=(struct linknode*)malloc(sizeof(struct linknode)) ;
hm->i=m; hm->j=n;
cp[0]=hm;
for (i=1; i<=s;i++)
{  p=(struct linknode*)malloc(sizeof(struct linknode)) ;
   p->i=0;  p->j=0;
p->rptr=p;  p->cptr=p;
cp[i]=p;
cp[i-1]->k.next=p;
}
cp[s]->k.next=hm;
for( x=1;x<=t;x++)
{    printf("请输入一个三元组(i,j,v)/n");
 scanf("%d%d%d",&i,&j,&k);
p=(struct linknode*)malloc(sizeof(struct linknode));
p->i=i; p->j=j;  p->k.v=k;
/*以下是将p插入到第i行链表中 */
q=cp[i];
while ((q->rptr!=cp[i]) &&( q->rptr->j<j))
q=q->rptr;
p->rptr=q->rptr;
q->rptr=p;
/*以下是将P插入到第j列链表中*/
q=cp[j];
while((q->cptr!=cp[j]) &&( q->cptr->i<i))
q=q->cptr;
p->cptr=q->cptr;
q->cptr=p;
}
return hm;
}
/*  ha和hb表示的两个稀疏矩阵相加,相加的结果放入ha中*/
struct linknode *matadd(struct linknode *ha, struct linknode *hb)
{  struct linknode  *pa, *pb, *qa, *ca,*cb,*p,*q;
  struct linknode  *hl[maxsize];
int    i , j, n;
if((ha->i!=hb->i)||(ha->j!=hb->j))
printf("矩阵不匹配,不能相加/n");
else
{   p=ha->k.next; n=ha->j;
for (i=1;i<=n; i++)
{  hl[i]=p;
p=p->k.next;
}
ca=ha->k.next; cb=hb->k.next;
while(ca->i==0)
{pa=ca->rptr;  pb=cb->rptr;
qa=ca;
while(pb->j!=0)
{   if((pa->j<pb->j)&&(pa->j!=0))
{    qa=pa;  pa=pa->rptr;}
else if ((pa->j>pb->j)||(pa->j==0))        /*插入一个结点*/
{  p=(struct linknode*)malloc(sizeof(struct linknode));
p->i=pb->i;  p->j=pb->j;
p->k.v=pb->k.v;
qa->rptr=p;  p->rptr=pa;
qa=p; pb=pb->rptr;
j=p->j; q=hl[j]->cptr;
while((q->i<p->i)&&(q->i!=0))
{  hl[j]=q;  q=hl[j]->cptr;}
hl[j]->cptr=p;  p->cptr=q;
hl[j]=p;
}
else
{pa->k.v=pa->k.v+pb->k.v;
if(pa->k.v==0)                /*删除一个结点*/
{ qa->rptr=pa->rptr;
j=pa->j;  q=hl[j]->cptr;
while (q->i<pa->i)
{hl[j]=q;  q=hl[j]->cptr;}
hl[j]->cptr=q->cptr;
pa=pa->rptr;   pb=pb->rptr;
free(q);
}
else
{  qa=pa; pa=pa->rptr;
pb=pb->rptr;
}
}
}
ca=ca->k.next;  cb=cb->k.next;
}
}
return ha;
}
void print(struct linknode *ha)    /*输出十字链表*/
{ struct linknode *p,*q;
      p=ha->k.next;
while(p->k.next!=ha)
{ q=p->rptr;
   while(q->rptr!=p)
  { printf("%3d%3d%3d/t",q->i,q->j,q->k.v);
         q=q->rptr;
  }
   if(p!=q)
   printf("%3d%3d%3d",q->i,q->j,q->k.v);
   printf("/n");
   p=p->k.next;
}
q=p->rptr;
   while(q->rptr!=p)
  { printf("%3d%3d%3d/t",q->i,q->j,q->k.v);
         q=q->rptr;
    }
   if(p!=q)
   printf("%3d%3d%3d",q->i,q->j,q->k.v);
   printf("/n");
}

void main()
{
struct linknode  *ha=NULL,*hb=NULL,*hc=NULL;
ha=creatlindmat( );     /*生成一个十字链表ha*/
hb=creatlindmat( );              /*生成另一个十字链表hb*/
printf("A:/n");                 /*输出十字链表ha*/
 print(ha);printf("/n");
printf("B:/n");             /*输出十字链表hb*/
print(hb);printf("/n");   
hc=matadd(ha,hb);              /*十字链表相加*/
printf("A+B:/n");     /*输出相加后的结果*/
print(hc);printf("/n");   
}

P94  数据类型描述如下:
#define elemtype char  
struct  node1
{  int atom;
  struct node1  *link;
union
 {
 struct node1  *slink;
elemtype  data;
}  ds;
}

P95  数据类型描述如下:
struct node2
{   elemtype data;
   struct node2  *link1,*link2;
}

P96  求广义表的深度depth(LS)
int depth(struct node1  *LS)
{
 int max=0,dep;
while(LS!=NULL)
{ if(LS->atom==0)   //有子表
     { dep=depth(LS->ds.slink);
        if(dep>max)   max=dep;
        }
        LS=LS->link;
}
return max+1;
}

P96  广义表的建立creat(LS)
void creat(struct node1 *LS)
{
           char ch;
           scanf("%c",&ch);
           if(ch=='#')
           LS=NULL;
           else if(ch=='(')
           {LS=(struct node*)malloc(sizeof(struct node));
            LS->atom=0;
           creat(LS->ds.slink);
           }
          else
           { LS=(struct node*)malloc(sizeof(struct node));
              LS->atom=1;
             LS->ds.data=ch;
           }
           scanf("%c",&ch);
           if(LS==NULL);
           else if(ch==',')
                      creat(LS->link);
           else if((ch==')')||(ch==';'))
                      LS->link=NULL;
}

P97  输出广义表print(LS)
void print(struct node1 *LS)
{
     if(LS->atom==0)
     {
          printf("(");
       if(LS->ds.slink==NULL)
                 printf("#");
       else
                    print(LS->ds.slink);
      }
     else
                    printf("%c ",LS->ds.data);
    if(LS->atom==0)
                    printf(")");
    if(LS->link!=NULL)
     {
                    printf(";");
                    print(LS->link);
     }
}

P98  该算法的时间复杂度为O(n)。整个完整程序如下:
#include<stdio.h>
#define elemtype char
struct node1
{ int atom;
struct node1  *link;
union
 {
 struct node1  *slink;
elemtype  data;
}  ds;
};

void creat(struct node1 LS)      /*建立广义表的单链表*/
{
           char ch;
           scanf("%c",&ch);
           if(ch=='#')
           LS=NULL;
           else if(ch=='(')
    {LS=(struct node1*)malloc(sizeof(struct node1));
            LS->atom=0;
    creat(LS->ds.slink);
           }
          else
    { LS=(struct node1*)malloc(sizeof(struct node1));
              LS->atom=1;
      LS->ds.data=ch;
           }
           scanf("%c",&ch);
           if(LS==NULL);
           else if(ch==',')
                      creat(LS->link);
           else if((ch==')')||(ch==';'))
                      LS->link=NULL;
}
void print(struct node1 LS)     /*输出广义单链表*/
{
     if(LS->atom==0)
     {
          printf("(");
       if(LS->ds.slink==NULL)
                 printf("#");
       else
      print(LS->ds.slink);
      }
     else
      printf("%c",LS->ds.data);
    if(LS->atom==0)
                    printf(")");
    if(LS->link!=NULL)
     {
                    printf(";");
                    print(LS->link);
     }
}
int depth(struct node1 LS)      /*求广义表的深度*/
{
 int max=0;
while(LS!=NULL)
{ if(LS->atom==0)
     { int dep=depth(LS->ds.slink);
        if(dep>max)   max=dep;
        }
        LS=LS->link;
}
return max+1;
}
main()
{ int dep;
  struct node1 *p=NULL;
  creat(p);            /*建立广义表的单链表*/
  print(p);             /*输出广义单链表*/
  dep=depth(p);       /*求广义表的深度*/
  printf("%d/n",dep);
  }


第六章 树
P109  二叉链表的结点类型定义如下:
typedef struct btnode
  { anytype data;
    struct btnode *Lch,*Rch;
   }tnodetype;

P109  三叉链表的结点类型定义如下:
typedef struct btnode3
  { anytype data;
    struct btnode *Lch,*Rch,*Parent ;
   }tnodetype3;

P112  C语言的先序遍历算法:
void preorder (tnodetype *t)
/*先序遍历二叉树算法,t为指向根结点的指针*/
{  if (t!=NULL)
      {printf("%d ",t->data);
       preorder(t->lch);
       preorder(t->rch);
        }
  }

P113  C语言的中序遍历算法:
void inorder(tnodetype *t)
/*中序遍历二叉树算法,t为指向根结点的指针*/
{
  if(t!=NULL)
  {inorder(t->lch);
   printf("%d ",t->data);
   inorder(t->rch);
  }
}

P113  C语言的后序遍历算法:
void postorder(tnodetype *t)
/*后序遍历二叉树算法,t为指向根结点的指针*/
{
  if(t!=NULL)
   { postorder(t->lch);
     postorder(t->rch);
     printf("%d ",t->data);
   }
}

P114  如果引入队列作为辅助存储工具,按层次遍历二叉树的算法可描述如下:
void levelorder(tnodetype *t)
/*按层次遍历二叉树算法,t为指向根结点的指针*/
{tnodetype q[20];        /*辅助队列*/
 front=0;
 rear=0;               /*置空队列*/
 if (t!=NULL)
   { rear++;
    q[rear]=t;          /*根结点入队*/
   }
while (front!=rear)
    { front++;
    t=q [front];
    printf ("%c/n",t->data);
    if (t->lch!=NULL)         /*t的左孩子不空,则入队*/
      { rear++;
       q [rear]=t->lch;
       }
    if (t->rch!=NULL)        /*t的右孩子不空,则入队*/
      { rear++;
       q [rear]=t->rch;
       }
   }
}

P115  以中序遍历的方法统计二叉树中的结点数和叶子结点数,算法描述为:
void inordercount (tnodetype *t)
/*中序遍历二叉树,统计树中的结点数和叶子结点数*/
{ if (t!=NULL)
   { inordercount (t->lch);           /*中序遍历左子树*/
    printf ("%c/n",t->data);          /*访问根结点*/
    countnode++;                  /*结点计数*/
    if ((t->lch==NULL)&&(t->rch==NULL))
      countleaf++;                 /*叶子结点计数*/
    inordercount (t->rch);            /*中序遍历右子树*/
    }
}

P115  可按如下方法计算一棵二叉树的深度:
void preorderdeep (tnodetype *t,int j)
/*先序遍历二叉树,并计算二叉树的深度*/
{ if (t!=NULL)
   { printf ("%c/n",t->data);        /*访问根结点*/
      j++;
      if (k<j)  k=j;
      preorderdeep (t->lch,j);       /*先序遍历左子树*/
      preorderdeep (t->rch,j);       /*先序遍历右子树*/
      }
 }

P117  线索二叉树的结点类型定义如下:
struct nodexs
{anytype data;
 struct nodexs *lch, *rch;
int ltag,rtag;   /*左、右标志域*/
}

P117  中序次序线索化算法
void inorderxs (struct nodexs *t)
/*中序遍历t所指向的二叉树,并为结点建立线索*/
 { if (t!=NULL)
     { inorderxs (t->lch);
       printf ("%c/n",t->data);
       if (t->lch!=NULL)
          t->ltag=0;
    else { t->ltag=1;
         t->lch=pr;
        }     /*建立t所指向结点的左线索,令其指向前驱结点pr*/
    if (pr!=NULL)
      { if (pr->rch!=NULL)
         pr->rtag=0;
       else { pr->rtag=1;
            pr->rch=p;
            }
         }  /*建立pr所指向结点的右线索,令其指向后继结点p*/
    pr=p;
    inorderxs (t->rch);
  }
}

P118  在中根线索树上检索某结点的前驱结点的算法描述如下:
struct nodexs * inpre (struct nodexs *q)
/*在中根线索树上检索q所指向的结点的前驱结点*/
  { if (q->ltag==1)
     p=q->lch;
   else { r=q->lch;
        while (r->rtag!=1)
             r=r->rch;
        p=r;
       }
   return (p);
}

P119  在中根线索树上检索某结点的后继结点的算法描述如下:
struct nodexs * insucc (struct nodexs *q)
/*在中根线索树上检索q所指向的结点的后继结点*/
  { if (q->rtag==1)
     p=q->rch;
   else { r=q->rch;
        while (r->ltag!=1)
             r=r->lch;
        p=r;
       }
   return (p);
}

P120  算法程序用C语言描述如下:
void insertbst(t,s)
/*将指针s所指的结点插入到以t为根指针的二叉树中*/
{ if (t==NULL)
  t=s;        /*若t所指为空树,s所指结点为根*/
  else if (s->data < t->data)
insertbst(t->lch,s);    /*s结点插入到t的左子树上去*/
else
insertbst(t->rch,s);    /*s结点插入到t的右子树上去*/
}

P121  二叉排序树结点删除算法的C语言描述如下:
void delnode(bt,f,p)
/*bt为一棵二叉排序树的根指针,p指向被删除结点,f指向其双亲*/
/*当p=bt时f为NULL*/
{ fag=0;        /*fag=0时需修改f指针信息,fag=1时不需修改*/
  if (p->lch==NULL)
      s=p->rch;       /*被删除结点为叶子或其左子树为空*/
  else if (p->rch==NULL)
           s=p->lch;
  else { q=p;       /*被删除结点的左、右子树均非空*/
         s=p->lch;
         while (s->rch!=NULL)
               { q=s;
                 s=s->rch;
                }      /*寻找s结点*/
         if (q=p)
             q->lch=s->lch;
         else q->rch=s->lch;
         p->data=s->data;     /*s所指向的结点代替被删除结点*/
         DISPOSE(s);
         Fag=1;
        }
  if (fag=0)   /*需要修改双亲指针*/
     { if (f=NULL) 
          bt=s;       /*被删除结点为根结点*/
      else if (f->lch=p)
               f->lch=s;
           else f->rch=s;
      DISPOSE(p);      /*释放被删除结点*/
     }
}


第七章 图
P134  用邻接矩阵表示法表示图,除了存储用于表示顶点间相邻关系的邻接矩阵外,通常还需要用一个顺序表来存储顶点信息。其形式说明如下:
# define n 6        /*图的顶点数*/
# define e 8        /*图的边(弧)数*/
typedef char vextype;     /*顶点的数据类型*/
typedef float adjtype;     /*权值类型*/
typedef struct
{vextype vexs[n];
 adjtype arcs[n][n];
}graph;

P135  建立一个无向网络的算法。
CREATGRAPH(ga)            /*建立无向网络*/
Graph * ga;
{
int i,j,k;
float w;
for(i=0;i<n;i++ )
ga ->vexs[i]=getchar();   /*读入顶点信息,建立顶点表*/
for(i=0;i<n;i++ )
for(j=0;j<n;j++)
ga ->arcs[i][j]=0;        /*邻接矩阵初始化*/
for(k=0;k<e;k++)          /*读入e条边*/
(scanf("%d%d%f",&I,&j,&w);  /*读入边(vi,vj)上的权w */
ga ->arcs[i][j]=w;
ga - >arcs[j][i]=w;
}
}                           /*CREATGRAPH*/

P136  邻接表的形式说明及其建立算法:
typedef struct node
{int adjvex;           /*邻接点域*/
struct node * next;     /*链域*/
}edgenode;     /*边表结点*/
typedef struct
{vextype vertex;    /*顶点信息*/
edgenode link;      /*边表头指针*/
}vexnode;          /*顶点表结点*/
vexnode ga[n];

CREATADJLIST(ga)          /*建立无向图的邻接表*/
Vexnode ga[ ];
{int i,j,k;
edgenode * s;
for(i=o;i<n;i++=    /*读入顶点信息*/
(ga[i].vertex=getchar();
ga[i].1ink=NULL;    /*边表头指针初始化*/
}
for(k=0;k<e;k++=    /*建立边表*/
{scanf("%d%d",&i,&j);   /*读入边(vi , vj)的顶点对序号*/
s=malloc(sizeof(edgenode));  /*生成邻接点序号为j的表结点*s  */
s-> adjvex=j;
s- - >next:=ga[i].Link;
ga[i].1ink=s;     /*将*s插入顶点vi的边表头部*/
s=malloc(size0f(edgende));  /*生成邻接点序号为i的边表结点*s */
s ->adjvex=i;
s ->next=ga[j].1ink;
ga[j].1ink=s;     /*将*s插入顶点vj的边表头部*/
}
}       /* CREATADJLIST */

P139  分别以邻接矩阵和邻接表作为图的存储结构给出具体算法,算法中g、g1和visited为全程量,visited的各分量初始值均为FALSE。
int visited[n]       /*定义布尔向量visitd为全程量*/
Graph g;            /*图g为全程量*/

DFS(i)               /*从Vi+1出发深度优先搜索图g,g用邻接矩阵表示*/
int i;
{ int j;
  printf("node:%c\n" , g.vexs[i]);  /*访问出发点vi+1 */
  Visited[i]=TRUE;    /*标记vi+l已访问过*/
  for (j=0;j<n;j++)     /*依次搜索vi+1的邻接点*/
    if((g.arcs[i][j]==1)  &&(! visited[j]))
       DFS(j);  /*若Vi+l的邻接点vj+l未曾访问过,则从vj+l出发进行深度优先搜索*/
}        /*DFS*/
vexnode gl[n]   /*邻接表全程量*/
   
DFSL(i)     /*从vi+l出发深度优先搜索图g1,g1用邻接表表示*/
int i;
{ int j;
  edgenode * p;
  printf("node:%C/n" ,g1[i].vertex);
  vistited[i]=TRUE;
  p=g1[i].1ink;    /*取vi+1的边表头指针*/
  while(p !=NULL)    /*依次搜索vi+l的邻接点*/
  {
   if(! Vistited[p ->adjvex])
   DFSL(p - >adjvex);  /*从vi+1的未曾访问过的邻接点出发进行深度优先搜索*/
   p=p - >next;    /*找vi+l的下一个邻接点*/
  }
}      /* DFSL */

P142  以邻接矩阵和邻接表作为图的存储结构,分别给出宽度优先搜索算法。
BFS(k) /*从vk+l出发宽度优先搜索图g,g用邻接矩阵表示,visited为访问标志向量*/
int k;
{ int i,j;
  SETNULL(Q);      /*置空队Q */
  printf("%c\n",g.vexs[k]);    /*访问出发点vk+l*x/
  visited[k]=TRUE;     /*标记vk+l已访问过*/
  ENQUEUE(Q,K);      /*已访问过的顶点(序号)入队列*/
  While(!EMPTY(Q))     /*队非空时执行*/
  {i=DEQUEUE(Q);     /*队头元素序号出队列*/
     for(j=0;j<n;j++)
       if((g.arcs[i][j]==1)&&(! visited[j]))
         {printf("%c\n" , g.vexs[j]);  /*访问vi+l的未曾访问的邻接点vj+l */
          visited[j]=TRUE;
          ENQUEUE(Q,j);    /*访问过的顶点入队*/
    }
 }
}         /* BFS */
BFSL(k)   /*从vk+l出发宽度优先搜索图g1,g1用邻接表表示*/
int k
{ int i;
  edgenode * p;
  SETNULL(Q);
  printf("%c\n" , g1[k].vertex);
  visited[k]=TRUE;
  ENQUEUE(Q,k);
  while(! EMPTY(Q));
  { i=DEQUEUE(Q);
    p=g1[i].1ink       /*取vi+l的边表头指针*/
    while(p !=NULL)     /*依次搜索vi+l的邻接点*/
    { if( ! visited[p - >adjvex])   /*访问vi+l的未访问的邻接点*/
      { printf{"%c\n" , g1[p - >adjvex].vertex};
        visited[p - >adjvex]=TRUE;
        ENQUEUE(Q,p - >adjvex);  /*访问过的顶点入队*/
       }
       p=p - >next;    /*找vi+l的下一个邻接点*/
     }
    }
  }        /*BFSL*/

P148  在对算法Prim求精之前,先确定有关的存储结构如下:
typdef struct
{Int fromvex,endvex;  /*边的起点和终点*/
float length;    /*边的权值*/
} edge;

float dist[n][n];     /*连通网络的带权邻接矩阵*/
edgeT[n-1];    /*生成树*/

P149  抽象语句(1)可求精为:
for(j=1;j<n;j++)     /*对n-1个蓝点构造候选紫边集*/
{T[j-1].fromvex=1};    /*紫边的起点为红点*/
T[j-1].endvex=j+1;     /*紫边的终点为蓝点*/
T[j-1].1ength=dist[0][j];    /*紫边长度*/
}

P149  抽象语句(3)所求的第k条最短紫边可求精为:
min=max;      /*znax大于任何边上的权值*/
for (j=k;j<n-1;j++)    /*扫描当前候选紫边集T[k]到T[n-2],找最短紫边*/
if(T[j].1ength<min)
{min=T[j].1ength;m=j;    /*记录当前最短紫边的位置*/
}

P149  抽象语句(4)的求精:
e=T[m];T[m]=T[k];T[k]=e,  /* T[k]和T[m]交换*/
v=T[kl.Endvex];    /* v是刚被涂红色的顶点*/

P149  抽象语句(5)可求精为:
for(j=k+1;j<n-1;j++)    /*调整候选紫边集T[k+1]到T[n-2]*/
{d=dist[v-1][T[j].endvex-1];   /*新紫边的长度*/
  if(d<T[j].1ength)     /*新紫边的长度小于原最短紫边*/
    {T[j].1ength=d;
     T[j].fromvex=v;    /*新紫边取代原最短紫边*/
    }
}

P150  完整的算法:
PRIM()  /*从第一个顶点出发构造连通网络dist的最小生成树,结果放在T中*/
{int j , k , m , v , min , max=l0000;
  float d;
  edge e;
  for(j=1;j<n;j++)     /*构造初始候选紫边集*/
  {T[j-1].formvex=1;    /*顶点1是第一个加入树中的红点*/
   T[j-1].endvex=j+1;
   T[j-1].length=dist[o][j];
  }
for(k=0;k<n-1;k++)     /*求第k条边*/
  {min=max;
  for(j=k;j<n-1;j++)        /*在候选紫边集中找最短紫边*/
   if(T[j].1ength<min)
     {min=T[j].1ength;
      m=j;
     }       /*T[m]是当前最短紫边*/
  }
    e=T[m];T[m]=T[k];T[k]=e;  /*T[k]和T[m]交换后,T[k]是第k条红色树边*/
    v=T[k].endvex ;         /* v是新红点*/
    for(j=k+1;j<n-1;j++)    /*调整候选紫边集*/
      {d=dist[v-1][T[j].endvex-1];
       if(d<T[j].1ength);
       {T[j].1ength=d;
        T[j].fromvex=v;
       }
      }
}        /* PRIM */

P151  Kruskl算法的粗略描述:
T=(V,φ);
While(T中所含边数<n-1)
{从E中选取当前最短边(u,v);
  从E中删去边(u,v);
  if((u,v)并入T之后不产生回路,将边(u,v)并入T中;
}

P153  迪杰斯特拉算法实现。算法描述如下:
#define max 32767          /*max代表一个很大的数*/
void dijkstra (float cost[][n],int v)
/*求源点v到其余顶点的最短路径及其长度*/
 { v1=v-1;
  for (i=0;i<n;i++)
    { dist[i]=cost[v1][i];      /*初始化dist*/
      if (dist[i]<max)
        pre[i]=v;
      else pre[i]=0;
     }
  pre[v1]=0;
  for (i=0;i<n;i++)
     s[i]=0;           /*s数组初始化为空*/
  s[v1]=1;           /*将源点v归入s集合*/
  for (i=0;i<n;i++)
   { min=max;
     for (j=0;j<n;j++)
        if (!s[j] && (dist[j]<min))
          { min=dist[j];
           k=j;
           }           /*选择dist值最小的顶点k+1*/
     s[k]=1;            /*将顶点k+1归入s集合中*/
     for (j=0;j<n;j++)
        if (!s[j]&&(dist[j]>dist[k]+cost[k][j]))
          { dist[j]=dist[k]+cost[k][j];     /*修改 V-S集合中各顶点的dist值*/
            pre[j]=k+1;           /*k+1顶点是j+1顶点的前驱*/
            }
   }          /*所有顶点均已加入到S集合中*/
for (j=0;j<n;j++)         /*打印结果*/
   { printf("%f/n%d",dist[j],j+1;);
    p=pre[j];
    while (p!=0)
         { printf("%d",p);
          p=pre[p-1];
           }
    }
}

P155  弗洛伊德算法可以描述为:
A(0)[i][j]=cost[i][j];                //cost为图的邻接矩阵
A(k)[i][j]=min{A(k-1) [i][j],A(k-1) [i][k]+A(k-1) [k][j]}
其中 k=1,2,...,n

P155  弗洛伊德算法实现。算法描述如下:
int path[n][n];         /*路径矩阵*/
void floyd (float A[][n],cost[][n])
 { for (i=0;i<n;i++)          /*设置A和path的初值*/
      for (j=0;j<n;j++)
         { if (cost[i][j]<max)
             path[i][j]=j;
          else { path[i][j]=0;
               A[i][j]=cost[i][j];
               }
          }
      for (k=0;k<n;k++)
    /*做n次迭代,每次均试图将顶点k扩充到当前求得的从i到j的最短路径上*/
      for (i=0;i<n;i++)
        for (j=0;j<n;j++)
          if (A[i][j]>(A[i][k]+A[k][j]))    /*修改长度和路径*/
            { A[i][j]=A[i][k]+A[k][j];
              path[i][j]=path[i][k];
             }
      for (i=0;i<n;i++)   /*输出所有顶点对i,j之间的最短路径长度及路径*/
      for (j=0;j<n;j++)
         { printf ("%f",A[i][j]);     /*输出最短路径的长度*/
      next=path[i][j];       /*next为起点i的后继顶点*/
           if (next==0)            /*i无后继表示最短路径不存在*/
             printf ("%d to %d no path./n",i+1,j+1);
           else { printf ("%d",i+1);    /*最短路径存在*/
                while (next!=j+1)   /*打印后继顶点,然后寻找下一个后继顶点*/
                    { printf ("%d",next);
                      next =path[next-1][j];
                      } 
                 printf ("%d/n",j+1);
               }
           }
     }


第八章 查找
P163  具体实现图8-1框图的程序段如下:
Void seqsrch(struct node r[],int n,int k)
{ int i=1;
  r[n+1].key=k;   /*设置边界*/
  while (r[i].key!=k)
           i=i+1;
  if (i<=n)
     printf("%3d,it is r[%2d]",k,i);
  else printf("%3d not found",k );
}


P164  设表的长度为n,表的被查找部分的头为low,尾为high,初始时,low=1,high=n,k为关键字的值。具体算法如下:
Void binsrch(struct node r[ ],int n,int k)
{ int mid,low,high,find;
  low=1; high=n;find=0;     /*置区间初值*/
  while ((low<=high) && (!find))
  { mid=(low+high)/2;     /*求中点*/
     if (k= = r[mid].key)
        find=1;      /*已查到*/
    else if(k>r[mid].key )
              low=mid+1;    /*在后半区间查找*/
           else high=mid-1;    /*在前半区间查找*/
   }
if (find)
   return (mid);      /*查找成功,返回找到元素的位置*/
else return (0);      /*查找不成功,返回0标记*/
}

P170  下面是线性探测法的算法,请注意,算法中设立了一个查找的边界值i,当顺序探测已超过表长,则要翻转到表首继续查找,直到查到i位置才是真正的查完全表。为编程方便,令i=j-1。
Define m 100;        /*哈希表的长度*/
Struct hash
{int key;
 }HT[m];
Void linehash(struct hash HT[ ],int k,int p)
{j=k%p;i=j-1;
 while ((HT[j].key!=NULL)&&(HT[j].key!=k)&&(j!=i))
 j=(j+1)%m;         /*解决冲突*/
 if (HT[j].key==k)
     printf("succ!%d,%d/n",k,j);
 else if (j==i)
        printf("overflow!/n");     /*溢出*/
      else HT[j].key=k;       /*插入k*/
}

P171  链地址散列表的具体算法描述如下:
Define m 100;     /*表长*/
Struct node
{int key;
struct node * next;
}HT[m];
Void linkhash(struct node HT[ ],int k,int p)
{struct node * p,* r,* s;
 j=k%p;
if(HT[j].key==0)
   {HT[j].key=k;
    HT[j].next=NULL;
   }
else if(HT[j].key==k)
        printf("succ!%d,%d/n",j,k);
     else {q=HT[j].next;
           while(q!=NULL)&&(q->key!=k)
                 {r=q;
                 q=q->next;
                 }
           if(q==NULL)
              {s=(struct node *)malloc(sizeof(struct node));
               s->key=k;
               s->next=NULL;
               r->next=s;
               }
            else printf("succ!%d,%d/n",j,k);
}


第九章 排序
P175  线性插入排序
void insertsort(struct node r[ n+1],int n)
/* r[n+1]为一维数组,其中r[0]为监视哨,r[1]到r[n]为待排序的n个记录,排序好的记录仍放在r中*/
{ for(i=2;i<=n;i++)     /*共进行n-1趟*/
     { r[0]=r[i];      /*r[0]为监视哨,也可做下边循环结束标志*/
       j=i-1;
       while(r[j].key>r[0].key)
             { r[j+1]=r[j];
               j--;
              }
       r[j+1]=r[0];
      }
 } 

P176  折半插入排序
void binarysort(struct node r[ n+1],int n)
/*按关键字递增的次序对记录r[1],r[2],......,r[n]进行折半插入排序 */
{ for(i=2;i<=n;i++)
     { r[0]=r[i];
       l=1;
       h=i-1;
       while(l<=h)
            { mid=(l+h)/2;
              if(r[0].key<r[mid].key)
                h=mid-1;
              else l=mid+1;
             }
       for(j=i-1;j>=l;j--)
           r[j+1]=r[j];
       r[l]=r[0];
       }
}

P178  希尔排序
rectype R[n+d1];                /* R[d1-1]为d1个监视哨*/
int d[t];                       /* d[0]到d[t-1]为增量序列*/
SHELLSORT(R,d)
Rectype R[ ];
int d[ ];
{int i,j,k,h;
 rectype temp;
 int maxint=32767;               /*机器中最大整数*/
 for (i=0;i<d[0];i++)
   R[i].key=-maxint;              /*设置哨兵*/
   K=0;
   Do{
       H=d[k];                  /*取本趟增量*/
       For(i=h+di;i<n+d1;i++)   /*R[h+d1]到R[n+d1-1]插入当前有序区*/
         {temp=R[i]};           /*保存待插入记录R[i]*/
           j=i-h;
            while(temp.key<R[j].key)    /*查找正确的插入位置*/
            {R[j+h]=R[j]};           /*后移记录*/
             j=j-h;                  /*得到前一记录位置*/
             }
             R[j+h]=temp;           /*插入R[i]*/
            }                        /*本趟排序完成*/
           k++;
         } while (h!=1);             /*增量为1排序后终止算法*/
       }                             /*SHELLSORT*/

P180  选择排序算法如下:
void selectsort(struct node r[n+1],int n)
/*对记录数组r[1]至r[n]进行选择排序*/
{ for(i=1;i<n;i++)
    { min=i;
     for(j=i+1;j<=n;j++)     /*选择最小元*/
        if (r[j].key<r[min].key)
          min=j;
     if(min!=i)
      { temp=r[min];
       r[min]=r[i];
       r[i]=temp;
       }
     }
}

P183  把左、右子树都是堆的顺序二叉树调整为一个堆,其算法描述如下:
void adjust(struct node r[m+1],int m)
   /* 将文件(r[1],r[2],...,r[m])解释为一棵顺序二叉树,将其中以r[i]为根结点的二叉树调整
      为一个堆,设以r[i]为根的二叉树的左,右子树已是堆,1≤i≤1[m/2]  */
{ x=r[i];j=2*i;         /*求出r[i]的左孩子r[2*i],即r[j] */
     while (j<=m)   /*有左孩子*/
         { if ((j<m) &&(r[j].key<r[j+1].key))     /*比较左、右孩子*/
             j=j+1; /*左孩子<右孩子*/
          if (x.key<r[j].key)      /*比较根结点和它的大孩子*/
             { r[i]=r[j];      /*大孩子上移到它的双亲位置*/
              i=j;       /*今 r[j]为根结点*/
              j=2*i;       /*求出左孩子*/
               }
          else  j=m+1      /*根不小于它的任一孩子时,强迫退出while循环*/
          }
r[i]=x;              /*将存放在x中的根结点放到r[i]中*/
 }

P183  堆排序算法如下:
void heapsort (struct node r[n+1],int m)
/*对记录数组r[1]至r[n]进行堆排序*/
{ for(i=n/2;i>=1;i--)
    adjust(r,i,n);       /*建立初始堆*/
  for(j=n;j>=2;j--)
    { x=r[1];  r[1]=r[j];        /*交换根结点和堆的最后一个结点*/
     r[j]=x;
     Adjust (r,1,j-1)       /*将r [1]至r[j-1]调整为堆*/
     }
}

P185  一次划分及其排序的算法。
int partition(r,1,h)      /*返回划分后被定的基准记录的位置*/
rectype R[ ];       /*对无序区R[1]到R[h]做划分*/
int 1,h;
{int i,j;
   rectype temp;
   i=1;j=h temp=R[i];      /*初始化,temp为基准*/
   Do{
       While((R[j].key>=temp.key)  && (i<j))
     j--;     /*从右向左扫描,查找第1个关键字小于temp.key的记录*/
    if(i<j) R[i++]=R[j];    /*交换R[i]和R[j]*/
  while((R[i].key<=temp.key) && (i<j))
     i++;    /*从左向右扫描,查找第1个关键字大于temp.key的记录*/
    if(i<j) R[j--]=R[i];     /*交换R[i]和R[j]*/
  }  
quicksort(R,s1,t1)     /*对R[s1]到R[t1]*/
rectype R[ ];
int s1,t1;
{int i;
  if (s1<t1)          /* 只有一个记录或无记录须排序*/
   {i= partition (R,s1,t1);    /*对R[s1]到R[t1]做划分*/
    quicksort (R,s1,i-1);    /*递归处理左区间*/
    quicksort (R,i+1,t1);    /*递归处理右区间*/
   }
}

P188  归并排序
MERGE(R,R1,low,mid,high)
rectype R[ ],R1[ ];
int low,mid,high;
{int i,j,k;
i=low;j=mid+1;k=low;
while((i<=mid)&&(i<=high))
if(R[i].key<=R[j].key)
R1[k++]=R1[i++];
else R1[k++]=R1[j++];
while (i<=mid) R1[k++]=R1[i++];
while (i<=high) R1[k++]=R1[j++];
}

P189  这两种特殊情况进行特殊处理。具体算法如下:
MERGEPASS(R,R1,length)
rectype R[],R1[];
int length;
{int i,j;
i=0;
while(i+2*length-1<n);
{MERGEPASS(R,R1,i+length-1,i+2*length-1);
i=i+2*length}
if(i+2*length-1<n-1)
MERGE(R,R1,i,i+length-1,n-1);
else
for(j=i;j<n;j++) R1[j],R[j];
}

P190  二路归并算法如下:
MERGESORT(R)
rectype R[ ];
int length;
{int length;
length=1;
while(length<n);
{MERGEPASS(R,R1,length);
length=2*length;
MERGEPASS(R1,R,length);
length=2*length;
}
}