一、線性表
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 }
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 }
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 }
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 }
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 }
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 }
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 }
三、串
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 }
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 }
四、樹
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 }
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 }
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 }
五、圖
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
六、靜態查找
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 }
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 }
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 }
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 }
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 }
七、排序
排序
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 }
