常用数据结构代码示例
一、线性表
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 }