常用數據結構代碼示例


一、線性表

  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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM