Fork me on GitHub

常用数据结构代码示例

一、线性表

  1、线性表顺序存储

  1 #include "stdio.h"    
  2 
  3 #include "stdlib.h"   
  4 #include "io.h"  
  5 #include "math.h"  
  6 #include "time.h"
  7 
  8 #define OK 1
  9 #define ERROR 0
 10 #define TRUE 1
 11 #define FALSE 0
 12 
 13 #define MAXSIZE 20 /* 存储空间初始分配量 */
 14 
 15 typedef int Status;          /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
 16 typedef int ElemType;        /* ElemType类型根据实际情况而定,这里假设为int */
 17 
 18 
 19 Status visit(ElemType c)
 20 {
 21     printf("%d ",c);
 22     return OK;
 23 }
 24 
 25 typedef struct
 26 {
 27     ElemType data[MAXSIZE];        /* 数组,存储数据元素 */
 28     int length;                                /* 线性表当前长度 */
 29 }SqList;
 30 
 31 /* 初始化顺序线性表 */
 32 Status InitList(SqList *L) 
 33 { 
 34     L->length=0;
 35     return OK;
 36 }
 37 
 38 /* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
 39 Status ListEmpty(SqList L)
 40 { 
 41     if(L.length==0)
 42         return TRUE;
 43     else
 44         return FALSE;
 45 }
 46 
 47 /* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
 48 Status ClearList(SqList *L)
 49 { 
 50     L->length=0;
 51     return OK;
 52 }
 53 
 54 /* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
 55 int ListLength(SqList L)
 56 {
 57     return L.length;
 58 }
 59 
 60 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
 61 /* 操作结果:用e返回L中第i个数据元素的值,注意i是指位置,第1个位置的数组是从0开始 */
 62 Status GetElem(SqList L,int i,ElemType *e)
 63 {
 64     if(L.length==0 || i<1 || i>L.length)
 65             return ERROR;
 66     *e=L.data[i-1];
 67 
 68     return OK;
 69 }
 70 
 71 /* 初始条件:顺序线性表L已存在 */
 72 /* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
 73 /* 若这样的数据元素不存在,则返回值为0 */
 74 int LocateElem(SqList L,ElemType e)
 75 {
 76     int i;
 77     if (L.length==0)
 78             return 0;
 79     for(i=0;i<L.length;i++)
 80     {
 81             if (L.data[i]==e)
 82                     break;
 83     }
 84     if(i>=L.length)
 85             return 0;
 86 
 87     return i+1;
 88 }
 89 
 90 
 91 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
 92 /* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
 93 Status ListInsert(SqList *L,int i,ElemType e)
 94 { 
 95     int k;
 96     if (L->length==MAXSIZE)  /* 顺序线性表已经满 */
 97         return ERROR;
 98     if (i<1 || i>L->length+1)/* 当i比第一位置小或者比最后一位置后一位置还要大时 */
 99         return ERROR;
100 
101     if (i<=L->length)        /* 若插入数据位置不在表尾 */
102     {
103         for(k=L->length-1;k>=i-1;k--)  /* 将要插入位置之后的数据元素向后移动一位 */
104             L->data[k+1]=L->data[k];
105     }
106     L->data[i-1]=e;          /* 将新元素插入 */
107     L->length++;
108 
109     return OK;
110 }
111 
112 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
113 /* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
114 Status ListDelete(SqList *L,int i,ElemType *e) 
115 { 
116     int k;
117     if (L->length==0)               /* 线性表为空 */
118         return ERROR;
119     if (i<1 || i>L->length)         /* 删除位置不正确 */
120         return ERROR;
121     *e=L->data[i-1];
122     if (i<L->length)                /* 如果删除不是最后位置 */
123     {
124         for(k=i;k<L->length;k++)/* 将删除位置后继元素前移 */
125             L->data[k-1]=L->data[k];
126     }
127     L->length--;
128     return OK;
129 }
130 
131 /* 初始条件:顺序线性表L已存在 */
132 /* 操作结果:依次对L的每个数据元素输出 */
133 Status ListTraverse(SqList L)
134 {
135     int i;
136     for(i=0;i<L.length;i++)
137             visit(L.data[i]);
138     printf("\n");
139     return OK;
140 }
141 
142 void unionL(SqList *La,SqList Lb)
143 {
144     int La_len,Lb_len,i;
145     ElemType e;
146     La_len=ListLength(*La);
147     Lb_len=ListLength(Lb);
148     for (i=1;i<=Lb_len;i++)
149     {
150         GetElem(Lb,i,&e);
151         if (!LocateElem(*La,e))
152             ListInsert(La,++La_len,e);
153     }
154 }
155 
156 int main()
157 {
158         
159     SqList L;
160     SqList Lb;
161     
162     ElemType e;
163     Status i;
164     int j,k;
165     i=InitList(&L);
166     printf("初始化L后:L.length=%d\n",L.length);
167     for(j=1;j<=5;j++)
168             i=ListInsert(&L,1,j);
169     printf("在L的表头依次插入1~5后:L.data=");
170     ListTraverse(L); 
171 
172     printf("L.length=%d \n",L.length);
173     i=ListEmpty(L);
174     printf("L是否空:i=%d(1:是 0:否)\n",i);
175 
176     i=ClearList(&L);
177     printf("清空L后:L.length=%d\n",L.length);
178     i=ListEmpty(L);
179     printf("L是否空:i=%d(1:是 0:否)\n",i);
180 
181     for(j=1;j<=10;j++)
182             ListInsert(&L,j,j);
183     printf("在L的表尾依次插入1~10后:L.data=");
184     ListTraverse(L); 
185 
186     printf("L.length=%d \n",L.length);
187 
188     ListInsert(&L,1,0);
189     printf("在L的表头插入0后:L.data=");
190     ListTraverse(L); 
191     printf("L.length=%d \n",L.length);
192 
193     GetElem(L,5,&e);
194     printf("第5个元素的值为:%d\n",e);
195     for(j=3;j<=4;j++)
196     {
197             k=LocateElem(L,j);
198             if(k)
199                     printf("第%d个元素的值为%d\n",k,j);
200             else
201                     printf("没有值为%d的元素\n",j);
202     }
203     
204 
205     k=ListLength(L); /* k为表长 */
206     for(j=k+1;j>=k;j--)
207     {
208             i=ListDelete(&L,j,&e); /* 删除第j个数据 */
209             if(i==ERROR)
210                     printf("删除第%d个数据失败\n",j);
211             else
212                     printf("删除第%d个的元素值为:%d\n",j,e);
213     }
214     printf("依次输出L的元素:");
215     ListTraverse(L); 
216 
217     j=5;
218     ListDelete(&L,j,&e); /* 删除第5个数据 */
219     printf("删除第%d个的元素值为:%d\n",j,e);
220 
221     printf("依次输出L的元素:");
222     ListTraverse(L); 
223 
224     //构造一个有10个数的Lb
225     i=InitList(&Lb);
226     for(j=6;j<=15;j++)
227             i=ListInsert(&Lb,1,j);
228 
229     unionL(&L,Lb);
230 
231     printf("依次输出合并了Lb的L的元素:");
232     ListTraverse(L); 
233 
234     return 0;
235 }
List.c

  2、线性表链式存储

  1 #include "stdio.h"    
  2 #include "string.h"
  3 #include "ctype.h"      
  4 #include "stdlib.h"   
  5 #include "io.h"  
  6 #include "math.h"  
  7 #include "time.h"
  8 
  9 #define OK 1
 10 #define ERROR 0
 11 #define TRUE 1
 12 #define FALSE 0
 13 
 14 #define MAXSIZE 20 /* 存储空间初始分配量 */
 15 
 16 typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
 17 typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int */
 18 
 19 
 20 Status visit(ElemType c)
 21 {
 22     printf("%d ",c);
 23     return OK;
 24 }
 25 
 26 typedef struct Node
 27 {
 28     ElemType data;
 29     struct Node *next;
 30 }Node;
 31 typedef struct Node *LinkList; /* 定义LinkList */
 32 
 33 /* 初始化顺序线性表 */
 34 Status InitList(LinkList *L) 
 35 { 
 36     *L=(LinkList)malloc(sizeof(Node)); /* 产生头结点,并使L指向此头结点 */
 37     if(!(*L)) /* 存储分配失败 */
 38             return ERROR;
 39     (*L)->next=NULL; /* 指针域为空 */
 40 
 41     return OK;
 42 }
 43 
 44 /* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
 45 Status ListEmpty(LinkList L)
 46 { 
 47     if(L->next)
 48             return FALSE;
 49     else
 50             return TRUE;
 51 }
 52 
 53 /* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
 54 Status ClearList(LinkList *L)
 55 { 
 56     LinkList p,q;
 57     p=(*L)->next;           /*  p指向第一个结点 */
 58     while(p)                /*  没到表尾 */
 59     {
 60         q=p->next;
 61         free(p);
 62         p=q;
 63     }
 64     (*L)->next=NULL;        /* 头结点指针域为空 */
 65     return OK;
 66 }
 67 
 68 /* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
 69 int ListLength(LinkList L)
 70 {
 71     int i=0;
 72     LinkList p=L->next; /* p指向第一个结点 */
 73     while(p)                        
 74     {
 75         i++;
 76         p=p->next;
 77     }
 78     return i;
 79 }
 80 
 81 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
 82 /* 操作结果:用e返回L中第i个数据元素的值 */
 83 Status GetElem(LinkList L,int i,ElemType *e)
 84 {
 85     int j;
 86     LinkList p;        /* 声明一结点p */
 87     p = L->next;        /* 让p指向链表L的第一个结点 */
 88     j = 1;        /*  j为计数器 */
 89     while (p && j<i)  /* p不为空或者计数器j还没有等于i时,循环继续 */
 90     {   
 91         p = p->next;  /* 让p指向下一个结点 */
 92         ++j;
 93     }
 94     if ( !p || j>i ) 
 95         return ERROR;  /*  第i个元素不存在 */
 96     *e = p->data;   /*  取第i个元素的数据 */
 97     return OK;
 98 }
 99 
100 /* 初始条件:顺序线性表L已存在 */
101 /* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
102 /* 若这样的数据元素不存在,则返回值为0 */
103 int LocateElem(LinkList L,ElemType e)
104 {
105     int i=0;
106     LinkList p=L->next;
107     while(p)
108     {
109         i++;
110         if(p->data==e) /* 找到这样的数据元素 */
111                 return i;
112         p=p->next;
113     }
114 
115     return 0;
116 }
117 
118 
119 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
120 /* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
121 Status ListInsert(LinkList *L,int i,ElemType e)
122 { 
123     int j;
124     LinkList p,s;
125     p = *L;   
126     j = 1;
127     while (p && j < i)     /* 寻找第i个结点 */
128     {
129         p = p->next;
130         ++j;
131     } 
132     if (!p || j > i) 
133         return ERROR;   /* 第i个元素不存在 */
134     s = (LinkList)malloc(sizeof(Node));  /*  生成新结点(C语言标准函数) */
135     s->data = e;  
136     s->next = p->next;      /* 将p的后继结点赋值给s的后继  */
137     p->next = s;          /* 将s赋值给p的后继 */
138     return OK;
139 }
140 
141 /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
142 /* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
143 Status ListDelete(LinkList *L,int i,ElemType *e) 
144 { 
145     int j;
146     LinkList p,q;
147     p = *L;
148     j = 1;
149     while (p->next && j < i)    /* 遍历寻找第i个元素 */
150     {
151         p = p->next;
152         ++j;
153     }
154     if (!(p->next) || j > i) 
155         return ERROR;           /* 第i个元素不存在 */
156     q = p->next;
157     p->next = q->next;            /* 将q的后继赋值给p的后继 */
158     *e = q->data;               /* 将q结点中的数据给e */
159     free(q);                    /* 让系统回收此结点,释放内存 */
160     return OK;
161 }
162 
163 /* 初始条件:顺序线性表L已存在 */
164 /* 操作结果:依次对L的每个数据元素输出 */
165 Status ListTraverse(LinkList L)
166 {
167     LinkList p=L->next;
168     while(p)
169     {
170         visit(p->data);
171         p=p->next;
172     }
173     printf("\n");
174     return OK;
175 }
176 
177 /*  随机产生n个元素的值,建立带表头结点的单链线性表L(头插法) */
178 void CreateListHead(LinkList *L, int n) 
179 {
180     LinkList p;
181     int i;
182     srand(time(0));                         /* 初始化随机数种子 */
183     *L = (LinkList)malloc(sizeof(Node));
184     (*L)->next = NULL;                      /*  先建立一个带头结点的单链表 */
185     for (i=0; i<n; i++) 
186     {
187         p = (LinkList)malloc(sizeof(Node)); /*  生成新结点 */
188         p->data = rand()%100+1;             /*  随机生成100以内的数字 */
189         p->next = (*L)->next;    
190         (*L)->next = p;                        /*  插入到表头 */
191     }
192 }
193 
194 /*  随机产生n个元素的值,建立带表头结点的单链线性表L(尾插法) */
195 void CreateListTail(LinkList *L, int n) 
196 {
197     LinkList p,r;
198     int i;
199     srand(time(0));                      /* 初始化随机数种子 */
200     *L = (LinkList)malloc(sizeof(Node)); /* L为整个线性表 */
201     r=*L;                                /* r为指向尾部的结点 */
202     for (i=0; i<n; i++) 
203     {
204         p = (Node *)malloc(sizeof(Node)); /*  生成新结点 */
205         p->data = rand()%100+1;           /*  随机生成100以内的数字 */
206         r->next=p;                        /* 将表尾终端结点的指针指向新结点 */
207         r = p;                            /* 将当前的新结点定义为表尾终端结点 */
208     }
209     r->next = NULL;                       /* 表示当前链表结束 */
210 }
211 
212 int main()
213 {        
214     LinkList L;
215     ElemType e;
216     Status i;
217     int j,k;
218     i=InitList(&L);
219     printf("初始化L后:ListLength(L)=%d\n",ListLength(L));
220     for(j=1;j<=5;j++)
221             i=ListInsert(&L,1,j);
222     printf("在L的表头依次插入1~5后:L.data=");
223     ListTraverse(L); 
224 
225     printf("ListLength(L)=%d \n",ListLength(L));
226     i=ListEmpty(L);
227     printf("L是否空:i=%d(1:是 0:否)\n",i);
228 
229     i=ClearList(&L);
230     printf("清空L后:ListLength(L)=%d\n",ListLength(L));
231     i=ListEmpty(L);
232     printf("L是否空:i=%d(1:是 0:否)\n",i);
233 
234     for(j=1;j<=10;j++)
235             ListInsert(&L,j,j);
236     printf("在L的表尾依次插入1~10后:L.data=");
237     ListTraverse(L); 
238 
239     printf("ListLength(L)=%d \n",ListLength(L));
240 
241     ListInsert(&L,1,0);
242     printf("在L的表头插入0后:L.data=");
243     ListTraverse(L); 
244     printf("ListLength(L)=%d \n",ListLength(L));
245 
246     GetElem(L,5,&e);
247     printf("第5个元素的值为:%d\n",e);
248     for(j=3;j<=4;j++)
249     {
250             k=LocateElem(L,j);
251             if(k)
252                     printf("第%d个元素的值为%d\n",k,j);
253             else
254                     printf("没有值为%d的元素\n",j);
255     }
256     
257 
258     k=ListLength(L); /* k为表长 */
259     for(j=k+1;j>=k;j--)
260     {
261             i=ListDelete(&L,j,&e); /* 删除第j个数据 */
262             if(i==ERROR)
263                     printf("删除第%d个数据失败\n",j);
264             else
265                     printf("删除第%d个的元素值为:%d\n",j,e);
266     }
267     printf("依次输出L的元素:");
268     ListTraverse(L); 
269 
270     j=5;
271     ListDelete(&L,j,&e); /* 删除第5个数据 */
272     printf("删除第%d个的元素值为:%d\n",j,e);
273 
274     printf("依次输出L的元素:");
275     ListTraverse(L); 
276 
277     i=ClearList(&L);
278     printf("\n清空L后:ListLength(L)=%d\n",ListLength(L));
279     CreateListHead(&L,20);
280     printf("整体创建L的元素(头插法):");
281     ListTraverse(L); 
282     
283     i=ClearList(&L);
284     printf("\n删除L后:ListLength(L)=%d\n",ListLength(L));
285     CreateListTail(&L,20);
286     printf("整体创建L的元素(尾插法):");
287     ListTraverse(L); 
288 
289 
290     return 0;
291 }
LinkList.c

  3、静态链表

StaticLinkList.c

 

二、栈与队列

  1、顺序栈

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 #define MAXSIZE 20 /* 存储空间初始分配量 */
 12 
 13 typedef int Status; 
 14 typedef int SElemType; /* SElemType类型根据实际情况而定,这里假设为int */
 15 
 16 /* 顺序栈结构 */
 17 typedef struct
 18 {
 19         SElemType data[MAXSIZE];
 20         int top; /* 用于栈顶指针 */
 21 }SqStack;
 22 
 23 Status visit(SElemType c)
 24 {
 25         printf("%d ",c);
 26         return OK;
 27 }
 28 
 29 /*  构造一个空栈S */
 30 Status InitStack(SqStack *S)
 31 { 
 32         /* S.data=(SElemType *)malloc(MAXSIZE*sizeof(SElemType)); */
 33         S->top=-1;
 34         return OK;
 35 }
 36 
 37 /* 把S置为空栈 */
 38 Status ClearStack(SqStack *S)
 39 { 
 40         S->top=-1;
 41         return OK;
 42 }
 43 
 44 /* 若栈S为空栈,则返回TRUE,否则返回FALSE */
 45 Status StackEmpty(SqStack S)
 46 { 
 47         if (S.top==-1)
 48                 return TRUE;
 49         else
 50                 return FALSE;
 51 }
 52 
 53 /* 返回S的元素个数,即栈的长度 */
 54 int StackLength(SqStack S)
 55 { 
 56         return S.top+1;
 57 }
 58 
 59 /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
 60 Status GetTop(SqStack S,SElemType *e)
 61 {
 62         if (S.top==-1)
 63                 return ERROR;
 64         else
 65                 *e=S.data[S.top];
 66         return OK;
 67 }
 68 
 69 /* 插入元素e为新的栈顶元素 */
 70 Status Push(SqStack *S,SElemType e)
 71 {
 72         if(S->top == MAXSIZE -1) /* 栈满 */
 73         {
 74                 return ERROR;
 75         }
 76         S->top++;                /* 栈顶指针增加一 */
 77         S->data[S->top]=e;  /* 将新插入元素赋值给栈顶空间 */
 78         return OK;
 79 }
 80 
 81 /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
 82 Status Pop(SqStack *S,SElemType *e)
 83 { 
 84         if(S->top==-1)
 85                 return ERROR;
 86         *e=S->data[S->top];    /* 将要删除的栈顶元素赋值给e */
 87         S->top--;                /* 栈顶指针减一 */
 88         return OK;
 89 }
 90 
 91 /* 从栈底到栈顶依次对栈中每个元素显示 */
 92 Status StackTraverse(SqStack S)
 93 {
 94         int i;
 95         i=0;
 96         while(i<=S.top)
 97         {
 98                 visit(S.data[i++]);
 99         }
100         printf("\n");
101         return OK;
102 }
103 
104 int main()
105 {
106         int j;
107         SqStack s;
108         int e;
109         if(InitStack(&s)==OK)
110                 for(j=1;j<=10;j++)
111                         Push(&s,j);
112         printf("栈中元素依次为:");
113         StackTraverse(s);
114         Pop(&s,&e);
115         printf("弹出的栈顶元素 e=%d\n",e);
116         printf("栈空否:%d(1:空 0:否)\n",StackEmpty(s));
117         GetTop(s,&e);
118         printf("栈顶元素 e=%d 栈的长度为%d\n",e,StackLength(s));
119         ClearStack(&s);
120         printf("清空栈后,栈空否:%d(1:空 0:否)\n",StackEmpty(s));
121         
122         return 0;
123 }
Stack.c

  2、两栈共享空间

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 #define MAXSIZE 20 /* 存储空间初始分配量 */
 12 
 13 typedef int Status; 
 14 
 15 typedef int SElemType; /* SElemType类型根据实际情况而定,这里假设为int */
 16 
 17 
 18 /* 两栈共享空间结构 */
 19 typedef struct 
 20 {
 21         SElemType data[MAXSIZE];
 22         int top1;    /* 栈1栈顶指针 */
 23         int top2;    /* 栈2栈顶指针 */
 24 }SqDoubleStack;
 25 
 26 
 27 Status visit(SElemType c)
 28 {
 29         printf("%d ",c);
 30         return OK;
 31 }
 32 
 33 /*  构造一个空栈S */
 34 Status InitStack(SqDoubleStack *S)
 35 { 
 36         S->top1=-1;
 37         S->top2=MAXSIZE;
 38         return OK;
 39 }
 40 
 41 /* 把S置为空栈 */
 42 Status ClearStack(SqDoubleStack *S)
 43 { 
 44         S->top1=-1;
 45         S->top2=MAXSIZE;
 46         return OK;
 47 }
 48 
 49 /* 若栈S为空栈,则返回TRUE,否则返回FALSE */
 50 Status StackEmpty(SqDoubleStack S)
 51 { 
 52         if (S.top1==-1 && S.top2==MAXSIZE)
 53                 return TRUE;
 54         else
 55                 return FALSE;
 56 }
 57 
 58 /* 返回S的元素个数,即栈的长度 */
 59 int StackLength(SqDoubleStack S)
 60 { 
 61         return (S.top1+1)+(MAXSIZE-S.top2);
 62 }
 63 
 64 /* 插入元素e为新的栈顶元素 */
 65 Status Push(SqDoubleStack *S,SElemType e,int stackNumber)
 66 {
 67         if (S->top1+1==S->top2)    /* 栈已满,不能再push新元素了 */
 68                 return ERROR;    
 69         if (stackNumber==1)            /* 栈1有元素进栈 */
 70                 S->data[++S->top1]=e; /* 若是栈1则先top1+1后给数组元素赋值。 */
 71         else if (stackNumber==2)    /* 栈2有元素进栈 */
 72                 S->data[--S->top2]=e; /* 若是栈2则先top2-1后给数组元素赋值。 */
 73         return OK;
 74 }
 75 
 76 /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
 77 Status Pop(SqDoubleStack *S,SElemType *e,int stackNumber)
 78 { 
 79         if (stackNumber==1) 
 80         {
 81                 if (S->top1==-1) 
 82                         return ERROR; /* 说明栈1已经是空栈,溢出 */
 83                 *e=S->data[S->top1--]; /* 将栈1的栈顶元素出栈 */
 84         }
 85         else if (stackNumber==2)
 86         { 
 87                 if (S->top2==MAXSIZE) 
 88                         return ERROR; /* 说明栈2已经是空栈,溢出 */
 89                 *e=S->data[S->top2++]; /* 将栈2的栈顶元素出栈 */
 90         }
 91         return OK;
 92 }
 93 
 94 Status StackTraverse(SqDoubleStack S)
 95 {
 96         int i;
 97         i=0;
 98         while(i<=S.top1)
 99         {
100                 visit(S.data[i++]);
101         }
102         i=S.top2;
103         while(i<MAXSIZE)
104         {
105                 visit(S.data[i++]);
106         }
107         printf("\n");
108         return OK;
109 }
110 
111 int main()
112 {
113         int j;
114         SqDoubleStack s;
115         int e;
116         if(InitStack(&s)==OK)
117         {
118                 for(j=1;j<=5;j++)
119                         Push(&s,j,1);
120                 for(j=MAXSIZE;j>=MAXSIZE-2;j--)
121                         Push(&s,j,2);
122         }
123 
124         printf("栈中元素依次为:");
125         StackTraverse(s);
126 
127         printf("当前栈中元素有:%d \n",StackLength(s));
128 
129         Pop(&s,&e,2);
130         printf("弹出的栈顶元素 e=%d\n",e);
131         printf("栈空否:%d(1:空 0:否)\n",StackEmpty(s));
132 
133         for(j=6;j<=MAXSIZE-2;j++)
134                 Push(&s,j,1);
135 
136         printf("栈中元素依次为:");
137         StackTraverse(s);
138 
139         printf("栈满否:%d(1:否 0:满)\n",Push(&s,100,1));
140 
141         
142         ClearStack(&s);
143         printf("清空栈后,栈空否:%d(1:空 0:否)\n",StackEmpty(s));
144         
145         return 0;
146 }
DoubleStack.c

  3、链栈

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 #define MAXSIZE 20 /* 存储空间初始分配量 */
 12 
 13 typedef int Status; 
 14 typedef int SElemType; /* SElemType类型根据实际情况而定,这里假设为int */
 15 
 16 
 17 /* 链栈结构 */
 18 typedef struct StackNode
 19 {
 20         SElemType data;
 21         struct StackNode *next;
 22 }StackNode,*LinkStackPtr;
 23 
 24 
 25 typedef struct
 26 {
 27         LinkStackPtr top;
 28         int count;
 29 }LinkStack;
 30 
 31 Status visit(SElemType c)
 32 {
 33         printf("%d ",c);
 34         return OK;
 35 }
 36 
 37 /*  构造一个空栈S */
 38 Status InitStack(LinkStack *S)
 39 { 
 40         S->top = (LinkStackPtr)malloc(sizeof(StackNode));
 41         if(!S->top)
 42                 return ERROR;
 43         S->top=NULL;
 44         S->count=0;
 45         return OK;
 46 }
 47 
 48 /* 把S置为空栈 */
 49 Status ClearStack(LinkStack *S)
 50 { 
 51         LinkStackPtr p,q;
 52         p=S->top;
 53         while(p)
 54         {  
 55                 q=p;
 56                 p=p->next;
 57                 free(q);
 58         } 
 59         S->count=0;
 60         return OK;
 61 }
 62 
 63 /* 若栈S为空栈,则返回TRUE,否则返回FALSE */
 64 Status StackEmpty(LinkStack S)
 65 { 
 66         if (S.count==0)
 67                 return TRUE;
 68         else
 69                 return FALSE;
 70 }
 71 
 72 /* 返回S的元素个数,即栈的长度 */
 73 int StackLength(LinkStack S)
 74 { 
 75         return S.count;
 76 }
 77 
 78 /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
 79 Status GetTop(LinkStack S,SElemType *e)
 80 {
 81         if (S.top==NULL)
 82                 return ERROR;
 83         else
 84                 *e=S.top->data;
 85         return OK;
 86 }
 87 
 88 /* 插入元素e为新的栈顶元素 */
 89 Status Push(LinkStack *S,SElemType e)
 90 {
 91         LinkStackPtr s=(LinkStackPtr)malloc(sizeof(StackNode)); 
 92         s->data=e; 
 93         s->next=S->top;    /* 把当前的栈顶元素赋值给新结点的直接后继,见图中① */
 94         S->top=s;         /* 将新的结点s赋值给栈顶指针,见图中② */
 95         S->count++;
 96         return OK;
 97 }
 98 
 99 /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
100 Status Pop(LinkStack *S,SElemType *e)
101 { 
102         LinkStackPtr p;
103         if(StackEmpty(*S))
104                 return ERROR;
105         *e=S->top->data;
106         p=S->top;                    /* 将栈顶结点赋值给p,见图中③ */
107         S->top=S->top->next;    /* 使得栈顶指针下移一位,指向后一结点,见图中④ */
108         free(p);                    /* 释放结点p */        
109         S->count--;
110         return OK;
111 }
112 
113 Status StackTraverse(LinkStack S)
114 {
115         LinkStackPtr p;
116         p=S.top;
117         while(p)
118         {
119                  visit(p->data);
120                  p=p->next;
121         }
122         printf("\n");
123         return OK;
124 }
125 
126 int main()
127 {
128         int j;
129         LinkStack s;
130         int e;
131         if(InitStack(&s)==OK)
132                 for(j=1;j<=10;j++)
133                         Push(&s,j);
134         printf("栈中元素依次为:");
135         StackTraverse(s);
136         Pop(&s,&e);
137         printf("弹出的栈顶元素 e=%d\n",e);
138         printf("栈空否:%d(1:空 0:否)\n",StackEmpty(s));
139         GetTop(s,&e);
140         printf("栈顶元素 e=%d 栈的长度为%d\n",e,StackLength(s));
141         ClearStack(&s);
142         printf("清空栈后,栈空否:%d(1:空 0:否)\n",StackEmpty(s));
143         return 0;
144 }
LinkStack.c

  4、顺序队列

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 #define MAXSIZE 20 /* 存储空间初始分配量 */
 12 
 13 typedef int Status; 
 14 typedef int QElemType; /* QElemType类型根据实际情况而定,这里假设为int */
 15 
 16 /* 循环队列的顺序存储结构 */
 17 typedef struct
 18 {
 19     QElemType data[MAXSIZE];
 20     int front;        /* 头指针 */
 21     int rear;        /* 尾指针,若队列不空,指向队列尾元素的下一个位置 */
 22 }SqQueue;
 23 
 24 Status visit(QElemType c)
 25 {
 26     printf("%d ",c);
 27     return OK;
 28 }
 29 
 30 /* 初始化一个空队列Q */
 31 Status InitQueue(SqQueue *Q)
 32 {
 33     Q->front=0;
 34     Q->rear=0;
 35     return  OK;
 36 }
 37 
 38 /* 将Q清为空队列 */
 39 Status ClearQueue(SqQueue *Q)
 40 {
 41     Q->front=Q->rear=0;
 42     return OK;
 43 }
 44 
 45 /* 若队列Q为空队列,则返回TRUE,否则返回FALSE */
 46 Status QueueEmpty(SqQueue Q)
 47 { 
 48     if(Q.front==Q.rear) /* 队列空的标志 */
 49         return TRUE;
 50     else
 51         return FALSE;
 52 }
 53 
 54 /* 返回Q的元素个数,也就是队列的当前长度 */
 55 int QueueLength(SqQueue Q)
 56 {
 57     return  (Q.rear-Q.front+MAXSIZE)%MAXSIZE;
 58 }
 59 
 60 /* 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR */
 61 Status GetHead(SqQueue Q,QElemType *e)
 62 {
 63     if(Q.front==Q.rear) /* 队列空 */
 64         return ERROR;
 65     *e=Q.data[Q.front];
 66     return OK;
 67 }
 68 
 69 /* 若队列未满,则插入元素e为Q新的队尾元素 */
 70 Status EnQueue(SqQueue *Q,QElemType e)
 71 {
 72     if ((Q->rear+1)%MAXSIZE == Q->front)    /* 队列满的判断 */
 73         return ERROR;
 74     Q->data[Q->rear]=e;            /* 将元素e赋值给队尾 */
 75     Q->rear=(Q->rear+1)%MAXSIZE;/* rear指针向后移一位置, */
 76                                 /* 若到最后则转到数组头部 */
 77     return  OK;
 78 }
 79 
 80 /* 若队列不空,则删除Q中队头元素,用e返回其值 */
 81 Status DeQueue(SqQueue *Q,QElemType *e)
 82 {
 83     if (Q->front == Q->rear)            /* 队列空的判断 */
 84         return ERROR;
 85     *e=Q->data[Q->front];                /* 将队头元素赋值给e */
 86     Q->front=(Q->front+1)%MAXSIZE;    /* front指针向后移一位置, */
 87                                     /* 若到最后则转到数组头部 */
 88     return  OK;
 89 }
 90 
 91 /* 从队头到队尾依次对队列Q中每个元素输出 */
 92 Status QueueTraverse(SqQueue Q)
 93 { 
 94     int i;
 95     i=Q.front;
 96     while((i+Q.front)!=Q.rear)
 97     {
 98         visit(Q.data[i]);
 99         i=(i+1)%MAXSIZE;
100     }
101     printf("\n");
102     return OK;
103 }
104 
105 int main()
106 {
107     Status j;
108     int i=0,l;
109     QElemType d;
110     SqQueue Q;
111     InitQueue(&Q);
112     printf("初始化队列后,队列空否?%u(1:空 0:否)\n",QueueEmpty(Q));
113 
114     printf("请输入整型队列元素(不超过%d个),-1为提前结束符: ",MAXSIZE-1);
115     do
116     {
117         /* scanf("%d",&d); */
118         d=i+100;
119         if(d==-1)
120             break;
121         i++;
122         EnQueue(&Q,d);
123     }while(i<MAXSIZE-1);
124 
125     printf("队列长度为: %d\n",QueueLength(Q));
126     printf("现在队列空否?%u(1:空 0:否)\n",QueueEmpty(Q));
127     printf("连续%d次由队头删除元素,队尾插入元素:\n",MAXSIZE);
128     for(l=1;l<=MAXSIZE;l++)
129     {
130         DeQueue(&Q,&d);
131         printf("删除的元素是%d,插入的元素:%d \n",d,l+1000);
132         /* scanf("%d",&d); */
133         d=l+1000;
134         EnQueue(&Q,d);
135     }
136     l=QueueLength(Q);
137 
138     printf("现在队列中的元素为: \n");
139     QueueTraverse(Q);
140     printf("共向队尾插入了%d个元素\n",i+MAXSIZE);
141     if(l-2>0)
142         printf("现在由队头删除%d个元素:\n",l-2);
143     while(QueueLength(Q)>2)
144     {
145         DeQueue(&Q,&d);
146         printf("删除的元素值为%d\n",d);
147     }
148 
149     j=GetHead(Q,&d);
150     if(j)
151         printf("现在队头元素为: %d\n",d);
152     ClearQueue(&Q);
153     printf("清空队列后, 队列空否?%u(1:空 0:否)\n",QueueEmpty(Q));
154     return 0;
155 }
Queue.c

  5、链队列

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 #define MAXSIZE 20 /* 存储空间初始分配量 */
 12 
 13 typedef int Status; 
 14 
 15 typedef int QElemType; /* QElemType类型根据实际情况而定,这里假设为int */
 16 
 17 typedef struct QNode    /* 结点结构 */
 18 {
 19    QElemType data;
 20    struct QNode *next;
 21 }QNode,*QueuePtr;
 22 
 23 typedef struct            /* 队列的链表结构 */
 24 {
 25    QueuePtr front,rear; /* 队头、队尾指针 */
 26 }LinkQueue;
 27 
 28 Status visit(QElemType c)
 29 {
 30     printf("%d ",c);
 31     return OK;
 32 }
 33 
 34 /* 构造一个空队列Q */
 35 Status InitQueue(LinkQueue *Q)
 36 { 
 37     Q->front=Q->rear=(QueuePtr)malloc(sizeof(QNode));
 38     if(!Q->front)
 39         exit(OVERFLOW);
 40     Q->front->next=NULL;
 41     return OK;
 42 }
 43 
 44 /* 销毁队列Q */
 45 Status DestroyQueue(LinkQueue *Q)
 46 {
 47     while(Q->front)
 48     {
 49          Q->rear=Q->front->next;
 50          free(Q->front);
 51          Q->front=Q->rear;
 52     }
 53     return OK;
 54 }
 55 
 56 /* 将Q清为空队列 */
 57 Status ClearQueue(LinkQueue *Q)
 58 {
 59     QueuePtr p,q;
 60     Q->rear=Q->front;
 61     p=Q->front->next;
 62     Q->front->next=NULL;
 63     while(p)
 64     {
 65          q=p;
 66          p=p->next;
 67          free(q);
 68     }
 69     return OK;
 70 }
 71 
 72 /* 若Q为空队列,则返回TRUE,否则返回FALSE */
 73 Status QueueEmpty(LinkQueue Q)
 74 { 
 75     if(Q.front==Q.rear)
 76         return TRUE;
 77     else
 78         return FALSE;
 79 }
 80 
 81 /* 求队列的长度 */
 82 int QueueLength(LinkQueue Q)
 83 { 
 84     int i=0;
 85     QueuePtr p;
 86     p=Q.front;
 87     while(Q.rear!=p)
 88     {
 89          i++;
 90          p=p->next;
 91     }
 92     return i;
 93 }
 94 
 95 /* 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR */
 96 Status GetHead(LinkQueue Q,QElemType *e)
 97 { 
 98     QueuePtr p;
 99     if(Q.front==Q.rear)
100         return ERROR;
101     p=Q.front->next;
102     *e=p->data;
103     return OK;
104 }
105 
106 
107 /* 插入元素e为Q的新的队尾元素 */
108 Status EnQueue(LinkQueue *Q,QElemType e)
109 { 
110     QueuePtr s=(QueuePtr)malloc(sizeof(QNode));
111     if(!s) /* 存储分配失败 */
112         exit(OVERFLOW);
113     s->data=e;
114     s->next=NULL;
115     Q->rear->next=s;    /* 把拥有元素e的新结点s赋值给原队尾结点的后继,见图中① */
116     Q->rear=s;        /* 把当前的s设置为队尾结点,rear指向s,见图中② */
117     return OK;
118 }
119 
120 /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */
121 Status DeQueue(LinkQueue *Q,QElemType *e)
122 {
123     QueuePtr p;
124     if(Q->front==Q->rear)
125         return ERROR;
126     p=Q->front->next;        /* 将欲删除的队头结点暂存给p,见图中① */
127     *e=p->data;                /* 将欲删除的队头结点的值赋值给e */
128     Q->front->next=p->next;/* 将原队头结点的后继p->next赋值给头结点后继,见图中② */
129     if(Q->rear==p)        /* 若队头就是队尾,则删除后将rear指向头结点,见图中③ */
130         Q->rear=Q->front;
131     free(p);
132     return OK;
133 }
134 
135 /* 从队头到队尾依次对队列Q中每个元素输出 */
136 Status QueueTraverse(LinkQueue Q)
137 {
138     QueuePtr p;
139     p=Q.front->next;
140     while(p)
141     {
142          visit(p->data);
143          p=p->next;
144     }
145     printf("\n");
146     return OK;
147 }
148 
149 int main()
150 {
151     int i;
152     QElemType d;
153     LinkQueue q;
154     i=InitQueue(&q);
155     if(i)
156         printf("成功地构造了一个空队列!\n");
157     printf("是否空队列?%d(1:空 0:否)  ",QueueEmpty(q));
158     printf("队列的长度为%d\n",QueueLength(q));
159     EnQueue(&q,-5);
160     EnQueue(&q,5);
161     EnQueue(&q,10);
162     printf("插入3个元素(-5,5,10)后,队列的长度为%d\n",QueueLength(q));
163     printf("是否空队列?%d(1:空 0:否)  ",QueueEmpty(q));
164     printf("队列的元素依次为:");
165     QueueTraverse(q);
166     i=GetHead(q,&d);
167     if(i==OK)
168      printf("队头元素是:%d\n",d);
169     DeQueue(&q,&d);
170     printf("删除了队头元素%d\n",d);
171     i=GetHead(q,&d);
172     if(i==OK)
173         printf("新的队头元素是:%d\n",d);
174     ClearQueue(&q);
175     printf("清空队列后,q.front=%u q.rear=%u q.front->next=%u\n",q.front,q.rear,q.front->next);
176     DestroyQueue(&q);
177     printf("销毁队列后,q.front=%u q.rear=%u\n",q.front, q.rear);
178     
179     return 0;
180 }
LinkQueue.c

 

三、串

  1、串

  1 #include "string.h"
  2 #include "stdio.h"    
  3 #include "stdlib.h"   
  4 #include "io.h"  
  5 #include "math.h"  
  6 #include "time.h"
  7 
  8 #define OK 1
  9 #define ERROR 0
 10 #define TRUE 1
 11 #define FALSE 0
 12 
 13 #define MAXSIZE 40 /* 存储空间初始分配量 */
 14 
 15 typedef int Status;        /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
 16 typedef int ElemType;    /* ElemType类型根据实际情况而定,这里假设为int */
 17 
 18 typedef char String[MAXSIZE+1]; /*  0号单元存放串的长度 */
 19 
 20 /* 生成一个其值等于chars的串T */
 21 Status StrAssign(String T,char *chars)
 22 { 
 23     int i;
 24     if(strlen(chars)>MAXSIZE)
 25         return ERROR;
 26     else
 27     {
 28         T[0]=strlen(chars);
 29         for(i=1;i<=T[0];i++)
 30             T[i]=*(chars+i-1);
 31         return OK;
 32     }
 33 }
 34 
 35 /* 由串S复制得串T */
 36 Status StrCopy(String T,String S)
 37 { 
 38     int i;
 39     for(i=0;i<=S[0];i++)
 40         T[i]=S[i];
 41     return OK;
 42 }
 43 
 44 /* 若S为空串,则返回TRUE,否则返回FALSE */
 45 Status StrEmpty(String S)
 46 { 
 47     if(S[0]==0)
 48         return TRUE;
 49     else
 50         return FALSE;
 51 }
 52 
 53 /*  初始条件: 串S和T存在 */
 54 /*  操作结果: 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0 */
 55 int StrCompare(String S,String T)
 56 { 
 57     int i;
 58     for(i=1;i<=S[0]&&i<=T[0];++i)
 59         if(S[i]!=T[i])
 60             return S[i]-T[i];
 61     return S[0]-T[0];
 62 }
 63 
 64 /* 返回串的元素个数 */
 65 int StrLength(String S)
 66 { 
 67     return S[0];
 68 }
 69 
 70 /* 初始条件:串S存在。操作结果:将S清为空串 */
 71 Status ClearString(String S)
 72 { 
 73     S[0]=0;/*  令串长为零 */
 74     return OK;
 75 }
 76 
 77 /* 用T返回S1和S2联接而成的新串。若未截断,则返回TRUE,否则FALSE */
 78 Status Concat(String T,String S1,String S2)
 79 {
 80     int i;
 81     if(S1[0]+S2[0]<=MAXSIZE)
 82     { /*  未截断 */
 83         for(i=1;i<=S1[0];i++)
 84             T[i]=S1[i];
 85         for(i=1;i<=S2[0];i++)
 86             T[S1[0]+i]=S2[i];
 87         T[0]=S1[0]+S2[0];
 88         return TRUE;
 89     }
 90     else
 91     { /*  截断S2 */
 92         for(i=1;i<=S1[0];i++)
 93             T[i]=S1[i];
 94         for(i=1;i<=MAXSIZE-S1[0];i++)
 95             T[S1[0]+i]=S2[i];
 96         T[0]=MAXSIZE;
 97         return FALSE;
 98     }
 99 }
100 
101 /* 用Sub返回串S的第pos个字符起长度为len的子串。 */
102 Status SubString(String Sub,String S,int pos,int len)
103 {
104     int i;
105     if(pos<1||pos>S[0]||len<0||len>S[0]-pos+1)
106         return ERROR;
107     for(i=1;i<=len;i++)
108         Sub[i]=S[pos+i-1];
109     Sub[0]=len;
110     return OK;
111 }
112 
113 /* 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。 */
114 /* 其中,T非空,1≤pos≤StrLength(S)。 */
115 int Index(String S, String T, int pos) 
116 {
117     int i = pos;    /* i用于主串S中当前位置下标值,若pos不为1,则从pos位置开始匹配 */
118     int j = 1;                /* j用于子串T中当前位置下标值 */
119     while (i <= S[0] && j <= T[0]) /* 若i小于S的长度并且j小于T的长度时,循环继续 */
120     {
121         if (S[i] == T[j])     /* 两字母相等则继续 */
122           {
123             ++i;
124              ++j; 
125           } 
126           else                 /* 指针后退重新开始匹配 */
127           {  
128              i = i-j+2;        /* i退回到上次匹配首位的下一位 */
129              j = 1;             /* j退回到子串T的首位 */
130           }      
131     }
132     if (j > T[0]) 
133         return i-T[0];
134     else 
135         return 0;
136 }
137 
138 
139 /*  T为非空串。若主串S中第pos个字符之后存在与T相等的子串, */
140 /*  则返回第一个这样的子串在S中的位置,否则返回0 */
141 int Index2(String S, String T, int pos) 
142 {
143     int n,m,i;
144     String sub;
145     if (pos > 0) 
146     {
147         n = StrLength(S);    /* 得到主串S的长度 */
148         m = StrLength(T);    /* 得到子串T的长度 */
149         i = pos;
150         while (i <= n-m+1) 
151         {
152             SubString (sub, S, i, m);    /* 取主串中第i个位置长度与T相等的子串给sub */
153             if (StrCompare(sub,T) != 0)    /* 如果两串不相等 */
154                 ++i;
155             else                 /* 如果两串相等 */
156                 return i;        /* 则返回i值 */
157         }
158     }
159     return 0;    /* 若无子串与T相等,返回0 */
160 }
161 
162 
163 /*  初始条件: 串S和T存在,1≤pos≤StrLength(S)+1 */
164 /*  操作结果: 在串S的第pos个字符之前插入串T。完全插入返回TRUE,部分插入返回FALSE */
165 Status StrInsert(String S,int pos,String T)
166 { 
167     int i;
168     if(pos<1||pos>S[0]+1)
169         return ERROR;
170     if(S[0]+T[0]<=MAXSIZE)
171     { /*  完全插入 */
172         for(i=S[0];i>=pos;i--)
173             S[i+T[0]]=S[i];
174         for(i=pos;i<pos+T[0];i++)
175             S[i]=T[i-pos+1];
176         S[0]=S[0]+T[0];
177         return TRUE;
178     }
179     else
180     { /*  部分插入 */
181         for(i=MAXSIZE;i<=pos;i--)
182             S[i]=S[i-T[0]];
183         for(i=pos;i<pos+T[0];i++)
184             S[i]=T[i-pos+1];
185         S[0]=MAXSIZE;
186         return FALSE;
187     }
188 }
189 
190 /*  初始条件: 串S存在,1≤pos≤StrLength(S)-len+1 */
191 /*  操作结果: 从串S中删除第pos个字符起长度为len的子串 */
192 Status StrDelete(String S,int pos,int len)
193 { 
194     int i;
195     if(pos<1||pos>S[0]-len+1||len<0)
196         return ERROR;
197     for(i=pos+len;i<=S[0];i++)
198         S[i-len]=S[i];
199     S[0]-=len;
200     return OK;
201 }
202 
203 /*  初始条件: 串S,T和V存在,T是非空串(此函数与串的存储结构无关) */
204 /*  操作结果: 用V替换主串S中出现的所有与T相等的不重叠的子串 */
205 Status Replace(String S,String T,String V)
206 { 
207     int i=1; /*  从串S的第一个字符起查找串T */
208     if(StrEmpty(T)) /*  T是空串 */
209         return ERROR;
210     do
211     {
212         i=Index(S,T,i); /*  结果i为从上一个i之后找到的子串T的位置 */
213         if(i) /*  串S中存在串T */
214         {
215             StrDelete(S,i,StrLength(T)); /*  删除该串T */
216             StrInsert(S,i,V); /*  在原串T的位置插入串V */
217             i+=StrLength(V); /*  在插入的串V后面继续查找串T */
218         }
219     }while(i);
220     return OK;
221 }
222 
223 /*  输出字符串T */
224 void StrPrint(String T)
225 { 
226     int i;
227     for(i=1;i<=T[0];i++)
228         printf("%c",T[i]);
229     printf("\n");
230 }
231 
232 
233 int main()
234 {
235     
236     int i,j;
237     Status k;
238     char s;
239     String t,s1,s2;
240     printf("请输入串s1: ");
241     
242     k=StrAssign(s1,"abcd");
243     if(!k)
244     {
245         printf("串长超过MAXSIZE(=%d)\n",MAXSIZE);
246         exit(0);
247     }
248     printf("串长为%d 串空否?%d(1:是 0:否)\n",StrLength(s1),StrEmpty(s1));
249     StrCopy(s2,s1);
250     printf("拷贝s1生成的串为: ");
251     StrPrint(s2);
252     printf("请输入串s2: ");
253     
254     k=StrAssign(s2,"efghijk");
255     if(!k)
256     {
257         printf("串长超过MAXSIZE(%d)\n",MAXSIZE);
258         exit(0);
259     }
260     i=StrCompare(s1,s2);
261     if(i<0)
262         s='<';
263     else if(i==0)
264         s='=';
265     else
266         s='>';
267     printf("串s1%c串s2\n",s);
268     k=Concat(t,s1,s2);
269     printf("串s1联接串s2得到的串t为: ");
270     StrPrint(t);
271     if(k==FALSE)
272         printf("串t有截断\n");
273     ClearString(s1);
274     printf("清为空串后,串s1为: ");
275     StrPrint(s1);
276     printf("串长为%d 串空否?%d(1:是 0:否)\n",StrLength(s1),StrEmpty(s1));
277     printf("求串t的子串,请输入子串的起始位置,子串长度: ");
278 
279     i=2;
280     j=3;
281     printf("%d,%d \n",i,j);
282 
283     k=SubString(s2,t,i,j);
284     if(k)
285     {
286         printf("子串s2为: ");
287         StrPrint(s2);
288     }
289     printf("从串t的第pos个字符起,删除len个字符,请输入pos,len: ");
290     
291     i=4;
292     j=2;
293     printf("%d,%d \n",i,j);
294 
295 
296     StrDelete(t,i,j);
297     printf("删除后的串t为: ");
298     StrPrint(t);
299     i=StrLength(s2)/2;
300     StrInsert(s2,i,t);
301     printf("在串s2的第%d个字符之前插入串t后,串s2为:\n",i);
302     StrPrint(s2);
303     i=Index(s2,t,1);
304     printf("s2的第%d个字母起和t第一次匹配\n",i);
305     SubString(t,s2,1,1);
306     printf("串t为:");
307     StrPrint(t);
308     Concat(s1,t,t);
309     printf("串s1为:");
310     StrPrint(s1);
311     Replace(s2,t,s1);
312     printf("用串s1取代串s2中和串t相同的不重叠的串后,串s2为: ");
313     StrPrint(s2);
314 
315 
316     return 0;
317 }
String.c

  2、模式匹配 KMP

  1 #include "string.h"
  2 #include "stdio.h"    
  3 #include "stdlib.h"   
  4 #include "io.h"  
  5 #include "math.h"  
  6 #include "time.h"
  7 
  8 #define OK 1
  9 #define ERROR 0
 10 #define TRUE 1
 11 #define FALSE 0
 12 #define MAXSIZE 100 /* 存储空间初始分配量 */
 13 
 14 typedef int Status;        /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
 15 typedef int ElemType;    /* ElemType类型根据实际情况而定,这里假设为int */
 16 
 17 typedef char String[MAXSIZE+1]; /*  0号单元存放串的长度 */
 18 
 19 /* 生成一个其值等于chars的串T */
 20 Status StrAssign(String T,char *chars)
 21 { 
 22     int i;
 23     if(strlen(chars)>MAXSIZE)
 24         return ERROR;
 25     else
 26     {
 27         T[0]=strlen(chars);
 28         for(i=1;i<=T[0];i++)
 29             T[i]=*(chars+i-1);
 30         return OK;
 31     }
 32 }
 33 
 34 Status ClearString(String S)
 35 { 
 36     S[0]=0;/*  令串长为零 */
 37     return OK;
 38 }
 39 
 40 /*  输出字符串T。 */
 41 void StrPrint(String T)
 42 { 
 43     int i;
 44     for(i=1;i<=T[0];i++)
 45         printf("%c",T[i]);
 46     printf("\n");
 47 }
 48 
 49 /*  输出Next数组值。 */
 50 void NextPrint(int next[],int length)
 51 { 
 52     int i;
 53     for(i=1;i<=length;i++)
 54         printf("%d",next[i]);
 55     printf("\n");
 56 }
 57 
 58 /* 返回串的元素个数 */
 59 int StrLength(String S)
 60 { 
 61     return S[0];
 62 }
 63 
 64 /* 朴素的模式匹配法 */
 65 int Index(String S, String T, int pos) 
 66 {
 67     int i = pos;    /* i用于主串S中当前位置下标值,若pos不为1,则从pos位置开始匹配 */
 68     int j = 1;                /* j用于子串T中当前位置下标值 */
 69     while (i <= S[0] && j <= T[0]) /* 若i小于S的长度并且j小于T的长度时,循环继续 */
 70     {
 71         if (S[i] == T[j])     /* 两字母相等则继续 */
 72           {
 73             ++i;
 74              ++j; 
 75           } 
 76           else                 /* 指针后退重新开始匹配 */
 77           {  
 78              i = i-j+2;        /* i退回到上次匹配首位的下一位 */
 79              j = 1;             /* j退回到子串T的首位 */
 80           }      
 81     }
 82     if (j > T[0]) 
 83         return i-T[0];
 84     else 
 85         return 0;
 86 }
 87 
 88 /* 通过计算返回子串T的next数组。 */
 89 void get_next(String T, int *next) 
 90 {
 91     int i,j;
 92       i=1;
 93       j=0;
 94       next[1]=0;
 95       while (i<T[0])  /* 此处T[0]表示串T的长度 */
 96      {
 97         if(j==0 || T[i]== T[j])     /* T[i]表示后缀的单个字符,T[j]表示前缀的单个字符 */
 98         {
 99               ++i;  
100             ++j;  
101             next[i] = j;
102         } 
103         else 
104             j= next[j];    /* 若字符不相同,则j值回溯 */
105       }
106 }
107 
108 /* 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数返回值为0。 */
109 /*  T非空,1≤pos≤StrLength(S)。 */
110 int Index_KMP(String S, String T, int pos) 
111 {
112     int i = pos;        /* i用于主串S中当前位置下标值,若pos不为1,则从pos位置开始匹配 */
113     int j = 1;            /* j用于子串T中当前位置下标值 */
114     int next[255];        /* 定义一next数组 */
115     get_next(T, next);    /* 对串T作分析,得到next数组 */
116     while (i <= S[0] && j <= T[0]) /* 若i小于S的长度并且j小于T的长度时,循环继续 */
117     {
118         if (j==0 || S[i] == T[j])     /* 两字母相等则继续,与朴素算法增加了j=0判断 */
119           {
120              ++i;
121              ++j; 
122           } 
123           else             /* 指针后退重新开始匹配 */
124                j = next[j];/* j退回合适的位置,i值不变 */
125     }
126     if (j > T[0]) 
127         return i-T[0];
128     else 
129         return 0;
130 }
131 
132 /* 求模式串T的next函数修正值并存入数组nextval */
133 void get_nextval(String T, int *nextval) 
134 {
135       int i,j;
136       i=1;
137       j=0;
138       nextval[1]=0;
139       while (i<T[0])  /* 此处T[0]表示串T的长度 */
140      {
141         if(j==0 || T[i]== T[j])     /* T[i]表示后缀的单个字符,T[j]表示前缀的单个字符 */
142         {
143               ++i;  
144             ++j;  
145             if (T[i]!=T[j])      /* 若当前字符与前缀字符不同 */
146                 nextval[i] = j;    /* 则当前的j为nextval在i位置的值 */
147               else 
148                 nextval[i] = nextval[j];    /* 如果与前缀字符相同,则将前缀字符的 */
149                                             /* nextval值赋值给nextval在i位置的值 */
150         } 
151         else 
152             j= nextval[j];            /* 若字符不相同,则j值回溯 */
153       }
154 }
155 
156 int Index_KMP1(String S, String T, int pos) 
157 {
158     int i = pos;        /* i用于主串S中当前位置下标值,若pos不为1,则从pos位置开始匹配 */
159     int j = 1;            /* j用于子串T中当前位置下标值 */
160     int next[255];        /* 定义一next数组 */
161     get_nextval(T, next);    /* 对串T作分析,得到next数组 */
162     while (i <= S[0] && j <= T[0]) /* 若i小于S的长度并且j小于T的长度时,循环继续 */
163     {
164         if (j==0 || S[i] == T[j])     /* 两字母相等则继续,与朴素算法增加了j=0判断 */
165           {
166              ++i;
167              ++j; 
168           } 
169           else             /* 指针后退重新开始匹配 */
170                j = next[j];/* j退回合适的位置,i值不变 */
171     }
172     if (j > T[0]) 
173         return i-T[0];
174     else 
175         return 0;
176 }
177 
178 int main()
179 {
180     int i,*p;
181     String s1,s2;
182     
183     StrAssign(s1,"abcdex");
184     printf("子串为: ");
185     StrPrint(s1);
186     i=StrLength(s1);
187     p=(int*)malloc((i+1)*sizeof(int));
188     get_next(s1,p); 
189     printf("Next为: ");
190     NextPrint(p,StrLength(s1));
191     printf("\n");
192 
193     StrAssign(s1,"abcabx");
194     printf("子串为: ");
195     StrPrint(s1);
196     i=StrLength(s1);
197     p=(int*)malloc((i+1)*sizeof(int));
198     get_next(s1,p); 
199     printf("Next为: ");
200     NextPrint(p,StrLength(s1));
201     printf("\n");
202 
203     StrAssign(s1,"ababaaaba");
204     printf("子串为: ");
205     StrPrint(s1);
206     i=StrLength(s1);
207     p=(int*)malloc((i+1)*sizeof(int));
208     get_next(s1,p); 
209     printf("Next为: ");
210     NextPrint(p,StrLength(s1));
211     printf("\n");
212 
213     StrAssign(s1,"aaaaaaaab");
214     printf("子串为: ");
215     StrPrint(s1);
216     i=StrLength(s1);
217     p=(int*)malloc((i+1)*sizeof(int));
218     get_next(s1,p); 
219     printf("Next为: ");
220     NextPrint(p,StrLength(s1));
221     printf("\n");
222 
223     StrAssign(s1,"ababaaaba");
224     printf("   子串为: ");
225     StrPrint(s1);
226     i=StrLength(s1);
227     p=(int*)malloc((i+1)*sizeof(int));
228     get_next(s1,p); 
229     printf("   Next为: ");
230     NextPrint(p,StrLength(s1));
231     get_nextval(s1,p); 
232     printf("NextVal为: ");
233     NextPrint(p,StrLength(s1));
234     printf("\n");
235 
236     StrAssign(s1,"aaaaaaaab");
237     printf("   子串为: ");
238     StrPrint(s1);
239     i=StrLength(s1);
240     p=(int*)malloc((i+1)*sizeof(int));
241     get_next(s1,p); 
242     printf("   Next为: ");
243     NextPrint(p,StrLength(s1));
244     get_nextval(s1,p); 
245     printf("NextVal为: ");
246     NextPrint(p,StrLength(s1));
247 
248     printf("\n");
249 
250     StrAssign(s1,"00000000000000000000000000000000000000000000000001");
251     printf("主串为: ");
252     StrPrint(s1);
253     StrAssign(s2,"0000000001");
254     printf("子串为: ");
255     StrPrint(s2);
256     printf("\n");
257     printf("主串和子串在第%d个字符处首次匹配(朴素模式匹配算法)\n",Index(s1,s2,1));
258     printf("主串和子串在第%d个字符处首次匹配(KMP算法) \n",Index_KMP(s1,s2,1));
259     printf("主串和子串在第%d个字符处首次匹配(KMP改良算法) \n",Index_KMP1(s1,s2,1));
260 
261     return 0;
262 }
KMP.c

 

四、树

  1、二叉树顺序结构实现

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 
 12 #define MAXSIZE 100 /* 存储空间初始分配量 */
 13 #define MAX_TREE_SIZE 100 /* 二叉树的最大结点数 */
 14 
 15 typedef int Status;        /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
 16 typedef int TElemType;  /* 树结点的数据类型,目前暂定为整型 */
 17 typedef TElemType SqBiTree[MAX_TREE_SIZE]; /* 0号单元存储根结点  */
 18 
 19 typedef struct
 20 {
 21     int level,order; /* 结点的层,本层序号(按满二叉树计算) */
 22 }Position;
 23 
 24 TElemType Nil=0; /*  设整型以0为空 */
 25 
 26 Status visit(TElemType c)
 27 {
 28     printf("%d ",c);
 29     return OK;
 30 }
 31 
 32 /* 构造空二叉树T。因为T是固定数组,不会改变,故不需要& */
 33 Status InitBiTree(SqBiTree T)
 34 {
 35     int i;
 36     for(i=0;i<MAX_TREE_SIZE;i++)
 37         T[i]=Nil; /* 初值为空 */
 38     return OK;
 39 }
 40 
 41 /* 按层序次序输入二叉树中结点的值(字符型或整型), 构造顺序存储的二叉树T */
 42 Status CreateBiTree(SqBiTree T)
 43 { 
 44     int i=0;
 45      printf("请按层序输入结点的值(整型),0表示空结点,输999结束。结点数≤%d:\n",MAX_TREE_SIZE);
 46     while(i<10)
 47     {
 48         T[i]=i+1;
 49         
 50         if(i!=0&&T[(i+1)/2-1]==Nil&&T[i]!=Nil) /* 此结点(不空)无双亲且不是根 */
 51         {
 52             printf("出现无双亲的非根结点%d\n",T[i]);
 53             exit(ERROR);
 54         }
 55         i++;
 56     }
 57     while(i<MAX_TREE_SIZE)
 58     {
 59         T[i]=Nil; /* 将空赋值给T的后面的结点 */
 60         i++;
 61     }
 62 
 63     return OK;
 64 }
 65 
 66 #define ClearBiTree InitBiTree /* 在顺序存储结构中,两函数完全一样 */
 67 
 68 /* 初始条件: 二叉树T存在 */
 69 /* 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */
 70 Status BiTreeEmpty(SqBiTree T)
 71 { 
 72     if(T[0]==Nil) /* 根结点为空,则树空 */
 73         return TRUE;
 74     else
 75         return FALSE;
 76 }
 77 
 78 /* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */
 79 int BiTreeDepth(SqBiTree T)
 80 { 
 81    int i,j=-1;
 82    for(i=MAX_TREE_SIZE-1;i>=0;i--) /* 找到最后一个结点 */
 83      if(T[i]!=Nil)
 84        break;
 85    i++; 
 86    do
 87      j++;
 88    while(i>=powl(2,j));/* 计算2的j次幂。 */
 89    return j;
 90 }
 91 
 92 /* 初始条件: 二叉树T存在 */
 93 /* 操作结果:  当T不空,用e返回T的根,返回OK;否则返回ERROR,e无定义 */
 94 Status Root(SqBiTree T,TElemType *e)
 95 { 
 96     if(BiTreeEmpty(T)) /* T空 */
 97         return ERROR;
 98     else
 99     {    
100         *e=T[0];
101         return OK;
102     }
103 }
104 
105 /* 初始条件: 二叉树T存在,e是T中某个结点(的位置) */
106 /* 操作结果: 返回处于位置e(层,本层序号)的结点的值 */
107 TElemType Value(SqBiTree T,Position e)
108 { 
109      return T[(int)powl(2,e.level-1)+e.order-2];
110 }
111 
112 /* 初始条件: 二叉树T存在,e是T中某个结点(的位置) */
113 /* 操作结果: 给处于位置e(层,本层序号)的结点赋新值value */
114 Status Assign(SqBiTree T,Position e,TElemType value)
115 { 
116     int i=(int)powl(2,e.level-1)+e.order-2; /* 将层、本层序号转为矩阵的序号 */
117     if(value!=Nil&&T[(i+1)/2-1]==Nil) /* 给叶子赋非空值但双亲为空 */
118         return ERROR;
119     else if(value==Nil&&(T[i*2+1]!=Nil||T[i*2+2]!=Nil)) /*  给双亲赋空值但有叶子(不空) */
120         return ERROR;
121     T[i]=value;
122     return OK;
123 }
124 
125 /* 初始条件: 二叉树T存在,e是T中某个结点 */
126 /* 操作结果: 若e是T的非根结点,则返回它的双亲,否则返回"空" */
127 TElemType Parent(SqBiTree T,TElemType e)
128 { 
129     int i;
130     if(T[0]==Nil) /* 空树 */
131         return Nil;
132     for(i=1;i<=MAX_TREE_SIZE-1;i++)
133         if(T[i]==e) /* 找到e */
134             return T[(i+1)/2-1];
135     return Nil; /* 没找到e */
136 }
137 
138 
139 /* 初始条件: 二叉树T存在,e是T中某个结点 */
140 /* 操作结果: 返回e的左孩子。若e无左孩子,则返回"空" */
141 TElemType LeftChild(SqBiTree T,TElemType e)
142 { 
143     int i;
144     if(T[0]==Nil) /* 空树 */
145         return Nil;
146     for(i=0;i<=MAX_TREE_SIZE-1;i++)
147         if(T[i]==e) /* 找到e */
148             return T[i*2+1];
149     return Nil; /* 没找到e */
150 }
151 
152 /* 初始条件: 二叉树T存在,e是T中某个结点 */
153 /* 操作结果: 返回e的右孩子。若e无右孩子,则返回"空" */
154 TElemType RightChild(SqBiTree T,TElemType e)
155 { 
156     int i;
157     if(T[0]==Nil) /* 空树 */
158         return Nil;
159     for(i=0;i<=MAX_TREE_SIZE-1;i++)
160         if(T[i]==e) /* 找到e */
161             return T[i*2+2];
162     return Nil; /* 没找到e */
163 }
164 
165 /* 初始条件: 二叉树T存在,e是T中某个结点 */
166 /* 操作结果: 返回e的左兄弟。若e是T的左孩子或无左兄弟,则返回"空" */
167 TElemType LeftSibling(SqBiTree T,TElemType e)
168 { 
169     int i;
170     if(T[0]==Nil) /* 空树 */
171         return Nil;
172     for(i=1;i<=MAX_TREE_SIZE-1;i++)
173         if(T[i]==e&&i%2==0) /* 找到e且其序号为偶数(是右孩子) */
174             return T[i-1];
175     return Nil; /* 没找到e */
176 }
177 
178 /* 初始条件: 二叉树T存在,e是T中某个结点 */
179 /* 操作结果: 返回e的右兄弟。若e是T的右孩子或无右兄弟,则返回"空" */
180 TElemType RightSibling(SqBiTree T,TElemType e)
181 { 
182     int i;
183     if(T[0]==Nil) /* 空树 */
184         return Nil;
185     for(i=1;i<=MAX_TREE_SIZE-1;i++)
186         if(T[i]==e&&i%2) /* 找到e且其序号为奇数(是左孩子) */
187             return T[i+1];
188     return Nil; /* 没找到e */
189 }
190 
191 /* PreOrderTraverse()调用 */
192 void PreTraverse(SqBiTree T,int e)
193 { 
194     visit(T[e]);
195     if(T[2*e+1]!=Nil) /* 左子树不空 */
196         PreTraverse(T,2*e+1);
197     if(T[2*e+2]!=Nil) /* 右子树不空 */
198         PreTraverse(T,2*e+2);
199 }
200 
201 /* 初始条件: 二叉树存在 */
202 /* 操作结果: 先序遍历T。 */
203 Status PreOrderTraverse(SqBiTree T)
204 { 
205     if(!BiTreeEmpty(T)) /* 树不空 */
206      PreTraverse(T,0);
207     printf("\n");
208     return OK;
209 }
210 
211 /* InOrderTraverse()调用 */
212 void InTraverse(SqBiTree T,int e)
213 { 
214     if(T[2*e+1]!=Nil) /* 左子树不空 */
215         InTraverse(T,2*e+1);
216     visit(T[e]);
217     if(T[2*e+2]!=Nil) /* 右子树不空 */
218         InTraverse(T,2*e+2);
219 }
220 
221 /* 初始条件: 二叉树存在 */
222 /* 操作结果: 中序遍历T。 */
223 Status InOrderTraverse(SqBiTree T)
224 { 
225     if(!BiTreeEmpty(T)) /* 树不空 */
226         InTraverse(T,0);
227     printf("\n");
228     return OK;
229 }
230 
231 /* PostOrderTraverse()调用 */
232 void PostTraverse(SqBiTree T,int e)
233 { 
234     if(T[2*e+1]!=Nil) /* 左子树不空 */
235         PostTraverse(T,2*e+1);
236     if(T[2*e+2]!=Nil) /* 右子树不空 */
237         PostTraverse(T,2*e+2);
238     visit(T[e]);
239 }
240 
241 /* 初始条件: 二叉树T存在 */
242 /* 操作结果: 后序遍历T。 */
243 Status PostOrderTraverse(SqBiTree T)
244 { 
245     if(!BiTreeEmpty(T)) /* 树不空 */
246         PostTraverse(T,0);
247     printf("\n");
248     return OK;
249 }
250 
251 /* 层序遍历二叉树 */
252 void LevelOrderTraverse(SqBiTree T)
253 { 
254     int i=MAX_TREE_SIZE-1,j;
255     while(T[i]==Nil)
256         i--; /* 找到最后一个非空结点的序号 */
257     for(j=0;j<=i;j++)  /* 从根结点起,按层序遍历二叉树 */
258         if(T[j]!=Nil)
259             visit(T[j]); /* 只遍历非空的结点 */
260     printf("\n");
261 }
262 
263 /* 逐层、按本层序号输出二叉树 */
264 void Print(SqBiTree T)
265 { 
266     int j,k;
267     Position p;
268     TElemType e;
269     for(j=1;j<=BiTreeDepth(T);j++)
270     {
271         printf("第%d层: ",j);
272         for(k=1;k<=powl(2,j-1);k++)
273         {
274             p.level=j;
275             p.order=k;
276             e=Value(T,p);
277             if(e!=Nil)
278                 printf("%d:%d ",k,e);
279         }
280         printf("\n");
281     }
282 }
283 
284 
285 int main()
286 {
287     Status i;
288     Position p;
289     TElemType e;
290     SqBiTree T;
291     InitBiTree(T);
292     CreateBiTree(T);
293     printf("建立二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T));
294     i=Root(T,&e);
295     if(i)
296         printf("二叉树的根为:%d\n",e);
297     else
298         printf("树空,无根\n");
299     printf("层序遍历二叉树:\n");
300     LevelOrderTraverse(T);
301     printf("前序遍历二叉树:\n");
302     PreOrderTraverse(T);
303     printf("中序遍历二叉树:\n");
304     InOrderTraverse(T);
305     printf("后序遍历二叉树:\n");
306     PostOrderTraverse(T);
307     printf("修改结点的层号3本层序号2。");
308     p.level=3;
309     p.order=2;
310     e=Value(T,p);
311     printf("待修改结点的原值为%d请输入新值:50 ",e);
312     e=50;
313     Assign(T,p,e);
314     printf("前序遍历二叉树:\n");
315     PreOrderTraverse(T);
316     printf("结点%d的双亲为%d,左右孩子分别为",e,Parent(T,e));
317     printf("%d,%d,左右兄弟分别为",LeftChild(T,e),RightChild(T,e));
318     printf("%d,%d\n",LeftSibling(T,e),RightSibling(T,e));
319     ClearBiTree(T);
320     printf("清除二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T));
321     i=Root(T,&e);
322     if(i)
323         printf("二叉树的根为:%d\n",e);
324     else
325         printf("树空,无根\n");
326     
327     return 0;
328 }
BiTreeArray.c

  2、二叉树链式结构实现

  1 #include "string.h"
  2 #include "stdio.h"    
  3 #include "stdlib.h"   
  4 #include "io.h"  
  5 #include "math.h"  
  6 #include "time.h"
  7 
  8 #define OK 1
  9 #define ERROR 0
 10 #define TRUE 1
 11 #define FALSE 0
 12 
 13 #define MAXSIZE 100 /* 存储空间初始分配量 */
 14 
 15 typedef int Status;        /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
 16 
 17 /* 用于构造二叉树********************************** */
 18 int index=1;
 19 typedef char String[24]; /*  0号单元存放串的长度 */
 20 String str;
 21 
 22 Status StrAssign(String T,char *chars)
 23 { 
 24     int i;
 25     if(strlen(chars)>MAXSIZE)
 26         return ERROR;
 27     else
 28     {
 29         T[0]=strlen(chars);
 30         for(i=1;i<=T[0];i++)
 31             T[i]=*(chars+i-1);
 32         return OK;
 33     }
 34 }
 35 /* ************************************************ */
 36 
 37 typedef char TElemType;
 38 TElemType Nil=' '; /* 字符型以空格符为空 */
 39 
 40 Status visit(TElemType e)
 41 {
 42     printf("%c ",e);
 43     return OK;
 44 }
 45 
 46 typedef struct BiTNode  /* 结点结构 */
 47 {
 48    TElemType data;        /* 结点数据 */
 49    struct BiTNode *lchild,*rchild; /* 左右孩子指针 */
 50 }BiTNode,*BiTree;
 51 
 52 
 53 /* 构造空二叉树T */
 54 Status InitBiTree(BiTree *T)
 55 { 
 56     *T=NULL;
 57     return OK;
 58 }
 59 
 60 /* 初始条件: 二叉树T存在。操作结果: 销毁二叉树T */
 61 void DestroyBiTree(BiTree *T)
 62 { 
 63     if(*T) 
 64     {
 65         if((*T)->lchild) /* 有左孩子 */
 66             DestroyBiTree(&(*T)->lchild); /* 销毁左孩子子树 */
 67         if((*T)->rchild) /* 有右孩子 */
 68             DestroyBiTree(&(*T)->rchild); /* 销毁右孩子子树 */
 69         free(*T); /* 释放根结点 */
 70         *T=NULL; /* 空指针赋0 */
 71     }
 72 }
 73 
 74 /* 按前序输入二叉树中结点的值(一个字符) */
 75 /* #表示空树,构造二叉链表表示二叉树T。 */
 76 void CreateBiTree(BiTree *T)
 77 { 
 78     TElemType ch;
 79     
 80     /* scanf("%c",&ch); */
 81     ch=str[index++];
 82 
 83     if(ch=='#') 
 84         *T=NULL;
 85     else
 86     {
 87         *T=(BiTree)malloc(sizeof(BiTNode));
 88         if(!*T)
 89             exit(OVERFLOW);
 90         (*T)->data=ch; /* 生成根结点 */
 91         CreateBiTree(&(*T)->lchild); /* 构造左子树 */
 92         CreateBiTree(&(*T)->rchild); /* 构造右子树 */
 93     }
 94  }
 95 
 96 /* 初始条件: 二叉树T存在 */
 97 /* 操作结果: 若T为空二叉树,则返回TRUE,否则FALSE */
 98 Status BiTreeEmpty(BiTree T)
 99 { 
100     if(T)
101         return FALSE;
102     else
103         return TRUE;
104 }
105 
106 #define ClearBiTree DestroyBiTree
107 
108 /* 初始条件: 二叉树T存在。操作结果: 返回T的深度 */
109 int BiTreeDepth(BiTree T)
110 {
111     int i,j;
112     if(!T)
113         return 0;
114     if(T->lchild)
115         i=BiTreeDepth(T->lchild);
116     else
117         i=0;
118     if(T->rchild)
119         j=BiTreeDepth(T->rchild);
120     else
121         j=0;
122     return i>j?i+1:j+1;
123 }
124 
125 /* 初始条件: 二叉树T存在。操作结果: 返回T的根 */
126 TElemType Root(BiTree T)
127 { 
128     if(BiTreeEmpty(T))
129         return Nil;
130     else
131         return T->data;
132 }
133 
134 /* 初始条件: 二叉树T存在,p指向T中某个结点 */
135 /* 操作结果: 返回p所指结点的值 */
136 TElemType Value(BiTree p)
137 {
138     return p->data;
139 }
140 
141 /* 给p所指结点赋值为value */
142 void Assign(BiTree p,TElemType value)
143 {
144     p->data=value;
145 }
146 
147 /* 初始条件: 二叉树T存在 */
148 /* 操作结果: 前序递归遍历T */
149 void PreOrderTraverse(BiTree T)
150 { 
151     if(T==NULL)
152         return;
153     printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
154     PreOrderTraverse(T->lchild); /* 再先序遍历左子树 */
155     PreOrderTraverse(T->rchild); /* 最后先序遍历右子树 */
156 }
157 
158 /* 初始条件: 二叉树T存在 */
159 /* 操作结果: 中序递归遍历T */
160 void InOrderTraverse(BiTree T)
161 { 
162     if(T==NULL)
163         return;
164     InOrderTraverse(T->lchild); /* 中序遍历左子树 */
165     printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
166     InOrderTraverse(T->rchild); /* 最后中序遍历右子树 */
167 }
168 
169 /* 初始条件: 二叉树T存在 */
170 /* 操作结果: 后序递归遍历T */
171 void PostOrderTraverse(BiTree T)
172 {
173     if(T==NULL)
174         return;
175     PostOrderTraverse(T->lchild); /* 先后序遍历左子树  */
176     PostOrderTraverse(T->rchild); /* 再后序遍历右子树  */
177     printf("%c",T->data);/* 显示结点数据,可以更改为其它对结点操作 */
178 }
179 
180 
181 int main()
182 {
183     int i;
184     BiTree T;
185     TElemType e1;
186     InitBiTree(&T);
187 
188     
189     StrAssign(str,"ABDH#K###E##CFI###G#J##");
190 
191     CreateBiTree(&T);
192 
193     printf("构造空二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T));
194     e1=Root(T);
195     printf("二叉树的根为: %c\n",e1);
196 
197     printf("\n前序遍历二叉树:");
198     PreOrderTraverse(T);
199     printf("\n中序遍历二叉树:");
200     InOrderTraverse(T);
201     printf("\n后序遍历二叉树:");
202     PostOrderTraverse(T);
203     ClearBiTree(&T);
204     printf("\n清除二叉树后,树空否?%d(1:是 0:否) 树的深度=%d\n",BiTreeEmpty(T),BiTreeDepth(T));
205     i=Root(T);
206     if(!i)
207         printf("树空,无根\n");
208     
209     return 0;
210 }
BiTreeLink.c

  3、线索二叉树

  1 #include "string.h"
  2 #include "stdio.h"    
  3 #include "stdlib.h"   
  4 #include "io.h"  
  5 #include "math.h"  
  6 #include "time.h"
  7 
  8 #define OK 1
  9 #define ERROR 0
 10 #define TRUE 1
 11 #define FALSE 0
 12 
 13 #define MAXSIZE 100 /* 存储空间初始分配量 */
 14 
 15 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
 16 typedef char TElemType;
 17 typedef enum {Link,Thread} PointerTag;    /* Link==0表示指向左右孩子指针, */
 18                                         /* Thread==1表示指向前驱或后继的线索 */
 19 typedef  struct BiThrNode    /* 二叉线索存储结点结构 */
 20 {
 21     TElemType data;    /* 结点数据 */
 22     struct BiThrNode *lchild, *rchild;    /* 左右孩子指针 */
 23     PointerTag LTag;
 24     PointerTag RTag;        /* 左右标志 */
 25 } BiThrNode, *BiThrTree;
 26 
 27 TElemType Nil='#'; /* 字符型以空格符为空 */
 28 
 29 Status visit(TElemType e)
 30 {
 31     printf("%c ",e);
 32     return OK;
 33 }
 34 
 35 /* 按前序输入二叉线索树中结点的值,构造二叉线索树T */
 36 /* 0(整型)/空格(字符型)表示空结点 */
 37 Status CreateBiThrTree(BiThrTree *T)
 38 { 
 39     TElemType h;
 40     scanf("%c",&h);
 41 
 42     if(h==Nil)
 43         *T=NULL;
 44     else
 45     {
 46         *T=(BiThrTree)malloc(sizeof(BiThrNode));
 47         if(!*T)
 48             exit(OVERFLOW);
 49         (*T)->data=h; /* 生成根结点(前序) */
 50         CreateBiThrTree(&(*T)->lchild); /* 递归构造左子树 */
 51         if((*T)->lchild) /* 有左孩子 */
 52             (*T)->LTag=Link;
 53         CreateBiThrTree(&(*T)->rchild); /* 递归构造右子树 */
 54         if((*T)->rchild) /* 有右孩子 */
 55             (*T)->RTag=Link;
 56     }
 57     return OK;
 58 }
 59 
 60 BiThrTree pre; /* 全局变量,始终指向刚刚访问过的结点 */
 61 /* 中序遍历进行中序线索化 */
 62 void InThreading(BiThrTree p)
 63 { 
 64     if(p)
 65     {
 66         InThreading(p->lchild); /* 递归左子树线索化 */
 67         if(!p->lchild) /* 没有左孩子 */
 68         {
 69             p->LTag=Thread; /* 前驱线索 */
 70             p->lchild=pre; /* 左孩子指针指向前驱 */
 71         }
 72         if(!pre->rchild) /* 前驱没有右孩子 */
 73         {
 74             pre->RTag=Thread; /* 后继线索 */
 75             pre->rchild=p; /* 前驱右孩子指针指向后继(当前结点p) */
 76         }
 77         pre=p; /* 保持pre指向p的前驱 */
 78         InThreading(p->rchild); /* 递归右子树线索化 */
 79     }
 80 }
 81 
 82 /* 中序遍历二叉树T,并将其中序线索化,Thrt指向头结点 */
 83 Status InOrderThreading(BiThrTree *Thrt,BiThrTree T)
 84 { 
 85     *Thrt=(BiThrTree)malloc(sizeof(BiThrNode));
 86     if(!*Thrt)
 87         exit(OVERFLOW);
 88     (*Thrt)->LTag=Link; /* 建头结点 */
 89     (*Thrt)->RTag=Thread;
 90     (*Thrt)->rchild=(*Thrt); /* 右指针回指 */
 91     if(!T) /* 若二叉树空,则左指针回指 */
 92         (*Thrt)->lchild=*Thrt;
 93     else
 94     {
 95         (*Thrt)->lchild=T;
 96         pre=(*Thrt);
 97         InThreading(T); /* 中序遍历进行中序线索化 */
 98         pre->rchild=*Thrt;
 99         pre->RTag=Thread; /* 最后一个结点线索化 */
100         (*Thrt)->rchild=pre;
101     }
102     return OK;
103 }
104 
105 /* 中序遍历二叉线索树T(头结点)的非递归算法 */
106 Status InOrderTraverse_Thr(BiThrTree T)
107 { 
108     BiThrTree p;
109     p=T->lchild; /* p指向根结点 */
110     while(p!=T)
111     { /* 空树或遍历结束时,p==T */
112         while(p->LTag==Link)
113             p=p->lchild;
114         if(!visit(p->data)) /* 访问其左子树为空的结点 */
115             return ERROR;
116         while(p->RTag==Thread&&p->rchild!=T)
117         {
118             p=p->rchild;
119             visit(p->data); /* 访问后继结点 */
120         }
121         p=p->rchild;
122     }
123     return OK;
124 }
125 
126 int main()
127 {
128     BiThrTree H,T;
129     printf("请按前序输入二叉树(如:'ABDH##I##EJ###CF##G##')\n");
130      CreateBiThrTree(&T); /* 按前序产生二叉树 */
131     InOrderThreading(&H,T); /* 中序遍历,并中序线索化二叉树 */
132     printf("中序遍历(输出)二叉线索树:\n");
133     InOrderTraverse_Thr(H); /* 中序遍历(输出)二叉线索树 */
134     printf("\n");
135     
136     return 0;
137 }
ThreadBinaryTree.c

 

五、图

  1、邻接矩阵创建图

 1 #include "stdio.h"    
 2 #include "stdlib.h"   
 3 #include "io.h"  
 4 #include "math.h"  
 5 #include "time.h"
 6 
 7 #define OK 1
 8 #define ERROR 0
 9 #define TRUE 1
10 #define FALSE 0
11 #define MAXVEX 100 /* 最大顶点数,应由用户定义 */
12 #define INFINITY 65535
13 
14 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
15 typedef char VertexType; /* 顶点类型应由用户定义  */
16 typedef int EdgeType; /* 边上的权值类型应由用户定义 */
17 typedef struct
18 {
19     VertexType vexs[MAXVEX]; /* 顶点表 */
20     EdgeType arc[MAXVEX][MAXVEX];/* 邻接矩阵,可看作边表 */
21     int numNodes, numEdges; /* 图中当前的顶点数和边数  */
22 }MGraph;
23 
24 /* 建立无向网图的邻接矩阵表示 */
25 void CreateMGraph(MGraph *G)
26 {
27     int i,j,k,w;
28     printf("输入顶点数和边数:\n");
29     scanf("%d,%d",&G->numNodes,&G->numEdges); /* 输入顶点数和边数 */
30     for(i = 0;i <G->numNodes;i++) /* 读入顶点信息,建立顶点表 */
31         scanf(&G->vexs[i]);
32     for(i = 0;i <G->numNodes;i++)
33         for(j = 0;j <G->numNodes;j++)
34             G->arc[i][j]=INFINITY;    /* 邻接矩阵初始化 */
35     for(k = 0;k <G->numEdges;k++) /* 读入numEdges条边,建立邻接矩阵 */
36     {
37         printf("输入边(vi,vj)上的下标i,下标j和权w:\n");
38         scanf("%d,%d,%d",&i,&j,&w); /* 输入边(vi,vj)上的权w */
39         G->arc[i][j]=w; 
40         G->arc[j][i]= G->arc[i][j]; /* 因为是无向图,矩阵对称 */
41     }
42 }
43 
44 int main(void)
45 {    
46     MGraph G;    
47     CreateMGraph(&G);
48     
49     return 0;
50 }
CreateMGraph.c

  2、邻接表创建图

 1 #include "stdio.h"    
 2 #include "stdlib.h"   
 3 #include "io.h"  
 4 #include "math.h"  
 5 #include "time.h"
 6 
 7 #define OK 1
 8 #define ERROR 0
 9 #define TRUE 1
10 #define FALSE 0
11 #define MAXVEX 100 /* 最大顶点数,应由用户定义 */
12 
13 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
14 typedef char VertexType; /* 顶点类型应由用户定义 */
15 typedef int EdgeType; /* 边上的权值类型应由用户定义 */
16 
17 typedef struct EdgeNode /* 边表结点  */
18 {
19     int adjvex;    /* 邻接点域,存储该顶点对应的下标 */
20     EdgeType info;        /* 用于存储权值,对于非网图可以不需要 */
21     struct EdgeNode *next; /* 链域,指向下一个邻接点 */
22 }EdgeNode;
23 
24 typedef struct VertexNode /* 顶点表结点 */
25 {
26     VertexType data; /* 顶点域,存储顶点信息 */
27     EdgeNode *firstedge;/* 边表头指针 */
28 }VertexNode, AdjList[MAXVEX];
29 
30 typedef struct
31 {
32     AdjList adjList; 
33     int numNodes,numEdges; /* 图中当前顶点数和边数 */
34 }GraphAdjList;
35 
36 /* 建立图的邻接表结构 */
37 void  CreateALGraph(GraphAdjList *G)
38 {
39     int i,j,k;
40     EdgeNode *e;
41     printf("输入顶点数和边数:\n");
42     scanf("%d,%d",&G->numNodes,&G->numEdges); /* 输入顶点数和边数 */
43     for(i = 0;i < G->numNodes;i++) /* 读入顶点信息,建立顶点表 */
44     {
45         scanf(&G->adjList[i].data);     /* 输入顶点信息 */
46         G->adjList[i].firstedge=NULL;     /* 将边表置为空表 */
47     }
48     
49     
50     for(k = 0;k < G->numEdges;k++)/* 建立边表 */
51     {
52         printf("输入边(vi,vj)上的顶点序号:\n");
53         scanf("%d,%d",&i,&j); /* 输入边(vi,vj)上的顶点序号 */
54         e=(EdgeNode *)malloc(sizeof(EdgeNode)); /* 向内存申请空间,生成边表结点 */
55         e->adjvex=j;                    /* 邻接序号为j */                         
56         e->next=G->adjList[i].firstedge;    /* 将e的指针指向当前顶点上指向的结点 */
57         G->adjList[i].firstedge=e;        /* 将当前顶点的指针指向e */               
58         
59         e=(EdgeNode *)malloc(sizeof(EdgeNode)); /* 向内存申请空间,生成边表结点 */
60         e->adjvex=i;                    /* 邻接序号为i */                         
61         e->next=G->adjList[j].firstedge;    /* 将e的指针指向当前顶点上指向的结点 */
62         G->adjList[j].firstedge=e;        /* 将当前顶点的指针指向e */               
63     }
64 }
65 
66 int main(void)
67 {    
68     GraphAdjList G;    
69     CreateALGraph(&G);
70     
71     return 0;
72 }
CreateALGraph.c

  3、邻接矩阵深度和广度遍历

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 
 12 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */  
 13 typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
 14 
 15 typedef char VertexType; /* 顶点类型应由用户定义 */
 16 typedef int EdgeType; /* 边上的权值类型应由用户定义 */
 17 
 18 #define MAXSIZE 9 /* 存储空间初始分配量 */
 19 #define MAXEDGE 15
 20 #define MAXVEX 9
 21 #define INFINITY 65535
 22 
 23 typedef struct
 24 {
 25     VertexType vexs[MAXVEX]; /* 顶点表 */
 26     EdgeType arc[MAXVEX][MAXVEX];/* 邻接矩阵,可看作边表 */
 27     int numVertexes, numEdges; /* 图中当前的顶点数和边数 */ 
 28 }MGraph;
 29 
 30 /* 用到的队列结构与函数********************************** */
 31 
 32 /* 循环队列的顺序存储结构 */
 33 typedef struct
 34 {
 35     int data[MAXSIZE];
 36     int front;        /* 头指针 */
 37     int rear;        /* 尾指针,若队列不空,指向队列尾元素的下一个位置 */
 38 }Queue;
 39 
 40 /* 初始化一个空队列Q */
 41 Status InitQueue(Queue *Q)
 42 {
 43     Q->front=0;
 44     Q->rear=0;
 45     return  OK;
 46 }
 47 
 48 /* 若队列Q为空队列,则返回TRUE,否则返回FALSE */
 49 Status QueueEmpty(Queue Q)
 50 { 
 51     if(Q.front==Q.rear) /* 队列空的标志 */
 52         return TRUE;
 53     else
 54         return FALSE;
 55 }
 56 
 57 /* 若队列未满,则插入元素e为Q新的队尾元素 */
 58 Status EnQueue(Queue *Q,int e)
 59 {
 60     if ((Q->rear+1)%MAXSIZE == Q->front)    /* 队列满的判断 */
 61         return ERROR;
 62     Q->data[Q->rear]=e;            /* 将元素e赋值给队尾 */
 63     Q->rear=(Q->rear+1)%MAXSIZE;/* rear指针向后移一位置, */
 64                                 /* 若到最后则转到数组头部 */
 65     return  OK;
 66 }
 67 
 68 /* 若队列不空,则删除Q中队头元素,用e返回其值 */
 69 Status DeQueue(Queue *Q,int *e)
 70 {
 71     if (Q->front == Q->rear)            /* 队列空的判断 */
 72         return ERROR;
 73     *e=Q->data[Q->front];                /* 将队头元素赋值给e */
 74     Q->front=(Q->front+1)%MAXSIZE;    /* front指针向后移一位置, */
 75                                     /* 若到最后则转到数组头部 */
 76     return  OK;
 77 }
 78 /* ****************************************************** */
 79 
 80 
 81 void CreateMGraph(MGraph *G)
 82 {
 83     int i, j;
 84 
 85     G->numEdges=15;
 86     G->numVertexes=9;
 87 
 88     /* 读入顶点信息,建立顶点表 */
 89     G->vexs[0]='A';
 90     G->vexs[1]='B';
 91     G->vexs[2]='C';
 92     G->vexs[3]='D';
 93     G->vexs[4]='E';
 94     G->vexs[5]='F';
 95     G->vexs[6]='G';
 96     G->vexs[7]='H';
 97     G->vexs[8]='I';
 98 
 99 
100     for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
101     {
102         for ( j = 0; j < G->numVertexes; j++)
103         {
104             G->arc[i][j]=0;
105         }
106     }
107 
108     G->arc[0][1]=1;
109     G->arc[0][5]=1;
110 
111     G->arc[1][2]=1; 
112     G->arc[1][8]=1; 
113     G->arc[1][6]=1; 
114     
115     G->arc[2][3]=1; 
116     G->arc[2][8]=1; 
117     
118     G->arc[3][4]=1;
119     G->arc[3][7]=1;
120     G->arc[3][6]=1;
121     G->arc[3][8]=1;
122 
123     G->arc[4][5]=1;
124     G->arc[4][7]=1;
125 
126     G->arc[5][6]=1; 
127     
128     G->arc[6][7]=1; 
129 
130     
131     for(i = 0; i < G->numVertexes; i++)
132     {
133         for(j = i; j < G->numVertexes; j++)
134         {
135             G->arc[j][i] =G->arc[i][j];
136         }
137     }
138 
139 }
140  
141 Boolean visited[MAXVEX]; /* 访问标志的数组 */
142 
143 /* 邻接矩阵的深度优先递归算法 */
144 void DFS(MGraph G, int i)
145 {
146     int j;
147      visited[i] = TRUE;
148      printf("%c ", G.vexs[i]);/* 打印顶点,也可以其它操作 */
149     for(j = 0; j < G.numVertexes; j++)
150         if(G.arc[i][j] == 1 && !visited[j])
151              DFS(G, j);/* 对为访问的邻接顶点递归调用 */
152 }
153 
154 /* 邻接矩阵的深度遍历操作 */
155 void DFSTraverse(MGraph G)
156 {
157     int i;
158      for(i = 0; i < G.numVertexes; i++)
159          visited[i] = FALSE; /* 初始所有顶点状态都是未访问过状态 */
160     for(i = 0; i < G.numVertexes; i++)
161          if(!visited[i]) /* 对未访问过的顶点调用DFS,若是连通图,只会执行一次 */ 
162             DFS(G, i);
163 }
164 
165 /* 邻接矩阵的广度遍历算法 */
166 void BFSTraverse(MGraph G)
167 {
168     int i, j;
169     Queue Q;
170     for(i = 0; i < G.numVertexes; i++)
171            visited[i] = FALSE;
172     InitQueue(&Q);        /* 初始化一辅助用的队列 */
173     for(i = 0; i < G.numVertexes; i++)  /* 对每一个顶点做循环 */
174     {
175         if (!visited[i])    /* 若是未访问过就处理 */
176         {
177             visited[i]=TRUE;        /* 设置当前顶点访问过 */
178             printf("%c ", G.vexs[i]);/* 打印顶点,也可以其它操作 */
179             EnQueue(&Q,i);        /* 将此顶点入队列 */
180             while(!QueueEmpty(Q))    /* 若当前队列不为空 */
181             {
182                 DeQueue(&Q,&i);    /* 将队对元素出队列,赋值给i */
183                 for(j=0;j<G.numVertexes;j++) 
184                 { 
185                     /* 判断其它顶点若与当前顶点存在边且未访问过  */
186                     if(G.arc[i][j] == 1 && !visited[j]) 
187                     { 
188                          visited[j]=TRUE;            /* 将找到的此顶点标记为已访问 */
189                         printf("%c ", G.vexs[j]);    /* 打印顶点 */
190                         EnQueue(&Q,j);                /* 将找到的此顶点入队列  */
191                     } 
192                 } 
193             }
194         }
195     }
196 }
197 
198 
199 int main(void)
200 {    
201     MGraph G;
202     CreateMGraph(&G);
203     printf("\n深度遍历:");
204     DFSTraverse(G);
205     printf("\n广度遍历:");
206     BFSTraverse(G);
207     return 0;
208 }
DFS_BFS.c

  4、邻接表深度和广度遍历

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 
 12 #define MAXSIZE 9 /* 存储空间初始分配量 */
 13 #define MAXEDGE 15
 14 #define MAXVEX 9
 15 #define INFINITY 65535
 16 
 17 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
 18 typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
 19 
 20 typedef char VertexType; /* 顶点类型应由用户定义 */   
 21 typedef int EdgeType; /* 边上的权值类型应由用户定义 */
 22 
 23 /* 邻接矩阵结构 */
 24 typedef struct
 25 {
 26     VertexType vexs[MAXVEX]; /* 顶点表 */
 27     EdgeType arc[MAXVEX][MAXVEX];/* 邻接矩阵,可看作边表 */
 28     int numVertexes, numEdges; /* 图中当前的顶点数和边数 */ 
 29 }MGraph;
 30 
 31 /* 邻接表结构****************** */
 32 typedef struct EdgeNode /* 边表结点 */ 
 33 {
 34     int adjvex;    /* 邻接点域,存储该顶点对应的下标 */
 35     int weight;        /* 用于存储权值,对于非网图可以不需要 */
 36     struct EdgeNode *next; /* 链域,指向下一个邻接点 */ 
 37 }EdgeNode;
 38 
 39 typedef struct VertexNode /* 顶点表结点 */ 
 40 {
 41     int in;    /* 顶点入度 */
 42     char data; /* 顶点域,存储顶点信息 */
 43     EdgeNode *firstedge;/* 边表头指针 */   
 44 }VertexNode, AdjList[MAXVEX];
 45 
 46 typedef struct
 47 {
 48     AdjList adjList; 
 49     int numVertexes,numEdges; /* 图中当前顶点数和边数 */
 50 }graphAdjList,*GraphAdjList;
 51 /* **************************** */
 52 
 53 /* 用到的队列结构与函数********************************** */
 54 /* 循环队列的顺序存储结构 */
 55 typedef struct
 56 {
 57     int data[MAXSIZE];
 58     int front;        /* 头指针 */
 59     int rear;        /* 尾指针,若队列不空,指向队列尾元素的下一个位置 */
 60 }Queue;
 61 
 62 /* 初始化一个空队列Q */
 63 Status InitQueue(Queue *Q)
 64 {
 65     Q->front=0;
 66     Q->rear=0;
 67     return  OK;
 68 }
 69 
 70 /* 若队列Q为空队列,则返回TRUE,否则返回FALSE */
 71 Status QueueEmpty(Queue Q)
 72 { 
 73     if(Q.front==Q.rear) /* 队列空的标志 */
 74         return TRUE;
 75     else
 76         return FALSE;
 77 }
 78 
 79 /* 若队列未满,则插入元素e为Q新的队尾元素 */
 80 Status EnQueue(Queue *Q,int e)
 81 {
 82     if ((Q->rear+1)%MAXSIZE == Q->front)    /* 队列满的判断 */
 83         return ERROR;
 84     Q->data[Q->rear]=e;            /* 将元素e赋值给队尾 */
 85     Q->rear=(Q->rear+1)%MAXSIZE;/* rear指针向后移一位置, */
 86                                 /* 若到最后则转到数组头部 */
 87     return  OK;
 88 }
 89 
 90 /* 若队列不空,则删除Q中队头元素,用e返回其值 */
 91 Status DeQueue(Queue *Q,int *e)
 92 {
 93     if (Q->front == Q->rear)            /* 队列空的判断 */
 94         return ERROR;
 95     *e=Q->data[Q->front];                /* 将队头元素赋值给e */
 96     Q->front=(Q->front+1)%MAXSIZE;    /* front指针向后移一位置, */
 97                                     /* 若到最后则转到数组头部 */
 98     return  OK;
 99 }
100 /* ****************************************************** */
101 
102 
103 
104 void CreateMGraph(MGraph *G)
105 {
106     int i, j;
107 
108     G->numEdges=15;
109     G->numVertexes=9;
110 
111     /* 读入顶点信息,建立顶点表 */ 
112     G->vexs[0]='A';
113     G->vexs[1]='B';
114     G->vexs[2]='C';
115     G->vexs[3]='D';
116     G->vexs[4]='E';
117     G->vexs[5]='F';
118     G->vexs[6]='G';
119     G->vexs[7]='H';
120     G->vexs[8]='I';
121 
122 
123     for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
124     {
125         for ( j = 0; j < G->numVertexes; j++)
126         {
127             G->arc[i][j]=0;
128         }
129     }
130 
131     G->arc[0][1]=1;
132     G->arc[0][5]=1;
133 
134     G->arc[1][2]=1; 
135     G->arc[1][8]=1; 
136     G->arc[1][6]=1; 
137     
138     G->arc[2][3]=1; 
139     G->arc[2][8]=1; 
140     
141     G->arc[3][4]=1;
142     G->arc[3][7]=1;
143     G->arc[3][6]=1;
144     G->arc[3][8]=1;
145 
146     G->arc[4][5]=1;
147     G->arc[4][7]=1;
148 
149     G->arc[5][6]=1; 
150     
151     G->arc[6][7]=1; 
152 
153     
154     for(i = 0; i < G->numVertexes; i++)
155     {
156         for(j = i; j < G->numVertexes; j++)
157         {
158             G->arc[j][i] =G->arc[i][j];
159         }
160     }
161 
162 }
163  
164 /* 利用邻接矩阵构建邻接表 */
165 void CreateALGraph(MGraph G,GraphAdjList *GL)
166 {
167     int i,j;
168     EdgeNode *e;
169 
170     *GL = (GraphAdjList)malloc(sizeof(graphAdjList));
171 
172     (*GL)->numVertexes=G.numVertexes;
173     (*GL)->numEdges=G.numEdges;
174     for(i= 0;i <G.numVertexes;i++) /* 读入顶点信息,建立顶点表 */   
175     {
176         (*GL)->adjList[i].in=0;
177         (*GL)->adjList[i].data=G.vexs[i];
178         (*GL)->adjList[i].firstedge=NULL;     /* 将边表置为空表 */
179     }
180     
181     for(i=0;i<G.numVertexes;i++) /* 建立边表 */
182     { 
183         for(j=0;j<G.numVertexes;j++)
184         {
185             if (G.arc[i][j]==1)
186             {
187                 e=(EdgeNode *)malloc(sizeof(EdgeNode));
188                 e->adjvex=j;                    /* 邻接序号为j */                         
189                 e->next=(*GL)->adjList[i].firstedge;    /* 将当前顶点上的指向的结点指针赋值给e */
190                 (*GL)->adjList[i].firstedge=e;        /* 将当前顶点的指针指向e */   
191                 (*GL)->adjList[j].in++;
192                 
193             }
194         }
195     }
196     
197 }
198 
199 Boolean visited[MAXSIZE]; /* 访问标志的数组 */
200 
201 /* 邻接表的深度优先递归算法 */
202 void DFS(GraphAdjList GL, int i)
203 {
204     EdgeNode *p;
205      visited[i] = TRUE;
206      printf("%c ",GL->adjList[i].data);/* 打印顶点,也可以其它操作 */
207     p = GL->adjList[i].firstedge;
208     while(p)
209     {
210          if(!visited[p->adjvex])
211              DFS(GL, p->adjvex);/* 对为访问的邻接顶点递归调用 */
212         p = p->next;
213      }
214 }
215 
216 /* 邻接表的深度遍历操作 */
217 void DFSTraverse(GraphAdjList GL)
218 {
219     int i;
220      for(i = 0; i < GL->numVertexes; i++)
221          visited[i] = FALSE; /* 初始所有顶点状态都是未访问过状态 */
222     for(i = 0; i < GL->numVertexes; i++)
223          if(!visited[i]) /* 对未访问过的顶点调用DFS,若是连通图,只会执行一次 */ 
224             DFS(GL, i);
225 }
226 
227 /* 邻接表的广度遍历算法 */
228 void BFSTraverse(GraphAdjList GL)
229 {
230     int i;
231     EdgeNode *p;
232     Queue Q;
233     for(i = 0; i < GL->numVertexes; i++)
234            visited[i] = FALSE;
235     InitQueue(&Q);
236        for(i = 0; i < GL->numVertexes; i++)
237        {
238         if (!visited[i])
239         {
240             visited[i]=TRUE;
241             printf("%c ",GL->adjList[i].data);/* 打印顶点,也可以其它操作 */
242             EnQueue(&Q,i);
243             while(!QueueEmpty(Q))
244             {
245                 DeQueue(&Q,&i);
246                 p = GL->adjList[i].firstedge;    /* 找到当前顶点的边表链表头指针 */
247                 while(p)
248                 {
249                     if(!visited[p->adjvex])    /* 若此顶点未被访问 */
250                      {
251                          visited[p->adjvex]=TRUE;
252                         printf("%c ",GL->adjList[p->adjvex].data);
253                         EnQueue(&Q,p->adjvex);    /* 将此顶点入队列 */
254                     }
255                     p = p->next;    /* 指针指向下一个邻接点 */
256                 }
257             }
258         }
259     }
260 }
261 
262 int main(void)
263 {    
264     MGraph G;  
265     GraphAdjList GL;    
266     CreateMGraph(&G);
267     CreateALGraph(G,&GL);
268 
269     printf("\n深度遍历:");
270     DFSTraverse(GL);
271     printf("\n广度遍历:");
272     BFSTraverse(GL);
273     return 0;
274 }
DFS_BFS.c

  5、最小生成树

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 
 12 #define MAXEDGE 20
 13 #define MAXVEX 20
 14 #define INFINITY 65535
 15 
 16 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
 17 
 18 typedef struct
 19 {
 20     int arc[MAXVEX][MAXVEX];
 21     int numVertexes, numEdges;
 22 }MGraph;
 23 
 24 void CreateMGraph(MGraph *G)/* 构件图 */
 25 {
 26     int i, j;
 27 
 28     /* printf("请输入边数和顶点数:"); */
 29     G->numEdges=15;
 30     G->numVertexes=9;
 31 
 32     for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
 33     {
 34         for ( j = 0; j < G->numVertexes; j++)
 35         {
 36             if (i==j)
 37                 G->arc[i][j]=0;
 38             else
 39                 G->arc[i][j] = G->arc[j][i] = INFINITY;
 40         }
 41     }
 42 
 43     G->arc[0][1]=10;
 44     G->arc[0][5]=11; 
 45     G->arc[1][2]=18; 
 46     G->arc[1][8]=12; 
 47     G->arc[1][6]=16; 
 48     G->arc[2][8]=8; 
 49     G->arc[2][3]=22; 
 50     G->arc[3][8]=21; 
 51     G->arc[3][6]=24; 
 52     G->arc[3][7]=16;
 53     G->arc[3][4]=20;
 54     G->arc[4][7]=7; 
 55     G->arc[4][5]=26; 
 56     G->arc[5][6]=17; 
 57     G->arc[6][7]=19; 
 58 
 59     for(i = 0; i < G->numVertexes; i++)
 60     {
 61         for(j = i; j < G->numVertexes; j++)
 62         {
 63             G->arc[j][i] =G->arc[i][j];
 64         }
 65     }
 66 
 67 }
 68 
 69 /* Prim算法生成最小生成树  */
 70 void MiniSpanTree_Prim(MGraph G)
 71 {
 72     int min, i, j, k;
 73     int adjvex[MAXVEX];        /* 保存相关顶点下标 */
 74     int lowcost[MAXVEX];    /* 保存相关顶点间边的权值 */
 75     lowcost[0] = 0;/* 初始化第一个权值为0,即v0加入生成树 */
 76             /* lowcost的值为0,在这里就是此下标的顶点已经加入生成树 */
 77     adjvex[0] = 0;            /* 初始化第一个顶点下标为0 */
 78     for(i = 1; i < G.numVertexes; i++)    /* 循环除下标为0外的全部顶点 */
 79     {
 80         lowcost[i] = G.arc[0][i];    /* 将v0顶点与之有边的权值存入数组 */
 81         adjvex[i] = 0;                    /* 初始化都为v0的下标 */
 82     }
 83     for(i = 1; i < G.numVertexes; i++)
 84     {
 85         min = INFINITY;    /* 初始化最小权值为∞, */
 86                         /* 通常设置为不可能的大数字如32767、65535等 */
 87         j = 1;k = 0;
 88         while(j < G.numVertexes)    /* 循环全部顶点 */
 89         {
 90             if(lowcost[j]!=0 && lowcost[j] < min)/* 如果权值不为0且权值小于min */
 91             {    
 92                 min = lowcost[j];    /* 则让当前权值成为最小值 */
 93                 k = j;            /* 将当前最小值的下标存入k */
 94             }
 95             j++;
 96         }
 97         printf("(%d, %d)\n", adjvex[k], k);/* 打印当前顶点边中权值最小的边 */
 98         lowcost[k] = 0;/* 将当前顶点的权值设置为0,表示此顶点已经完成任务 */
 99         for(j = 1; j < G.numVertexes; j++)    /* 循环所有顶点 */
100         {
101             if(lowcost[j]!=0 && G.arc[k][j] < lowcost[j]) 
102             {/* 如果下标为k顶点各边权值小于此前这些顶点未被加入生成树权值 */
103                 lowcost[j] = G.arc[k][j];/* 将较小的权值存入lowcost相应位置 */
104                 adjvex[j] = k;                /* 将下标为k的顶点存入adjvex */
105             }
106         }
107     }
108 }
109 
110 int main(void)
111 {
112     MGraph G;
113     CreateMGraph(&G);
114     MiniSpanTree_Prim(G);
115   
116     return 0;
117  
118 }
Prim.c

  6、最小生成树

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 
 12 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
 13 
 14 #define MAXEDGE 20
 15 #define MAXVEX 20
 16 #define INFINITY 65535
 17 
 18 typedef struct
 19 {
 20     int arc[MAXVEX][MAXVEX];
 21     int numVertexes, numEdges;
 22 }MGraph;
 23 
 24 typedef struct
 25 {
 26     int begin;
 27     int end;
 28     int weight;
 29 }Edge;   /* 对边集数组Edge结构的定义 */
 30 
 31 /* 构件图 */
 32 void CreateMGraph(MGraph *G)
 33 {
 34     int i, j;
 35 
 36     /* printf("请输入边数和顶点数:"); */
 37     G->numEdges=15;
 38     G->numVertexes=9;
 39 
 40     for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
 41     {
 42         for ( j = 0; j < G->numVertexes; j++)
 43         {
 44             if (i==j)
 45                 G->arc[i][j]=0;
 46             else
 47                 G->arc[i][j] = G->arc[j][i] = INFINITY;
 48         }
 49     }
 50 
 51     G->arc[0][1]=10;
 52     G->arc[0][5]=11; 
 53     G->arc[1][2]=18; 
 54     G->arc[1][8]=12; 
 55     G->arc[1][6]=16; 
 56     G->arc[2][8]=8; 
 57     G->arc[2][3]=22; 
 58     G->arc[3][8]=21; 
 59     G->arc[3][6]=24; 
 60     G->arc[3][7]=16;
 61     G->arc[3][4]=20;
 62     G->arc[4][7]=7; 
 63     G->arc[4][5]=26; 
 64     G->arc[5][6]=17; 
 65     G->arc[6][7]=19; 
 66 
 67     for(i = 0; i < G->numVertexes; i++)
 68     {
 69         for(j = i; j < G->numVertexes; j++)
 70         {
 71             G->arc[j][i] =G->arc[i][j];
 72         }
 73     }
 74 
 75 }
 76 
 77 /* 交换权值 以及头和尾 */
 78 void Swapn(Edge *edges,int i, int j)
 79 {
 80     int temp;
 81     temp = edges[i].begin;
 82     edges[i].begin = edges[j].begin;
 83     edges[j].begin = temp;
 84     temp = edges[i].end;
 85     edges[i].end = edges[j].end;
 86     edges[j].end = temp;
 87     temp = edges[i].weight;
 88     edges[i].weight = edges[j].weight;
 89     edges[j].weight = temp;
 90 }
 91 
 92 /* 对权值进行排序 */
 93 void sort(Edge edges[],MGraph *G)
 94 {
 95     int i, j;
 96     for ( i = 0; i < G->numEdges; i++)
 97     {
 98         for ( j = i + 1; j < G->numEdges; j++)
 99         {
100             if (edges[i].weight > edges[j].weight)
101             {
102                 Swapn(edges, i, j);
103             }
104         }
105     }
106     printf("权排序之后的为:\n");
107     for (i = 0; i < G->numEdges; i++)
108     {
109         printf("(%d, %d) %d\n", edges[i].begin, edges[i].end, edges[i].weight);
110     }
111 
112 }
113 
114 /* 查找连线顶点的尾部下标 */
115 int Find(int *parent, int f)
116 {
117     while ( parent[f] > 0)
118     {
119         f = parent[f];
120     }
121     return f;
122 }
123 
124 /* 生成最小生成树 */
125 void MiniSpanTree_Kruskal(MGraph G)
126 {
127     int i, j, n, m;
128     int k = 0;
129     int parent[MAXVEX];/* 定义一数组用来判断边与边是否形成环路 */
130     
131     Edge edges[MAXEDGE];/* 定义边集数组,edge的结构为begin,end,weight,均为整型 */
132 
133     /* 用来构建边集数组并排序********************* */
134     for ( i = 0; i < G.numVertexes-1; i++)
135     {
136         for (j = i + 1; j < G.numVertexes; j++)
137         {
138             if (G.arc[i][j]<INFINITY)
139             {
140                 edges[k].begin = i;
141                 edges[k].end = j;
142                 edges[k].weight = G.arc[i][j];
143                 k++;
144             }
145         }
146     }
147     sort(edges, &G);
148     /* ******************************************* */
149 
150 
151     for (i = 0; i < G.numVertexes; i++)
152         parent[i] = 0;    /* 初始化数组值为0 */
153 
154     printf("打印最小生成树:\n");
155     for (i = 0; i < G.numEdges; i++)    /* 循环每一条边 */
156     {
157         n = Find(parent,edges[i].begin);
158         m = Find(parent,edges[i].end);
159         if (n != m) /* 假如n与m不等,说明此边没有与现有的生成树形成环路 */
160         {
161             parent[n] = m;    /* 将此边的结尾顶点放入下标为起点的parent中。 */
162                             /* 表示此顶点已经在生成树集合中 */
163             printf("(%d, %d) %d\n", edges[i].begin, edges[i].end, edges[i].weight);
164         }
165     }
166 }
167 
168 int main(void)
169 {
170     MGraph G;
171     CreateMGraph(&G);
172     MiniSpanTree_Kruskal(G);
173     return 0;
174 }
Kruskal.c

  7、最短路径

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 
 12 #define MAXEDGE 20
 13 #define MAXVEX 20
 14 #define INFINITY 65535
 15 
 16 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */ 
 17 
 18 
 19 typedef struct
 20 {
 21     int vexs[MAXVEX];
 22     int arc[MAXVEX][MAXVEX];
 23     int numVertexes, numEdges;
 24 }MGraph;
 25 
 26 typedef int Patharc[MAXVEX];    /* 用于存储最短路径下标的数组 */
 27 typedef int ShortPathTable[MAXVEX];/* 用于存储到各点最短路径的权值和 */
 28 
 29 /* 构件图 */
 30 void CreateMGraph(MGraph *G)
 31 {
 32     int i, j;
 33 
 34     /* printf("请输入边数和顶点数:"); */
 35     G->numEdges=16;
 36     G->numVertexes=9;
 37 
 38     for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
 39     {
 40         G->vexs[i]=i;
 41     }
 42 
 43     for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
 44     {
 45         for ( j = 0; j < G->numVertexes; j++)
 46         {
 47             if (i==j)
 48                 G->arc[i][j]=0;
 49             else
 50                 G->arc[i][j] = G->arc[j][i] = INFINITY;
 51         }
 52     }
 53 
 54     G->arc[0][1]=1;
 55     G->arc[0][2]=5; 
 56     G->arc[1][2]=3; 
 57     G->arc[1][3]=7; 
 58     G->arc[1][4]=5; 
 59 
 60     G->arc[2][4]=1; 
 61     G->arc[2][5]=7; 
 62     G->arc[3][4]=2; 
 63     G->arc[3][6]=3; 
 64     G->arc[4][5]=3;
 65 
 66     G->arc[4][6]=6;
 67     G->arc[4][7]=9; 
 68     G->arc[5][7]=5; 
 69     G->arc[6][7]=2; 
 70     G->arc[6][8]=7;
 71 
 72     G->arc[7][8]=4;
 73 
 74 
 75     for(i = 0; i < G->numVertexes; i++)
 76     {
 77         for(j = i; j < G->numVertexes; j++)
 78         {
 79             G->arc[j][i] =G->arc[i][j];
 80         }
 81     }
 82 
 83 }
 84 
 85 /*  Dijkstra算法,求有向网G的v0顶点到其余顶点v的最短路径P[v]及带权长度D[v] */    
 86 /*  P[v]的值为前驱顶点下标,D[v]表示v0到v的最短路径长度和 */  
 87 void ShortestPath_Dijkstra(MGraph G, int v0, Patharc *P, ShortPathTable *D)
 88 {    
 89     int v,w,k,min;    
 90     int final[MAXVEX];/* final[w]=1表示求得顶点v0至vw的最短路径 */
 91     for(v=0; v<G.numVertexes; v++)    /* 初始化数据 */
 92     {        
 93         final[v] = 0;            /* 全部顶点初始化为未知最短路径状态 */
 94         (*D)[v] = G.arc[v0][v];/* 将与v0点有连线的顶点加上权值 */
 95         (*P)[v] = -1;                /* 初始化路径数组P为-1  */       
 96     }
 97 
 98     (*D)[v0] = 0;  /* v0至v0路径为0 */  
 99     final[v0] = 1;    /* v0至v0不需要求路径 */        
100     /* 开始主循环,每次求得v0到某个v顶点的最短路径 */   
101     for(v=1; v<G.numVertexes; v++)   
102     {
103         min=INFINITY;    /* 当前所知离v0顶点的最近距离 */        
104         for(w=0; w<G.numVertexes; w++) /* 寻找离v0最近的顶点 */    
105         {            
106             if(!final[w] && (*D)[w]<min)             
107             {                   
108                 k=w;                    
109                 min = (*D)[w];    /* w顶点离v0顶点更近 */            
110             }        
111         }        
112         final[k] = 1;    /* 将目前找到的最近的顶点置为1 */
113         for(w=0; w<G.numVertexes; w++) /* 修正当前最短路径及距离 */
114         {
115             /* 如果经过v顶点的路径比现在这条路径的长度短的话 */
116             if(!final[w] && (min+G.arc[k][w]<(*D)[w]))   
117             { /*  说明找到了更短的路径,修改D[w]和P[w] */
118                 (*D)[w] = min + G.arc[k][w];  /* 修改当前路径长度 */               
119                 (*P)[w]=k;        
120             }       
121         }   
122     }
123 }
124 
125 int main(void)
126 {   
127     int i,j,v0;
128     MGraph G;    
129     Patharc P;    
130     ShortPathTable D; /* 求某点到其余各点的最短路径 */   
131     v0=0;
132     
133     CreateMGraph(&G);
134     
135     ShortestPath_Dijkstra(G, v0, &P, &D);  
136 
137     printf("最短路径倒序如下:\n");    
138     for(i=1;i<G.numVertexes;++i)   
139     {       
140         printf("v%d - v%d : ",v0,i);
141         j=i;
142         while(P[j]!=-1)
143         {
144             printf("%d ",P[j]);
145             j=P[j];
146         }
147         printf("\n");
148     }    
149     printf("\n源点到各顶点的最短路径长度为:\n");  
150     for(i=1;i<G.numVertexes;++i)        
151         printf("v%d - v%d : %d \n",G.vexs[0],G.vexs[i],D[i]);     
152     return 0;
153 }
Dijkstra.c

  8、最短路径

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 #define MAXEDGE 20
 12 #define MAXVEX 20
 13 #define INFINITY 65535
 14 
 15 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
 16 
 17 typedef struct
 18 {
 19     int vexs[MAXVEX];
 20     int arc[MAXVEX][MAXVEX];
 21     int numVertexes, numEdges;
 22 }MGraph;
 23 
 24 typedef int Patharc[MAXVEX][MAXVEX];
 25 typedef int ShortPathTable[MAXVEX][MAXVEX];
 26 
 27 /* 构件图 */
 28 void CreateMGraph(MGraph *G)
 29 {
 30     int i, j;
 31 
 32     /* printf("请输入边数和顶点数:"); */
 33     G->numEdges=16;
 34     G->numVertexes=9;
 35 
 36     for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
 37     {
 38         G->vexs[i]=i;
 39     }
 40 
 41     for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
 42     {
 43         for ( j = 0; j < G->numVertexes; j++)
 44         {
 45             if (i==j)
 46                 G->arc[i][j]=0;
 47             else
 48                 G->arc[i][j] = G->arc[j][i] = INFINITY;
 49         }
 50     }
 51 
 52     G->arc[0][1]=1;
 53     G->arc[0][2]=5; 
 54     G->arc[1][2]=3; 
 55     G->arc[1][3]=7; 
 56     G->arc[1][4]=5; 
 57 
 58     G->arc[2][4]=1; 
 59     G->arc[2][5]=7; 
 60     G->arc[3][4]=2; 
 61     G->arc[3][6]=3; 
 62     G->arc[4][5]=3;
 63 
 64     G->arc[4][6]=6;
 65     G->arc[4][7]=9; 
 66     G->arc[5][7]=5; 
 67     G->arc[6][7]=2; 
 68     G->arc[6][8]=7;
 69 
 70     G->arc[7][8]=4;
 71 
 72 
 73     for(i = 0; i < G->numVertexes; i++)
 74     {
 75         for(j = i; j < G->numVertexes; j++)
 76         {
 77             G->arc[j][i] =G->arc[i][j];
 78         }
 79     }
 80 
 81 }
 82 
 83 /* Floyd算法,求网图G中各顶点v到其余顶点w的最短路径P[v][w]及带权长度D[v][w]。 */    
 84 void ShortestPath_Floyd(MGraph G, Patharc *P, ShortPathTable *D)
 85 {    
 86     int v,w,k;    
 87     for(v=0; v<G.numVertexes; ++v) /* 初始化D与P */  
 88     {        
 89         for(w=0; w<G.numVertexes; ++w)  
 90         {
 91             (*D)[v][w]=G.arc[v][w];    /* D[v][w]值即为对应点间的权值 */
 92             (*P)[v][w]=w;                /* 初始化P */
 93         }
 94     }
 95     for(k=0; k<G.numVertexes; ++k)   
 96     {
 97         for(v=0; v<G.numVertexes; ++v)  
 98         {        
 99             for(w=0; w<G.numVertexes; ++w)    
100             {
101                 if ((*D)[v][w]>(*D)[v][k]+(*D)[k][w])
102                 {/* 如果经过下标为k顶点路径比原两点间路径更短 */
103                     (*D)[v][w]=(*D)[v][k]+(*D)[k][w];/* 将当前两点间权值设为更小的一个 */
104                     (*P)[v][w]=(*P)[v][k];/* 路径设置为经过下标为k的顶点 */
105                 }
106             }
107         }
108     }
109 }
110 
111 int main(void)
112 {    
113     int v,w,k;  
114     MGraph G;    
115     
116     Patharc P;    
117     ShortPathTable D; /* 求某点到其余各点的最短路径 */   
118     
119     CreateMGraph(&G);
120     
121     ShortestPath_Floyd(G,&P,&D);  
122 
123     printf("各顶点间最短路径如下:\n");    
124     for(v=0; v<G.numVertexes; ++v)   
125     {        
126         for(w=v+1; w<G.numVertexes; w++)  
127         {
128             printf("v%d-v%d weight: %d ",v,w,D[v][w]);
129             k=P[v][w];                /* 获得第一个路径顶点下标 */
130             printf(" path: %d",v);    /* 打印源点 */
131             while(k!=w)                /* 如果路径顶点下标不是终点 */
132             {
133                 printf(" -> %d",k);    /* 打印路径顶点 */
134                 k=P[k][w];            /* 获得下一个路径顶点下标 */
135             }
136             printf(" -> %d\n",w);    /* 打印终点 */
137         }
138         printf("\n");
139     }
140 
141     printf("最短路径D\n");
142     for(v=0; v<G.numVertexes; ++v)  
143     {        
144         for(w=0; w<G.numVertexes; ++w)    
145         {
146             printf("%d\t",D[v][w]);
147         }
148         printf("\n");
149     }
150     printf("最短路径P\n");
151     for(v=0; v<G.numVertexes; ++v)  
152     {        
153         for(w=0; w<G.numVertexes; ++w)    
154         {
155             printf("%d ",P[v][w]);
156         }
157         printf("\n");
158     }
159 
160     return 0;
161 }
Floyd.c

  9、拓扑排序

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 #define MAXEDGE 20
 12 #define MAXVEX 14
 13 #define INFINITY 65535
 14 
 15 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
 16 
 17 /* 邻接矩阵结构 */
 18 typedef struct
 19 {
 20     int vexs[MAXVEX];
 21     int arc[MAXVEX][MAXVEX];
 22     int numVertexes, numEdges;
 23 }MGraph;
 24 
 25 /* 邻接表结构****************** */
 26 typedef struct EdgeNode /* 边表结点  */
 27 {
 28     int adjvex;    /* 邻接点域,存储该顶点对应的下标 */
 29     int weight;        /* 用于存储权值,对于非网图可以不需要 */
 30     struct EdgeNode *next; /* 链域,指向下一个邻接点 */
 31 }EdgeNode;
 32 
 33 typedef struct VertexNode /* 顶点表结点 */
 34 {
 35     int in;    /* 顶点入度 */
 36     int data; /* 顶点域,存储顶点信息 */
 37     EdgeNode *firstedge;/* 边表头指针 */
 38 }VertexNode, AdjList[MAXVEX];
 39 
 40 typedef struct
 41 {
 42     AdjList adjList; 
 43     int numVertexes,numEdges; /* 图中当前顶点数和边数 */
 44 }graphAdjList,*GraphAdjList;
 45 /* **************************** */
 46 
 47 
 48 void CreateMGraph(MGraph *G)/* 构件图 */
 49 {
 50     int i, j;
 51     
 52     /* printf("请输入边数和顶点数:"); */
 53     G->numEdges=MAXEDGE;
 54     G->numVertexes=MAXVEX;
 55 
 56     for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
 57     {
 58         G->vexs[i]=i;
 59     }
 60 
 61     for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
 62     {
 63         for ( j = 0; j < G->numVertexes; j++)
 64         {
 65             G->arc[i][j]=0;
 66         }
 67     }
 68 
 69     G->arc[0][4]=1;
 70     G->arc[0][5]=1; 
 71     G->arc[0][11]=1; 
 72     G->arc[1][2]=1; 
 73     G->arc[1][4]=1; 
 74     G->arc[1][8]=1; 
 75     G->arc[2][5]=1; 
 76     G->arc[2][6]=1;
 77     G->arc[2][9]=1;
 78     G->arc[3][2]=1; 
 79     G->arc[3][13]=1;
 80     G->arc[4][7]=1;
 81     G->arc[5][8]=1;
 82     G->arc[5][12]=1; 
 83     G->arc[6][5]=1; 
 84     G->arc[8][7]=1;
 85     G->arc[9][10]=1;
 86     G->arc[9][11]=1;
 87     G->arc[10][13]=1;
 88     G->arc[12][9]=1;
 89 
 90 }
 91 
 92 /* 利用邻接矩阵构建邻接表 */
 93 void CreateALGraph(MGraph G,GraphAdjList *GL)
 94 {
 95     int i,j;
 96     EdgeNode *e;
 97 
 98     *GL = (GraphAdjList)malloc(sizeof(graphAdjList));
 99 
100     (*GL)->numVertexes=G.numVertexes;
101     (*GL)->numEdges=G.numEdges;
102     for(i= 0;i <G.numVertexes;i++) /* 读入顶点信息,建立顶点表 */
103     {
104         (*GL)->adjList[i].in=0;
105         (*GL)->adjList[i].data=G.vexs[i];
106         (*GL)->adjList[i].firstedge=NULL;     /* 将边表置为空表 */
107     }
108     
109     for(i=0;i<G.numVertexes;i++) /* 建立边表 */
110     { 
111         for(j=0;j<G.numVertexes;j++)
112         {
113             if (G.arc[i][j]==1)
114             {
115                 e=(EdgeNode *)malloc(sizeof(EdgeNode));
116                 e->adjvex=j;                    /* 邻接序号为j  */                        
117                 e->next=(*GL)->adjList[i].firstedge;    /* 将当前顶点上的指向的结点指针赋值给e */
118                 (*GL)->adjList[i].firstedge=e;        /* 将当前顶点的指针指向e  */  
119                 (*GL)->adjList[j].in++;
120                 
121             }
122         }
123     }
124     
125 }
126 
127 
128 /* 拓扑排序,若GL无回路,则输出拓扑排序序列并返回1,若有回路返回0。 */
129 Status TopologicalSort(GraphAdjList GL)
130 {    
131     EdgeNode *e;    
132     int i,k,gettop;   
133     int top=0;  /* 用于栈指针下标  */
134     int count=0;/* 用于统计输出顶点的个数  */    
135     int *stack;    /* 建栈将入度为0的顶点入栈  */   
136     stack=(int *)malloc(GL->numVertexes * sizeof(int) );    
137 
138     for(i = 0; i<GL->numVertexes; i++)                
139         if(0 == GL->adjList[i].in) /* 将入度为0的顶点入栈 */         
140             stack[++top]=i;    
141     while(top!=0)    
142     {        
143         gettop=stack[top--];        
144         printf("%d -> ",GL->adjList[gettop].data);        
145         count++;        /* 输出i号顶点,并计数 */        
146         for(e = GL->adjList[gettop].firstedge; e; e = e->next)        
147         {            
148             k=e->adjvex;            
149             if( !(--GL->adjList[k].in) )  /* 将i号顶点的邻接点的入度减1,如果减1后为0,则入栈 */                
150                 stack[++top]=k;        
151         }
152     }   
153     printf("\n");   
154     if(count < GL->numVertexes)        
155         return ERROR;    
156     else       
157         return OK;
158 }
159 
160 
161 int main(void)
162 {    
163     MGraph G;  
164     GraphAdjList GL; 
165     int result;   
166     CreateMGraph(&G);
167     CreateALGraph(G,&GL);
168     result=TopologicalSort(GL);
169     printf("result:%d",result);
170 
171     return 0;
172 }
TopologicaSort.c

  10、关键路径

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 
 12 #define MAXEDGE 30
 13 #define MAXVEX 30
 14 #define INFINITY 65535
 15 
 16 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */  
 17 
 18 int *etv,*ltv; /* 事件最早发生时间和最迟发生时间数组,全局变量 */
 19 int *stack2;   /* 用于存储拓扑序列的栈 */
 20 int top2;       /* 用于stack2的指针 */
 21 
 22 /* 邻接矩阵结构 */
 23 typedef struct
 24 {
 25     int vexs[MAXVEX];
 26     int arc[MAXVEX][MAXVEX];
 27     int numVertexes, numEdges;
 28 }MGraph;
 29 
 30 /* 邻接表结构****************** */
 31 typedef struct EdgeNode /* 边表结点  */
 32 {
 33     int adjvex;    /* 邻接点域,存储该顶点对应的下标 */
 34     int weight;        /* 用于存储权值,对于非网图可以不需要 */
 35     struct EdgeNode *next; /* 链域,指向下一个邻接点 */
 36 }EdgeNode;
 37 
 38 typedef struct VertexNode /* 顶点表结点 */
 39 {
 40     int in;    /* 顶点入度 */
 41     int data; /* 顶点域,存储顶点信息 */
 42     EdgeNode *firstedge;/* 边表头指针 */
 43 }VertexNode, AdjList[MAXVEX];
 44 
 45 typedef struct
 46 {
 47     AdjList adjList; 
 48     int numVertexes,numEdges; /* 图中当前顶点数和边数 */
 49 }graphAdjList,*GraphAdjList;
 50 /* **************************** */
 51 
 52 
 53 void CreateMGraph(MGraph *G)/* 构件图 */
 54 {
 55     int i, j;
 56     /* printf("请输入边数和顶点数:"); */
 57     G->numEdges=13;
 58     G->numVertexes=10;
 59 
 60     for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
 61     {
 62         G->vexs[i]=i;
 63     }
 64 
 65     for (i = 0; i < G->numVertexes; i++)/* 初始化图 */
 66     {
 67         for ( j = 0; j < G->numVertexes; j++)
 68         {
 69             if (i==j)
 70                 G->arc[i][j]=0;
 71             else
 72                 G->arc[i][j]=INFINITY;
 73         }
 74     }
 75 
 76     G->arc[0][1]=3;
 77     G->arc[0][2]=4; 
 78     G->arc[1][3]=5; 
 79     G->arc[1][4]=6; 
 80     G->arc[2][3]=8; 
 81     G->arc[2][5]=7; 
 82     G->arc[3][4]=3;
 83     G->arc[4][6]=9; 
 84     G->arc[4][7]=4;
 85     G->arc[5][7]=6; 
 86     G->arc[6][9]=2;
 87     G->arc[7][8]=5;
 88     G->arc[8][9]=3;
 89 
 90 }
 91 
 92 /* 利用邻接矩阵构建邻接表 */
 93 void CreateALGraph(MGraph G,GraphAdjList *GL)
 94 {
 95     int i,j;
 96     EdgeNode *e;
 97 
 98     *GL = (GraphAdjList)malloc(sizeof(graphAdjList));
 99 
100     (*GL)->numVertexes=G.numVertexes;
101     (*GL)->numEdges=G.numEdges;
102     for(i= 0;i <G.numVertexes;i++) /* 读入顶点信息,建立顶点表 */
103     {
104         (*GL)->adjList[i].in=0;
105         (*GL)->adjList[i].data=G.vexs[i];
106         (*GL)->adjList[i].firstedge=NULL;     /* 将边表置为空表 */
107     }
108     
109     for(i=0;i<G.numVertexes;i++) /* 建立边表 */
110     { 
111         for(j=0;j<G.numVertexes;j++)
112         {
113             if (G.arc[i][j]!=0 && G.arc[i][j]<INFINITY)
114             {
115                 e=(EdgeNode *)malloc(sizeof(EdgeNode));
116                 e->adjvex=j;                    /* 邻接序号为j */   
117                 e->weight=G.arc[i][j];
118                 e->next=(*GL)->adjList[i].firstedge;    /* 将当前顶点上的指向的结点指针赋值给e */
119                 (*GL)->adjList[i].firstedge=e;        /* 将当前顶点的指针指向e  */  
120                 (*GL)->adjList[j].in++;
121                 
122             }
123         }
124     }
125     
126 }
127 
128 
129 /* 拓扑排序 */
130 Status TopologicalSort(GraphAdjList GL)
131 {    /* 若GL无回路,则输出拓扑排序序列并返回1,若有回路返回0。 */    
132     EdgeNode *e;    
133     int i,k,gettop;   
134     int top=0;  /* 用于栈指针下标  */
135     int count=0;/* 用于统计输出顶点的个数 */   
136     int *stack;    /* 建栈将入度为0的顶点入栈  */   
137     stack=(int *)malloc(GL->numVertexes * sizeof(int) );    
138     for(i = 0; i<GL->numVertexes; i++)                
139         if(0 == GL->adjList[i].in) /* 将入度为0的顶点入栈 */           
140             stack[++top]=i;    
141 
142     top2=0;    
143     etv=(int *)malloc(GL->numVertexes * sizeof(int) ); /* 事件最早发生时间数组 */    
144     for(i=0; i<GL->numVertexes; i++)        
145         etv[i]=0;    /* 初始化 */
146     stack2=(int *)malloc(GL->numVertexes * sizeof(int) );/* 初始化拓扑序列栈 */
147 
148     printf("TopologicalSort:\t");
149     while(top!=0)    
150     {        
151         gettop=stack[top--];        
152         printf("%d -> ",GL->adjList[gettop].data);        
153         count++;        /* 输出i号顶点,并计数 */ 
154 
155         stack2[++top2]=gettop;        /* 将弹出的顶点序号压入拓扑序列的栈 */
156 
157         for(e = GL->adjList[gettop].firstedge; e; e = e->next)        
158         {            
159             k=e->adjvex;            
160             if( !(--GL->adjList[k].in) )        /* 将i号顶点的邻接点的入度减1,如果减1后为0,则入栈 */                
161                 stack[++top]=k; 
162 
163             if((etv[gettop] + e->weight)>etv[k])    /* 求各顶点事件的最早发生时间etv值 */                
164                 etv[k] = etv[gettop] + e->weight;
165         }    
166     }    
167     printf("\n");   
168     if(count < GL->numVertexes)        
169         return ERROR;    
170     else       
171         return OK;
172 }
173 
174 /* 求关键路径,GL为有向网,输出G的各项关键活动 */
175 void CriticalPath(GraphAdjList GL) 
176 {    
177     EdgeNode *e;    
178     int i,gettop,k,j;    
179     int ete,lte;  /* 声明活动最早发生时间和最迟发生时间变量 */        
180     TopologicalSort(GL);   /* 求拓扑序列,计算数组etv和stack2的值 */ 
181     ltv=(int *)malloc(GL->numVertexes*sizeof(int));/* 事件最早发生时间数组 */   
182     for(i=0; i<GL->numVertexes; i++)        
183         ltv[i]=etv[GL->numVertexes-1];    /* 初始化 */        
184     
185     printf("etv:\t");   
186     for(i=0; i<GL->numVertexes; i++)        
187         printf("%d -> ",etv[i]);    
188     printf("\n"); 
189 
190     while(top2!=0)    /* 出栈是求ltv */    
191     {        
192         gettop=stack2[top2--];        
193         for(e = GL->adjList[gettop].firstedge; e; e = e->next)        /* 求各顶点事件的最迟发生时间ltv值 */        
194         {            
195             k=e->adjvex;            
196             if(ltv[k] - e->weight < ltv[gettop])               
197                 ltv[gettop] = ltv[k] - e->weight;        
198         }   
199     }    
200     
201     printf("ltv:\t");   
202     for(i=0; i<GL->numVertexes; i++)        
203         printf("%d -> ",ltv[i]);    
204     printf("\n"); 
205 
206     for(j=0; j<GL->numVertexes; j++)        /* 求ete,lte和关键活动 */        
207     {            
208         for(e = GL->adjList[j].firstedge; e; e = e->next)            
209         {                
210             k=e->adjvex;                
211             ete = etv[j];        /* 活动最早发生时间 */                
212             lte = ltv[k] - e->weight; /* 活动最迟发生时间 */               
213             if(ete == lte)    /* 两者相等即在关键路径上 */                    
214                 printf("<v%d - v%d> length: %d \n",GL->adjList[j].data,GL->adjList[k].data,e->weight);
215         }        
216     }
217 }
218 
219 
220 int main(void)
221 {    
222     MGraph G;    
223     GraphAdjList GL;    
224     CreateMGraph(&G);
225     CreateALGraph(G,&GL);
226     CriticalPath(GL);
227     return 0;
228 }
CriticalPath.c

 

六、静态查找

  1、静态查找

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 #define MAXSIZE 100 /* 存储空间初始分配量 */
 12 
 13 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */ 
 14 
 15 int F[100]; /* 斐波那契数列 */
 16 
 17 /* 无哨兵顺序查找,a为数组,n为要查找的数组个数,key为要查找的关键字 */
 18 int Sequential_Search(int *a,int n,int key)
 19 {
 20     int i;
 21     for(i=1;i<=n;i++)
 22     {
 23         if (a[i]==key)
 24             return i;
 25     }
 26     return 0;
 27 }
 28 /* 有哨兵顺序查找 */
 29 int Sequential_Search2(int *a,int n,int key)
 30 {
 31     int i;
 32     a[0]=key;
 33     i=n;
 34     while(a[i]!=key)
 35     {
 36         i--;
 37     }
 38     return i;
 39 }
 40 
 41 /* 折半查找 */
 42 int Binary_Search(int *a,int n,int key)
 43 {
 44     int low,high,mid;
 45     low=1;    /* 定义最低下标为记录首位 */
 46     high=n;    /* 定义最高下标为记录末位 */
 47     while(low<=high)
 48     {
 49         mid=(low+high)/2;    /* 折半 */
 50         if (key<a[mid])        /* 若查找值比中值小 */
 51             high=mid-1;        /* 最高下标调整到中位下标小一位 */
 52         else if (key>a[mid])/* 若查找值比中值大 */
 53             low=mid+1;        /* 最低下标调整到中位下标大一位 */
 54         else
 55         {
 56             return mid;        /* 若相等则说明mid即为查找到的位置 */
 57         }
 58         
 59     }
 60     return 0;
 61 }
 62 
 63 /* 插值查找 */
 64 int Interpolation_Search(int *a,int n,int key)
 65 {
 66     int low,high,mid;
 67     low=1;    /* 定义最低下标为记录首位 */
 68     high=n;    /* 定义最高下标为记录末位 */
 69     while(low<=high)
 70     {
 71         mid=low+ (high-low)*(key-a[low])/(a[high]-a[low]); /* 插值 */
 72         if (key<a[mid])        /* 若查找值比插值小 */
 73             high=mid-1;        /* 最高下标调整到插值下标小一位 */
 74         else if (key>a[mid])/* 若查找值比插值大 */
 75             low=mid+1;        /* 最低下标调整到插值下标大一位 */
 76         else
 77             return mid;        /* 若相等则说明mid即为查找到的位置 */
 78     }
 79     return 0;
 80 }
 81 
 82 /* 斐波那契查找 */
 83 int Fibonacci_Search(int *a,int n,int key)
 84 {
 85     int low,high,mid,i,k=0;
 86     low=1;    /* 定义最低下标为记录首位 */
 87     high=n;    /* 定义最高下标为记录末位 */
 88     while(n>F[k]-1)
 89         k++;
 90     for (i=n;i<F[k]-1;i++)
 91         a[i]=a[n];
 92     
 93     while(low<=high)
 94     {
 95         mid=low+F[k-1]-1;
 96         if (key<a[mid])
 97         {
 98             high=mid-1;        
 99             k=k-1;
100         }
101         else if (key>a[mid])
102         {
103             low=mid+1;        
104             k=k-2;
105         }
106         else
107         {
108             if (mid<=n)
109                 return mid;        /* 若相等则说明mid即为查找到的位置 */
110             else 
111                 return n;
112         }
113         
114     }
115     return 0;
116 }
117 
118 
119 
120 
121   
122 
123 int main(void)
124 {    
125 
126     int a[MAXSIZE+1],i,result;
127     int arr[MAXSIZE]={0,1,16,24,35,47,59,62,73,88,99};
128         
129     for(i=0;i<=MAXSIZE;i++)
130     {
131         a[i]=i;
132     }
133     result=Sequential_Search(a,MAXSIZE,MAXSIZE);
134     printf("Sequential_Search:%d \n",result);
135     result=Sequential_Search2(a,MAXSIZE,1);
136     printf("Sequential_Search2:%d \n",result);
137 
138     result=Binary_Search(arr,10,62);
139     printf("Binary_Search:%d \n",result);
140 
141     
142     result=Interpolation_Search(arr,10,62);
143     printf("Interpolation_Search:%d \n",result);
144 
145     
146     F[0]=0;
147     F[1]=1;
148     for(i = 2;i < 100;i++)  
149     { 
150         F[i] = F[i-1] + F[i-2];  
151     } 
152     result=Fibonacci_Search(arr,10,62);
153     printf("Fibonacci_Search:%d \n",result);
154     
155     return 0;
156 }
Search.c

  2、二叉排序树

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 #define MAXSIZE 100 /* 存储空间初始分配量 */
 12 
 13 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */ 
 14 
 15 /* 二叉树的二叉链表结点结构定义 */
 16 typedef  struct BiTNode    /* 结点结构 */
 17 {
 18     int data;    /* 结点数据 */
 19     struct BiTNode *lchild, *rchild;    /* 左右孩子指针 */
 20 } BiTNode, *BiTree;
 21 
 22 
 23 /* 递归查找二叉排序树T中是否存在key, */
 24 /* 指针f指向T的双亲,其初始调用值为NULL */
 25 /* 若查找成功,则指针p指向该数据元素结点,并返回TRUE */
 26 /* 否则指针p指向查找路径上访问的最后一个结点并返回FALSE */
 27 Status SearchBST(BiTree T, int key, BiTree f, BiTree *p) 
 28 {  
 29     if (!T)    /*  查找不成功 */
 30     { 
 31         *p = f;  
 32         return FALSE; 
 33     }
 34     else if (key==T->data) /*  查找成功 */
 35     { 
 36         *p = T;  
 37         return TRUE; 
 38     } 
 39     else if (key<T->data) 
 40         return SearchBST(T->lchild, key, T, p);  /*  在左子树中继续查找 */
 41     else  
 42         return SearchBST(T->rchild, key, T, p);  /*  在右子树中继续查找 */
 43 }
 44 
 45 
 46 /*  当二叉排序树T中不存在关键字等于key的数据元素时, */
 47 /*  插入key并返回TRUE,否则返回FALSE */
 48 Status InsertBST(BiTree *T, int key) 
 49 {  
 50     BiTree p,s;
 51     if (!SearchBST(*T, key, NULL, &p)) /* 查找不成功 */
 52     {
 53         s = (BiTree)malloc(sizeof(BiTNode));
 54         s->data = key;  
 55         s->lchild = s->rchild = NULL;  
 56         if (!p) 
 57             *T = s;            /*  插入s为新的根结点 */
 58         else if (key<p->data) 
 59             p->lchild = s;    /*  插入s为左孩子 */
 60         else 
 61             p->rchild = s;  /*  插入s为右孩子 */
 62         return TRUE;
 63     } 
 64     else 
 65         return FALSE;  /*  树中已有关键字相同的结点,不再插入 */
 66 }
 67 
 68 /* 从二叉排序树中删除结点p,并重接它的左或右子树。 */
 69 Status Delete(BiTree *p)
 70 {
 71     BiTree q,s;
 72     if((*p)->rchild==NULL) /* 右子树空则只需重接它的左子树(待删结点是叶子也走此分支) */
 73     {
 74         q=*p; *p=(*p)->lchild; free(q);
 75     }
 76     else if((*p)->lchild==NULL) /* 只需重接它的右子树 */
 77     {
 78         q=*p; *p=(*p)->rchild; free(q);
 79     }
 80     else /* 左右子树均不空 */
 81     {
 82         q=*p; s=(*p)->lchild;
 83         while(s->rchild) /* 转左,然后向右到尽头(找待删结点的前驱) */
 84         {
 85             q=s;
 86             s=s->rchild;
 87         }
 88         (*p)->data=s->data; /*  s指向被删结点的直接前驱(将被删结点前驱的值取代被删结点的值) */
 89         if(q!=*p)
 90             q->rchild=s->lchild; /*  重接q的右子树 */ 
 91         else
 92             q->lchild=s->lchild; /*  重接q的左子树 */
 93         free(s);
 94     }
 95     return TRUE;
 96 }
 97 
 98 /* 若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素结点, */
 99 /* 并返回TRUE;否则返回FALSE。 */
100 Status DeleteBST(BiTree *T,int key)
101 { 
102     if(!*T) /* 不存在关键字等于key的数据元素 */ 
103         return FALSE;
104     else
105     {
106         if (key==(*T)->data) /* 找到关键字等于key的数据元素 */ 
107             return Delete(T);
108         else if (key<(*T)->data)
109             return DeleteBST(&(*T)->lchild,key);
110         else
111             return DeleteBST(&(*T)->rchild,key);
112          
113     }
114 }
115 
116 int main(void)
117 {    
118     int i;
119     int a[10]={62,88,58,47,35,73,51,99,37,93};
120     BiTree T=NULL;
121     
122     for(i=0;i<10;i++)
123     {
124         InsertBST(&T, a[i]);
125     }
126     DeleteBST(&T,93);
127     DeleteBST(&T,47);
128     printf("本样例建议断点跟踪查看二叉排序树结构");
129     return 0;
130 }
BinarySortTree.c

  3、平衡二叉树

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 #define MAXSIZE 100 /* 存储空间初始分配量 */
 12 
 13 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */ 
 14 
 15 
 16 /* 二叉树的二叉链表结点结构定义 */
 17 typedef  struct BiTNode    /* 结点结构 */
 18 {
 19     int data;    /* 结点数据 */
 20     int bf; /*  结点的平衡因子 */ 
 21     struct BiTNode *lchild, *rchild;    /* 左右孩子指针 */
 22 } BiTNode, *BiTree;
 23 
 24 
 25 /* 对以p为根的二叉排序树作右旋处理, */
 26 /* 处理之后p指向新的树根结点,即旋转处理之前的左子树的根结点 */
 27 void R_Rotate(BiTree *P)
 28 { 
 29     BiTree L;
 30     L=(*P)->lchild; /*  L指向P的左子树根结点 */ 
 31     (*P)->lchild=L->rchild; /*  L的右子树挂接为P的左子树 */ 
 32     L->rchild=(*P);
 33     *P=L; /*  P指向新的根结点 */ 
 34 }
 35 
 36 /* 对以P为根的二叉排序树作左旋处理, */
 37 /* 处理之后P指向新的树根结点,即旋转处理之前的右子树的根结点0  */
 38 void L_Rotate(BiTree *P)
 39 { 
 40     BiTree R;
 41     R=(*P)->rchild; /*  R指向P的右子树根结点 */ 
 42     (*P)->rchild=R->lchild; /* R的左子树挂接为P的右子树 */ 
 43     R->lchild=(*P);
 44     *P=R; /*  P指向新的根结点 */ 
 45 }
 46 
 47 #define LH +1 /*  左高 */ 
 48 #define EH 0  /*  等高 */ 
 49 #define RH -1 /*  右高 */ 
 50 
 51 /*  对以指针T所指结点为根的二叉树作左平衡旋转处理 */
 52 /*  本算法结束时,指针T指向新的根结点 */
 53 void LeftBalance(BiTree *T)
 54 { 
 55     BiTree L,Lr;
 56     L=(*T)->lchild; /*  L指向T的左子树根结点 */ 
 57     switch(L->bf)
 58     { /*  检查T的左子树的平衡度,并作相应平衡处理 */ 
 59          case LH: /*  新结点插入在T的左孩子的左子树上,要作单右旋处理 */ 
 60             (*T)->bf=L->bf=EH;
 61             R_Rotate(T);
 62             break;
 63          case RH: /*  新结点插入在T的左孩子的右子树上,要作双旋处理 */ 
 64             Lr=L->rchild; /*  Lr指向T的左孩子的右子树根 */ 
 65             switch(Lr->bf)
 66             { /*  修改T及其左孩子的平衡因子 */ 
 67                 case LH: (*T)->bf=RH;
 68                          L->bf=EH;
 69                          break;
 70                 case EH: (*T)->bf=L->bf=EH;
 71                          break;
 72                 case RH: (*T)->bf=EH;
 73                          L->bf=LH;
 74                          break;
 75             }
 76             Lr->bf=EH;
 77             L_Rotate(&(*T)->lchild); /*  对T的左子树作左旋平衡处理 */ 
 78             R_Rotate(T); /*  对T作右旋平衡处理 */ 
 79     }
 80 }
 81 
 82 /*  对以指针T所指结点为根的二叉树作右平衡旋转处理, */ 
 83 /*  本算法结束时,指针T指向新的根结点 */ 
 84 void RightBalance(BiTree *T)
 85 { 
 86     BiTree R,Rl;
 87     R=(*T)->rchild; /*  R指向T的右子树根结点 */ 
 88     switch(R->bf)
 89     { /*  检查T的右子树的平衡度,并作相应平衡处理 */ 
 90      case RH: /*  新结点插入在T的右孩子的右子树上,要作单左旋处理 */ 
 91               (*T)->bf=R->bf=EH;
 92               L_Rotate(T);
 93               break;
 94      case LH: /*  新结点插入在T的右孩子的左子树上,要作双旋处理 */ 
 95               Rl=R->lchild; /*  Rl指向T的右孩子的左子树根 */ 
 96               switch(Rl->bf)
 97               { /*  修改T及其右孩子的平衡因子 */ 
 98                 case RH: (*T)->bf=LH;
 99                          R->bf=EH;
100                          break;
101                 case EH: (*T)->bf=R->bf=EH;
102                          break;
103                 case LH: (*T)->bf=EH;
104                          R->bf=RH;
105                          break;
106               }
107               Rl->bf=EH;
108               R_Rotate(&(*T)->rchild); /*  对T的右子树作右旋平衡处理 */ 
109               L_Rotate(T); /*  对T作左旋平衡处理 */ 
110     }
111 }
112 
113 /*  若在平衡的二叉排序树T中不存在和e有相同关键字的结点,则插入一个 */ 
114 /*  数据元素为e的新结点,并返回1,否则返回0。若因插入而使二叉排序树 */ 
115 /*  失去平衡,则作平衡旋转处理,布尔变量taller反映T长高与否。 */
116 Status InsertAVL(BiTree *T,int e,Status *taller)
117 {  
118     if(!*T)
119     { /*  插入新结点,树“长高”,置taller为TRUE */ 
120          *T=(BiTree)malloc(sizeof(BiTNode));
121          (*T)->data=e; (*T)->lchild=(*T)->rchild=NULL; (*T)->bf=EH;
122          *taller=TRUE;
123     }
124     else
125     {
126         if (e==(*T)->data)
127         { /*  树中已存在和e有相同关键字的结点则不再插入 */ 
128             *taller=FALSE; return FALSE;
129         }
130         if (e<(*T)->data)
131         { /*  应继续在T的左子树中进行搜索 */ 
132             if(!InsertAVL(&(*T)->lchild,e,taller)) /*  未插入 */ 
133                 return FALSE;
134             if(*taller) /*   已插入到T的左子树中且左子树“长高” */ 
135                 switch((*T)->bf) /*  检查T的平衡度 */ 
136                 {
137                     case LH: /*  原本左子树比右子树高,需要作左平衡处理 */ 
138                             LeftBalance(T);    *taller=FALSE; break;
139                     case EH: /*  原本左、右子树等高,现因左子树增高而使树增高 */ 
140                             (*T)->bf=LH; *taller=TRUE; break;
141                     case RH: /*  原本右子树比左子树高,现左、右子树等高 */  
142                             (*T)->bf=EH; *taller=FALSE; break;
143                 }
144         }
145         else
146         { /*  应继续在T的右子树中进行搜索 */ 
147             if(!InsertAVL(&(*T)->rchild,e,taller)) /*  未插入 */ 
148                 return FALSE;
149             if(*taller) /*  已插入到T的右子树且右子树“长高” */ 
150                 switch((*T)->bf) /*  检查T的平衡度 */ 
151                 {
152                     case LH: /*  原本左子树比右子树高,现左、右子树等高 */ 
153                             (*T)->bf=EH; *taller=FALSE;    break;
154                     case EH: /*  原本左、右子树等高,现因右子树增高而使树增高  */
155                             (*T)->bf=RH; *taller=TRUE; break;
156                     case RH: /*  原本右子树比左子树高,需要作右平衡处理 */ 
157                             RightBalance(T); *taller=FALSE; break;
158                 }
159         }
160     }
161     return TRUE;
162 }
163 
164 int main(void)
165 {    
166     int i;
167     int a[10]={3,2,1,4,5,6,7,10,9,8};
168     BiTree T=NULL;
169     Status taller;
170     for(i=0;i<10;i++)
171     {
172         InsertAVL(&T,a[i],&taller);
173     }
174     printf("本样例建议断点跟踪查看平衡二叉树结构");
175     return 0;
176 }
AVLTree.c

  4、树

  1 #include "stdio.h"    
  2 #include "stdlib.h"   
  3 #include "io.h"  
  4 #include "math.h"  
  5 #include "time.h"
  6 
  7 #define OK 1
  8 #define ERROR 0
  9 #define TRUE 1
 10 #define FALSE 0
 11 
 12 #define MAXSIZE 100 /* 存储空间初始分配量 */
 13 
 14 #define m 3 /*  B树的阶,暂设为3 */ 
 15 #define N 17 /*  数据元素个数 */ 
 16 #define MAX 5 /*  字符串最大长度+1  */
 17 
 18 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */ 
 19 
 20 typedef struct BTNode
 21 {
 22     int keynum; /*  结点中关键字个数,即结点的大小 */ 
 23     struct BTNode *parent; /*  指向双亲结点 */ 
 24     struct Node /*  结点向量类型 */ 
 25     {
 26          int key; /*  关键字向量 */ 
 27          struct BTNode *ptr; /*  子树指针向量 */ 
 28          int recptr; /*  记录指针向量 */ 
 29     }node[m+1]; /*  key,recptr的0号单元未用 */ 
 30 }BTNode,*BTree; /*  B树结点和B树的类型 */ 
 31 
 32 typedef struct
 33 {
 34     BTNode *pt; /*  指向找到的结点 */ 
 35     int i; /*  1..m,在结点中的关键字序号 */ 
 36     int tag; /*  1:查找成功,O:查找失败 */ 
 37 }Result; /*  B树的查找结果类型 */ 
 38 
 39 /*  在p->node[1..keynum].key中查找i,使得p->node[i].key≤K<p->node[i+1].key */ 
 40 int Search(BTree p, int K)
 41 { 
 42     int i=0,j;
 43     for(j=1;j<=p->keynum;j++)
 44      if(p->node[j].key<=K)
 45        i=j;
 46     return i;
 47 }
 48 
 49 /*  在m阶B树T上查找关键字K,返回结果(pt,i,tag)。若查找成功,则特征值 */ 
 50 /*  tag=1,指针pt所指结点中第i个关键字等于K;否则特征值tag=0,等于K的  */
 51 /*  关键字应插入在指针Pt所指结点中第i和第i+1个关键字之间。 */
 52 Result SearchBTree(BTree T, int K)
 53 { 
 54     BTree p=T,q=NULL; /*  初始化,p指向待查结点,q指向p的双亲  */
 55     Status found=FALSE;
 56     int i=0;
 57     Result r;
 58     while(p&&!found)
 59     {
 60      i=Search(p,K); /*  p->node[i].key≤K<p->node[i+1].key  */
 61      if(i>0&&p->node[i].key==K) /*  找到待查关键字 */ 
 62        found=TRUE;
 63      else
 64      {
 65        q=p;
 66        p=p->node[i].ptr;
 67      }
 68     }
 69     r.i=i;
 70     if(found) /*  查找成功  */
 71     {
 72      r.pt=p;
 73      r.tag=1;
 74     }
 75     else /*   查找不成功,返回K的插入位置信息 */ 
 76     {
 77      r.pt=q;
 78      r.tag=0;
 79     }
 80     return r;
 81 }
 82 
 83 /* 将r->key、r和ap分别插入到q->key[i+1]、q->recptr[i+1]和q->ptr[i+1]中 */ 
 84 void Insert(BTree *q,int i,int key,BTree ap)
 85 { 
 86     int j;
 87     for(j=(*q)->keynum;j>i;j--) /*  空出(*q)->node[i+1]  */
 88         (*q)->node[j+1]=(*q)->node[j];
 89     (*q)->node[i+1].key=key;
 90     (*q)->node[i+1].ptr=ap;
 91     (*q)->node[i+1].recptr=key;
 92     (*q)->keynum++;
 93 }
 94 
 95 /* 将结点q分裂成两个结点,前一半保留,后一半移入新生结点ap */ 
 96 void split(BTree *q,BTree *ap)
 97 { 
 98     int i,s=(m+1)/2;
 99     *ap=(BTree)malloc(sizeof(BTNode)); /*  生成新结点ap */ 
100     (*ap)->node[0].ptr=(*q)->node[s].ptr; /*  后一半移入ap */ 
101     for(i=s+1;i<=m;i++)
102     {
103          (*ap)->node[i-s]=(*q)->node[i];
104          if((*ap)->node[i-s].ptr)
105             (*ap)->node[i-s].ptr->parent=*ap;
106     }
107     (*ap)->keynum=m-s;
108     (*ap)->parent=(*q)->parent;
109     (*q)->keynum=s-1; /*  q的前一半保留,修改keynum */ 
110 }
111 
112 /* 生成含信息(T,r,ap)的新的根结点&T,原T和ap为子树指针 */ 
113 void NewRoot(BTree *T,int key,BTree ap)
114 { 
115     BTree p;
116     p=(BTree)malloc(sizeof(BTNode));
117     p->node[0].ptr=*T;
118     *T=p;
119     if((*T)->node[0].ptr)
120         (*T)->node[0].ptr->parent=*T;
121     (*T)->parent=NULL;
122     (*T)->keynum=1;
123     (*T)->node[1].key=key;
124     (*T)->node[1].recptr=key;
125     (*T)->node[1].ptr=ap;
126     if((*T)->node[1].ptr)
127         (*T)->node[1].ptr->parent=*T;
128 }
129 
130 /*  在m阶B树T上结点*q的key[i]与key[i+1]之间插入关键字K的指针r。若引起 */ 
131 /*  结点过大,则沿双亲链进行必要的结点分裂调整,使T仍是m阶B树。 */
132 void InsertBTree(BTree *T,int key,BTree q,int i)
133 { 
134     BTree ap=NULL;
135     Status finished=FALSE;
136     int s;
137     int rx;
138     rx=key;
139     while(q&&!finished)
140     {
141         Insert(&q,i,rx,ap); /*  将r->key、r和ap分别插入到q->key[i+1]、q->recptr[i+1]和q->ptr[i+1]中  */
142         if(q->keynum<m)
143             finished=TRUE; /*  插入完成 */ 
144         else
145         { /*  分裂结点*q */ 
146             s=(m+1)/2;
147             rx=q->node[s].recptr;
148             split(&q,&ap); /*  将q->key[s+1..m],q->ptr[s..m]和q->recptr[s+1..m]移入新结点*ap  */
149             q=q->parent;
150             if(q)
151                 i=Search(q,key); /*  在双亲结点*q中查找rx->key的插入位置  */
152         }
153     }
154     if(!finished) /*  T是空树(参数q初值为NULL)或根结点已分裂为结点*q和*ap */ 
155         NewRoot(T,rx,ap); /*  生成含信息(T,rx,ap)的新的根结点*T,原T和ap为子树指针 */ 
156 }
157 
158 
159 void print(BTNode c,int i) /*  TraverseDSTable()调用的函数  */
160 {
161     printf("(%d)",c.node[i].key);
162 }
163 
164 int main()
165 {
166     int r[N]={22,16,41,58,8,11,12,16,17,22,23,31,41,52,58,59,61};
167     BTree T=NULL;
168     Result s;
169     int i;
170     for(i=0;i<N;i++)
171     {
172         s=SearchBTree(T,r[i]);
173         if(!s.tag)
174             InsertBTree(&T,r[i],s.pt,s.i);
175     }
176     printf("\n请输入待查找记录的关键字: ");
177     scanf("%d",&i);
178     s=SearchBTree(T,i);
179     if(s.tag)
180         print(*(s.pt),s.i);
181     else
182         printf("没找到");
183     printf("\n");
184 
185     return 0;
186 }
BTree.c

  5、散列表

 1 #include "stdio.h"    
 2 #include "stdlib.h"   
 3 #include "io.h"  
 4 #include "math.h"  
 5 #include "time.h"
 6 
 7 #define OK 1
 8 #define ERROR 0
 9 #define TRUE 1
10 #define FALSE 0
11 
12 #define MAXSIZE 100 /* 存储空间初始分配量 */
13 
14 #define SUCCESS 1
15 #define UNSUCCESS 0
16 #define HASHSIZE 12 /* 定义散列表长为数组的长度 */
17 #define NULLKEY -32768 
18 
19 typedef int Status;    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */ 
20 
21 typedef struct
22 {
23    int *elem; /* 数据元素存储基址,动态分配数组 */
24    int count; /*  当前数据元素个数 */
25 }HashTable;
26 
27 int m=0; /* 散列表表长,全局变量 */
28 
29 /* 初始化散列表 */
30 Status InitHashTable(HashTable *H)
31 {
32     int i;
33     m=HASHSIZE;
34     H->count=m;
35     H->elem=(int *)malloc(m*sizeof(int));
36     for(i=0;i<m;i++)
37         H->elem[i]=NULLKEY; 
38     return OK;
39 }
40 
41 /* 散列函数 */
42 int Hash(int key)
43 {
44     return key % m; /* 除留余数法 */
45 }
46 
47 /* 插入关键字进散列表 */
48 void InsertHash(HashTable *H,int key)
49 {
50     int addr = Hash(key); /* 求散列地址 */
51     while (H->elem[addr] != NULLKEY) /* 如果不为空,则冲突 */
52     {
53         addr = (addr+1) % m; /* 开放定址法的线性探测 */
54     }
55     H->elem[addr] = key; /* 直到有空位后插入关键字 */
56 }
57 
58 /* 散列表查找关键字 */
59 Status SearchHash(HashTable H,int key,int *addr)
60 {
61     *addr = Hash(key);  /* 求散列地址 */
62     while(H.elem[*addr] != key) /* 如果不为空,则冲突 */
63     {
64         *addr = (*addr+1) % m; /* 开放定址法的线性探测 */
65         if (H.elem[*addr] == NULLKEY || *addr == Hash(key)) /* 如果循环回到原点 */
66             return UNSUCCESS;    /* 则说明关键字不存在 */
67     }
68     return SUCCESS;
69 }
70 
71 int main()
72 {
73     int arr[HASHSIZE]={12,67,56,16,25,37,22,29,15,47,48,34};
74     int i,p,key,result;
75     HashTable H;
76 
77     key=39;
78 
79     InitHashTable(&H);
80     for(i=0;i<m;i++)
81          InsertHash(&H,arr[i]);
82     
83     result=SearchHash(H,key,&p);
84     if (result)
85         printf("查找 %d 的地址为:%d \n",key,p);
86     else
87         printf("查找 %d 失败。\n",key);
88 
89     for(i=0;i<m;i++)
90     {
91         key=arr[i];
92         SearchHash(H,key,&p);
93         printf("查找 %d 的地址为:%d \n",key,p);
94     }
95 
96     return 0;
97 }
HashTable.c

 

七、排序

  排序

  1 #include <stdio.h>    
  2 #include <string.h>
  3 #include <ctype.h>      
  4 #include <stdlib.h>   
  5 #include <io.h>  
  6 #include <math.h>  
  7 #include <time.h>
  8 
  9 #define OK 1
 10 #define ERROR 0
 11 #define TRUE 1
 12 #define FALSE 0
 13 
 14 #define MAX_LENGTH_INSERT_SORT 7 /* 用于快速排序时判断是否选用插入排序阙值 */
 15 
 16 typedef int Status; 
 17 
 18 
 19 #define MAXSIZE 10000  /* 用于要排序数组个数最大值,可根据需要修改 */
 20 typedef struct
 21 {
 22     int r[MAXSIZE+1];    /* 用于存储要排序数组,r[0]用作哨兵或临时变量 */
 23     int length;            /* 用于记录顺序表的长度 */
 24 }SqList;
 25 
 26 /* 交换L中数组r的下标为i和j的值 */
 27 void swap(SqList *L,int i,int j) 
 28 { 
 29     int temp=L->r[i]; 
 30     L->r[i]=L->r[j]; 
 31     L->r[j]=temp; 
 32 }
 33 
 34 void print(SqList L)
 35 {
 36     int i;
 37     for(i=1;i<L.length;i++)
 38         printf("%d,",L.r[i]);
 39     printf("%d",L.r[i]);
 40     printf("\n");
 41 }
 42 
 43 /* 对顺序表L作交换排序(冒泡排序初级版) */
 44 void BubbleSort0(SqList *L)
 45 { 
 46     int i,j;
 47     for(i=1;i<L->length;i++)
 48     {
 49         for(j=i+1;j<=L->length;j++)
 50         {
 51             if(L->r[i]>L->r[j])
 52             {
 53                  swap(L,i,j);/* 交换L->r[i]与L->r[j]的值 */
 54             }
 55         }
 56     }
 57 }
 58 
 59 /* 对顺序表L作冒泡排序 */
 60 void BubbleSort(SqList *L)
 61 { 
 62     int i,j;
 63     for(i=1;i<L->length;i++)
 64     {
 65         for(j=L->length-1;j>=i;j--)  /* 注意j是从后往前循环 */
 66         {
 67             if(L->r[j]>L->r[j+1]) /* 若前者大于后者(注意这里与上一算法的差异)*/
 68             {
 69                  swap(L,j,j+1);/* 交换L->r[j]与L->r[j+1]的值 */
 70             }
 71         }
 72     }
 73 }
 74 
 75 /* 对顺序表L作改进冒泡算法 */
 76 void BubbleSort2(SqList *L)
 77 { 
 78     int i,j;
 79     Status flag=TRUE;            /* flag用来作为标记 */
 80     for(i=1;i<L->length && flag;i++) /* 若flag为true说明有过数据交换,否则停止循环 */
 81     {
 82         flag=FALSE;                /* 初始为False */
 83         for(j=L->length-1;j>=i;j--)
 84         {
 85             if(L->r[j]>L->r[j+1])
 86             {
 87                  swap(L,j,j+1);    /* 交换L->r[j]与L->r[j+1]的值 */
 88                  flag=TRUE;        /* 如果有数据交换,则flag为true */
 89             }
 90         }
 91     }
 92 }
 93 
 94 
 95 /* 对顺序表L作简单选择排序 */
 96 void SelectSort(SqList *L)
 97 {
 98     int i,j,min;
 99     for(i=1;i<L->length;i++)
100     { 
101         min = i;                        /* 将当前下标定义为最小值下标 */
102         for (j = i+1;j<=L->length;j++)/* 循环之后的数据 */
103         {
104             if (L->r[min]>L->r[j])    /* 如果有小于当前最小值的关键字 */
105                 min = j;                /* 将此关键字的下标赋值给min */
106         }
107         if(i!=min)                        /* 若min不等于i,说明找到最小值,交换 */
108             swap(L,i,min);                /* 交换L->r[i]与L->r[min]的值 */
109     }
110 }
111 
112 /* 对顺序表L作直接插入排序 */
113 void InsertSort(SqList *L)
114 { 
115     int i,j;
116     for(i=2;i<=L->length;i++)
117     {
118         if (L->r[i]<L->r[i-1]) /* 需将L->r[i]插入有序子表 */
119         {
120             L->r[0]=L->r[i]; /* 设置哨兵 */
121             for(j=i-1;L->r[j]>L->r[0];j--)
122                 L->r[j+1]=L->r[j]; /* 记录后移 */
123             L->r[j+1]=L->r[0]; /* 插入到正确位置 */
124         }
125     }
126 }
127 
128 /* 对顺序表L作希尔排序 */
129 void ShellSort(SqList *L)
130 {
131     int i,j,k=0;
132     int increment=L->length;
133     do
134     {
135         increment=increment/3+1;/* 增量序列 */
136         for(i=increment+1;i<=L->length;i++)
137         {
138             if (L->r[i]<L->r[i-increment])/*  需将L->r[i]插入有序增量子表 */ 
139             { 
140                 L->r[0]=L->r[i]; /*  暂存在L->r[0] */
141                 for(j=i-increment;j>0 && L->r[0]<L->r[j];j-=increment)
142                     L->r[j+increment]=L->r[j]; /*  记录后移,查找插入位置 */
143                 L->r[j+increment]=L->r[0]; /*  插入 */
144             }
145         }
146         printf("    第%d趟排序结果: ",++k);
147         print(*L);
148     }
149     while(increment>1);
150 
151 }
152 
153 
154 /* 堆排序********************************** */
155 
156 /* 已知L->r[s..m]中记录的关键字除L->r[s]之外均满足堆的定义, */
157 /* 本函数调整L->r[s]的关键字,使L->r[s..m]成为一个大顶堆 */
158 void HeapAdjust(SqList *L,int s,int m)
159 { 
160     int temp,j;
161     temp=L->r[s];
162     for(j=2*s;j<=m;j*=2) /* 沿关键字较大的孩子结点向下筛选 */
163     {
164         if(j<m && L->r[j]<L->r[j+1])
165             ++j; /* j为关键字中较大的记录的下标 */
166         if(temp>=L->r[j])
167             break; /* rc应插入在位置s上 */
168         L->r[s]=L->r[j];
169         s=j;
170     }
171     L->r[s]=temp; /* 插入 */
172 }
173 
174 /*  对顺序表L进行堆排序 */
175 void HeapSort(SqList *L)
176 {
177     int i;
178     for(i=L->length/2;i>0;i--) /*  把L中的r构建成一个大根堆 */
179          HeapAdjust(L,i,L->length);
180 
181     for(i=L->length;i>1;i--)
182     { 
183          swap(L,1,i); /* 将堆顶记录和当前未经排序子序列的最后一个记录交换 */
184          HeapAdjust(L,1,i-1); /*  将L->r[1..i-1]重新调整为大根堆 */
185     }
186 }
187 
188 /* **************************************** */
189 
190 
191 /* 归并排序********************************** */
192 
193 /* 将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n] */
194 void Merge(int SR[],int TR[],int i,int m,int n)
195 {
196     int j,k,l;
197     for(j=m+1,k=i;i<=m && j<=n;k++)    /* 将SR中记录由小到大地并入TR */
198     {
199         if (SR[i]<SR[j])
200             TR[k]=SR[i++];
201         else
202             TR[k]=SR[j++];
203     }
204     if(i<=m)
205     {
206         for(l=0;l<=m-i;l++)
207             TR[k+l]=SR[i+l];        /* 将剩余的SR[i..m]复制到TR */
208     }
209     if(j<=n)
210     {
211         for(l=0;l<=n-j;l++)
212             TR[k+l]=SR[j+l];        /* 将剩余的SR[j..n]复制到TR */
213     }
214 }
215 
216 
217 /* 递归法 */
218 /* 将SR[s..t]归并排序为TR1[s..t] */
219 void MSort(int SR[],int TR1[],int s, int t)
220 {
221     int m;
222     int TR2[MAXSIZE+1];
223     if(s==t)
224         TR1[s]=SR[s];
225     else
226     {
227         m=(s+t)/2;                /* 将SR[s..t]平分为SR[s..m]和SR[m+1..t] */
228         MSort(SR,TR2,s,m);        /* 递归地将SR[s..m]归并为有序的TR2[s..m] */
229         MSort(SR,TR2,m+1,t);    /* 递归地将SR[m+1..t]归并为有序的TR2[m+1..t] */
230         Merge(TR2,TR1,s,m,t);    /* 将TR2[s..m]和TR2[m+1..t]归并到TR1[s..t] */
231     }
232 }
233 
234 /* 对顺序表L作归并排序 */
235 void MergeSort(SqList *L)
236 { 
237      MSort(L->r,L->r,1,L->length);
238 }
239 
240 /* 非递归法 */
241 /* 将SR[]中相邻长度为s的子序列两两归并到TR[] */
242 void MergePass(int SR[],int TR[],int s,int n)
243 {
244     int i=1;
245     int j;
246     while(i <= n-2*s+1)
247     {/* 两两归并 */
248         Merge(SR,TR,i,i+s-1,i+2*s-1);
249         i=i+2*s;        
250     }
251     if(i<n-s+1) /* 归并最后两个序列 */
252         Merge(SR,TR,i,i+s-1,n);
253     else /* 若最后只剩下单个子序列 */
254         for(j =i;j <= n;j++)
255             TR[j] = SR[j];
256 }
257 
258 /* 对顺序表L作归并非递归排序 */
259 void MergeSort2(SqList *L)
260 {
261     int* TR=(int*)malloc(L->length * sizeof(int));/* 申请额外空间 */
262     int k=1;
263     while(k<L->length)
264     {
265         MergePass(L->r,TR,k,L->length);
266         k=2*k;/* 子序列长度加倍 */
267         MergePass(TR,L->r,k,L->length);
268         k=2*k;/* 子序列长度加倍 */       
269     }
270 }
271 
272 /* **************************************** */
273 
274 /* 快速排序******************************** */
275  
276 /* 交换顺序表L中子表的记录,使枢轴记录到位,并返回其所在位置 */
277 /* 此时在它之前(后)的记录均不大(小)于它。 */
278 int Partition(SqList *L,int low,int high)
279 { 
280     int pivotkey;
281 
282     pivotkey=L->r[low]; /* 用子表的第一个记录作枢轴记录 */
283     while(low<high) /*  从表的两端交替地向中间扫描 */
284     { 
285          while(low<high&&L->r[high]>=pivotkey)
286             high--;
287          swap(L,low,high);/* 将比枢轴记录小的记录交换到低端 */
288          while(low<high&&L->r[low]<=pivotkey)
289             low++;
290          swap(L,low,high);/* 将比枢轴记录大的记录交换到高端 */
291     }
292     return low; /* 返回枢轴所在位置 */
293 }
294 
295 /* 对顺序表L中的子序列L->r[low..high]作快速排序 */
296 void QSort(SqList *L,int low,int high)
297 { 
298     int pivot;
299     if(low<high)
300     {
301             pivot=Partition(L,low,high); /*  将L->r[low..high]一分为二,算出枢轴值pivot */
302             QSort(L,low,pivot-1);        /*  对低子表递归排序 */
303             QSort(L,pivot+1,high);        /*  对高子表递归排序 */
304     }
305 }
306 
307 /* 对顺序表L作快速排序 */
308 void QuickSort(SqList *L)
309 { 
310     QSort(L,1,L->length);
311 }
312 
313 /* **************************************** */
314 
315 /* 改进后快速排序******************************** */
316 
317 /* 快速排序优化算法 */
318 int Partition1(SqList *L,int low,int high)
319 { 
320     int pivotkey;
321 
322     int m = low + (high - low) / 2; /* 计算数组中间的元素的下标 */  
323     if (L->r[low]>L->r[high])            
324         swap(L,low,high);    /* 交换左端与右端数据,保证左端较小 */
325     if (L->r[m]>L->r[high])
326         swap(L,high,m);        /* 交换中间与右端数据,保证中间较小 */
327     if (L->r[m]>L->r[low])
328         swap(L,m,low);        /* 交换中间与左端数据,保证左端较小 */
329     
330     pivotkey=L->r[low]; /* 用子表的第一个记录作枢轴记录 */
331     L->r[0]=pivotkey;  /* 将枢轴关键字备份到L->r[0] */
332     while(low<high) /*  从表的两端交替地向中间扫描 */
333     { 
334          while(low<high&&L->r[high]>=pivotkey)
335             high--;
336          L->r[low]=L->r[high];
337          while(low<high&&L->r[low]<=pivotkey)
338             low++;
339          L->r[high]=L->r[low];
340     }
341     L->r[low]=L->r[0];
342     return low; /* 返回枢轴所在位置 */
343 }
344 
345 void QSort1(SqList *L,int low,int high)
346 { 
347     int pivot;
348     if((high-low)>MAX_LENGTH_INSERT_SORT)
349     {
350         while(low<high)
351         {
352             pivot=Partition1(L,low,high); /*  将L->r[low..high]一分为二,算出枢轴值pivot */
353             QSort1(L,low,pivot-1);        /*  对低子表递归排序 */
354             /* QSort(L,pivot+1,high);        /*  对高子表递归排序 */
355             low=pivot+1;    /* 尾递归 */
356         }
357     }
358     else
359         InsertSort(L);
360 }
361 
362 /* 对顺序表L作快速排序 */
363 void QuickSort1(SqList *L)
364 { 
365     QSort1(L,1,L->length);
366 }
367 
368 /* **************************************** */
369 #define N 9
370 int main()
371 {
372    int i;
373    
374    /* int d[N]={9,1,5,8,3,7,4,6,2}; */
375    int d[N]={50,10,90,30,70,40,80,60,20};
376    /* int d[N]={9,8,7,6,5,4,3,2,1}; */
377 
378    SqList l0,l1,l2,l3,l4,l5,l6,l7,l8,l9,l10;
379    
380    for(i=0;i<N;i++)
381      l0.r[i+1]=d[i];
382    l0.length=N;
383    l1=l2=l3=l4=l5=l6=l7=l8=l9=l10=l0;
384    printf("排序前:\n");
385    print(l0);
386 
387    printf("初级冒泡排序:\n");
388    BubbleSort0(&l0);
389    print(l0);
390    
391    printf("冒泡排序:\n");
392    BubbleSort(&l1);
393    print(l1);
394    
395    printf("改进冒泡排序:\n");
396    BubbleSort2(&l2);
397    print(l2);
398    
399    printf("选择排序:\n");
400    SelectSort(&l3);
401    print(l3);
402    
403    printf("直接插入排序:\n");
404    InsertSort(&l4);
405    print(l4);
406 
407    printf("希尔排序:\n");
408    ShellSort(&l5);
409    print(l5);
410     
411    printf("堆排序:\n");
412    HeapSort(&l6);
413    print(l6);
414 
415    printf("归并排序(递归):\n");
416    MergeSort(&l7);
417    print(l7);
418 
419    printf("归并排序(非递归):\n");
420    MergeSort2(&l8);
421    print(l8);
422 
423    printf("快速排序:\n");
424    QuickSort(&l9);
425    print(l9);
426 
427    printf("改进快速排序:\n");
428    QuickSort1(&l10);
429    print(l10);
430 
431 
432     /*大数据排序*/
433     /* 
434     srand(time(0));  
435     int Max=10000;
436     int d[10000];
437     int i;
438     SqList l0;
439     for(i=0;i<Max;i++)
440         d[i]=rand()%Max+1;
441     for(i=0;i<Max;i++)
442         l0.r[i+1]=d[i];
443     l0.length=Max;
444     MergeSort(l0);
445     print(l0);
446     */
447     return 0;
448 }
Sort.c

 

posted @ 2020-02-27 15:19  墨小语  阅读(1715)  评论(0编辑  收藏  举报