C_C+++常用算法整理+可运行

C_C+++常用算法整理(先放在这儿,以后总结)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
#include  "stdafx.h"
#include  "stdlib.h"
#include  "time.h"
#include <iostream>
using  namespace std;


  typedef  struct Node
 {
     int data;
     struct Node* next;
 }Node;
  typedef  struct Node *LinkList;


  //
  //注意:凡是更改链表数据的地方都要用指针。
  //
  void CreateListHead(LinkList *L, int n) //创建链表,头插法
 {
    LinkList p;
     int i;
    srand(time( NULL));
    *L=(LinkList)malloc( sizeof(Node));
    (*L)->data=n;
    (*L)->next= NULL;
     for (i= 0;i<n;i++)
    {
        p=(LinkList)malloc( sizeof(Node));
        p->data=rand()% 100+ 1;
        p->next=(*L)->next;
        (*L)->next=p;
    }
 }


  void CreateListTail(LinkList *L, int n) //创建链表,尾插法,利用一个动态指针。
 {
    LinkList p,q;
     int i;
    srand(time( NULL));
    *L=(LinkList)malloc( sizeof(Node));
    (*L)->data=n;
    p=*L;
     for(i= 0;i<n;i++)
    {
        q=(LinkList)malloc( sizeof(Node));
        q->data=rand()% 100+ 1;
        p->next=q;
        p=q;
    }

    p->next= NULL; //记住喽要置空
 }

  void ClearList(LinkList *L) //删除链表
 {
    LinkList p,q;
    p=(*L)->next;
     while (p)
    {
        q=p->next;
        free(p);
        p=q;
    }
    (*L)->next= NULL;
 }

  bool GetElem(LinkList L, int i,  int *e)   //从链表中查找一个元素,利用e返回
 {
     int j;
    LinkList p;
    p=L->next;
    j= 1;
     while (p&&j<i)
    {
        p=p->next;
        ++j;
    }

     if (!p||j>i)
    {
         return  false;
    }
    *e=p->data;
     return  true;
 }

  bool ListInsert(LinkList *L, int i, int e) //在位置i处插入元素
 {
     int j;
    LinkList p,q;
    p=*L;
    j= 1;
     while(p&&j<i)
    {
        p=p->next;
        ++j;
    }

     if (!p||j>i)
    {
         return  false;
    }

    q=(LinkList)malloc( sizeof(Node));
    q->data=e;
    q->next=p->next;
    p->next=q;
     return  true;
 }

  bool ListDelete(LinkList *L, int i) //删除一个元素
 {
     int j= 1;
    LinkList p,q;
    p=(*L);
     while(p&&j<i)
    {
        p=p->next;
        ++j;
    }

     if (!(p->next))
    {
         return  false;
    }

    q=p->next;
    p->next=q->next;
    free(q);
     return  true;

 }


  typedef  struct StackNode
 {
     int data;
    StackNode* next;
 }StackNode,*LinkStackPtr;

  typedef  struct LinkStack
 {
    LinkStackPtr top;
     int count;
 }LinkStack;

  void InitStack(LinkStack* S)
 {
  //     LinkStackPtr s=(LinkStackPtr)malloc(sizeof(StackNode));
  //     s->data=0;
  //     s->next=NULL;
  //     S->top=s;
  //     S->count=0;
    S->top= NULL;
    S->count= 0;
 }

  bool Push(LinkStack* S, int e)
 {
    LinkStackPtr s=(LinkStackPtr)malloc( sizeof(StackNode));
    s->data=e;
    s->next=S->top;
    S->top=s;
    S->count++;
     return  true;
 }

  bool Pop(LinkStack* S, int *e)
 {
    LinkStackPtr p;
     if (S->count== 0)
    {
         return  false;
    }

    *e=S->top->data;
    p=S->top;
    S->top=S->top->next;
    free(p);
    S->count--;
     return  true;
 }


  //迭代  斐波那契
  int Fbi( int i)
 {
     if (i< 2)
    {
         return i== 0 ?  0: 1;
    }
     return Fbi(i- 1)+Fbi(i- 2);
 }

  //循环队列
  typedef  int QElemType;   //前端删除,后端插入
  typedef  struct{
    QElemType data[ 100];
     int front;
     int rear;
 }SqQueue;

 BOOL InitQueue(SqQueue* Q)
 {
    Q->rear= 0;
    Q->front= 0;
     return TRUE;
 }

  int QueueLength(SqQueue Q)
 {
     return (Q.rear-Q.front+ 100)% 100;
 }

 BOOL EnQueue(SqQueue* Q,QElemType e)
 {
     if ((Q->rear+ 1)% 100==Q->front) //队列满判断
    {
         return FALSE;
    }

    Q->data[Q->rear]=e;
    Q->rear=(Q->rear+ 1)% 100; //移到下一位置

     return TRUE;
 }

 BOOL DeQueue(SqQueue* Q,QElemType *e)
 {
     if (Q->front==Q->rear) //队列空判断
    {
         return FALSE;
    }

    *e=Q->data[Q->front];
    Q->front=(Q->front+ 1)% 100;

     return TRUE;
 }


  // KMP模式匹配算法
   void get_next(string T, int * next) //返回字串T的next数组
  {
     int i,j;
    i= 1;j= 0;
    next[ 1]= 0;
     while (i<T[ 0])
    {
         if (j==0||T[i]==T[j])   //T[i]表示后缀的单个字符,T[j]表示前缀的单个字符
        {
            ++i;
            ++j;
            next[i]=j;
        }

         else
        {
            j=next[j]; //若字符不同则j值回溯
        }
    }
  }

   int Index_KMP(string S,string T, int pos) //返回子串在pos个字符之后的位置,不存在返回0
  {
     int i=pos; //i用于主串S当前位置下标值,若pos不为1,则从pos位置开始匹配

     int j= 1; //j用于子串T中当前位置下标值

     int next[ 255]; //定义以next数组
    get_next(T,next); //对串T做分析,得到next数组
     while (i<=S[ 0]&&j<=T[ 0]) //若i小于S的长度且j小于T的长度时,循环继续
    {
         if (j==0||S[i]==T[j]) //两字母相等则继续,与朴素法增加了j=0的判断
        {
            ++i;
            ++j;
        }
         else
            j=next[j]; //j退回合适的位置,i值不变
    }

     if (j>T[ 0])
    {
         return i-T[ 0];
    }
     else
         return  0;
  }


  //二叉树
  //二叉树二叉链表节点结构定义
  typedef  struct BiTNode
 {
     int data;
     int bf;
     struct BiTNode *lchild,*rchild; //左右孩子指针
 }BiTNode,*BitTree;

  void PreOrderTraverse(BitTree T) //前序遍历递归算法
 {
     if (T== NULL)
    {
         return;
    }

    printf( "%d",T->data); //可以更改为其他对节点操作
    PreOrderTraverse(T->lchild);
    PreOrderTraverse(T->rchild);

 }

  void InOrderTraverse(BitTree T) //中序遍历
 {
     if (T== NULL)
    {
         return;
    }

    InOrderTraverse(T->lchild);
    printf( "%d",T->data);
    InOrderTraverse(T->rchild);

 }

  void PostOrderTraverse(BitTree T) //后序遍历
 {
     if (T= NULL)
    {
         return;
    }

    PostOrderTraverse(T->lchild);
    PostOrderTraverse(T->rchild);
    printf( "%d",T->data);
 }

  void CreateBitTree(BitTree* T) //生成一个二叉树
 {
     int num;
    scanf( "%d",&num);
     if ( 99==num)   //自己定义
    {
        *T= NULL;
    }
     else
    {
        *T=(BitTree)malloc( sizeof(BiTNode));
         if (!*T)
        {
            (*T)->data=num;
            CreateBitTree(&(*T)->lchild);
            CreateBitTree(&(*T)->rchild);
        }
    }
 }


  //二叉排序树查找
 BOOL SearchBST(BitTree T, int key,BitTree f,BitTree*p) //f为T的双亲,初始调用值为NULL
                                                         //指针p指向该数据结点
 {
     if (!T)
    {
        *p=f;
         return FALSE;
    }

     else  if (key==T->data)
    {
        *p=T;
         return TRUE;
    }
     else  if (key<T->data)
    {
         return SearchBST(T->lchild,key,T,p);
    }
     else
         return SearchBST(T->rchild,key,T,p);
 }

 BOOL InsertBST(BitTree *T, int key)
 {
    BitTree p,s;
     if (!SearchBST(*T,key, NULL,&p))
    {
        s=(BitTree)malloc( sizeof(BiTNode));
        s->data=key;
        s->lchild=s->rchild= NULL;
         if (!p)
        {
            *T=s;
        }
         else  if (key<p->data)
        {
            p->lchild;
        }
         else
            p->rchild=s;
         return TRUE;
    }
     return FALSE;
 }

 BOOL DeleteBST(BitTree* T, int key) //二叉排序树删除元素
 {
     if (!*T)
    {
         return FALSE;
    }

     else
    {
         if (key==(*T)->data)
        {
             return Delete(T); //删除元素
        }
         else  if (key<(*T)->data)
        {
             return DeleteBST(&(*T)->lchild,key);
        }
         else
             return DeleteBST(&(*T)->rchild,key);
    }
 }

 BOOL Delete(BitTree*p)
 {
    BitTree q,s;
     if ((*p)->rchild== NULL) //右子树为空则只重连接左子树
    {
        q=*p;*p=(*p)->lchild;free(q);
    }
     else  if ((*p)->lchild== NULL) //重连右子树
    {
        q=*p;*p=(*p)->rchild;free(q);
    }
     else //左右子树都不空
    {
        q=*p;s=(*p)->lchild; //在左子树查找替代元素
         while (s->rchild) //右子树不空,就对q赋值
        {
            q=s;s=s->rchild;
        }
        (*p)->data=s->data;
         if (q!=*p)
        {
            q->rchild=s->lchild;
        }
         else
            q->lchild=s->lchild;
        free(s);
    }
     return TRUE;
 }


  void R_Rotate(BitTree* P) //二叉排序树右旋处理
 {
    BitTree L;
    L=(*P)->lchild; //L指向P的左子树根节点
    (*P)->lchild=L->rchild; //L的右子树挂接为P的左子树
    L->rchild=(*P); //P成为L的右子树
    *P=L; //重新设置新结点
 }

  void L_Rotate(BitTree*P) //二叉排序树左旋处理
 {
    BitTree R;
    R=(*P)->rchild;
    (*P)->rchild=R->lchild;
    R->lchild=(*P);
    *P=R;
 }


  //平衡二叉树 AVL
  #define LH + 1
  #define EH  0
  #define RH - 1
  void LeftBalance(BitTree*T) //对以T所指结点为根的二叉排序树做左平衡旋转处理
 {
    BitTree L,Lr;
    L=(*T)->lchild;
     switch (L->bf)
    {
     case LH:
        (*T)->bf=L->bf=EH; //新节点在T的左孩子的左子树上,简单右旋处理
        R_Rotate(T);
         break;
     case RH:         //新结点在T的左孩子的右子树上,要做双旋处理
        Lr=L->rchild;
         switch(Lr->bf)
        {
         case LH:(*T)->bf=RH;
                L->bf=EH;
                 break;
         case EH:(*T)->bf=L->bf=EH;
             break;
         case RH:(*T)->bf=EH;
            L->bf=LH;
             break;
        }
        Lr->bf=EH;
        L_Rotate(&(*T)->lchild); //对T的左子树做左旋平衡处理
        R_Rotate(T); //对T做右旋平衡处理
         break;
    }
 }


  void RightBalance(BitTree*T)
 {
    BitTree R,Rr;
    R=(*T)->rchild;
     switch (R->bf)
    {
     case LH:
        Rr=R->lchild;
         switch(Rr->bf)
        {
         case LH:(*T)->bf=RH;
            R->bf=EH;
             break;
         case EH:(*T)->bf=R->bf=EH;
             break;
         case RH:(*T)->bf=EH;
            R->bf=LH;
             break;
        }
        Rr->bf=EH;
        R_Rotate(&(*T)->rchild);
        L_Rotate(T);

         break;
     case RH:
        (*T)->bf=R->bf=EH;
        L_Rotate(T);
         break;
    }

 }


 BOOL InsertAVL(BitTree*T, int e,BOOL* taller)
 {
     if (!(*T))
    {
        *T=(BitTree)malloc( sizeof(BiTNode));
        (*T)->data=e;
        (*T)->lchild=(*T)->rchild= NULL;
        (*T)->bf=EH;
        *taller=TRUE;
    }
     else
    {
         if (e==(*T)->data)
        {
            *taller=FALSE;
             return FALSE;
        }
         if(e<(*T)->data) //应继续在T的左子树中进行搜索
        {
             if (!InsertAVL(&(*T)->lchild,e,taller)) //未插入
            {
                 return FALSE;
            }
             if (*taller) //已经插入到T的左子树中且左子树长高
            {
                 switch((*T)->bf)
                {
                 case LH:
                    LeftBalance(T);
                    *taller=FALSE;
                     break;
                 case EH:
                    (*T)->bf=LH;
                    *taller=TRUE;
                     break;
                 case RH:
                    (*T)->bf=EH;
                    *taller=FALSE;
                     break;
                }
            }
        }
         else
        {
             if (!InsertAVL(&(*T)->rchild,e,taller)) //应该在T的右子树中查找
            {
                 return FALSE;
            }
             if (*taller) //已经插入到T的右子树且右子树长高
            {
                 switch((*T)->bf)
                {
                 case LH:
                    (*T)->bf=EH;
                    *taller=FALSE;
                     break;
                 case EH:
                    (*T)->bf=RH;
                    *taller=TRUE;
                     break;
                 case RH:
                    RightBalance(T);
                    *taller=FALSE;
                     break;

                }
            }
        }
    }
     return TRUE;
 }

  //平衡二叉树 AVL

  //有序查找
  int Binary_Search( int *a, int n, int key) //折半(二分)查找法  用于有序表中
 {
     int low,high,mid;
    low= 1;
    high=n;

     while (low<=high)
    {
        mid=(low+high)/ 2; //折半
         if (key<a[mid])
        {
            high=mid- 1;
        }
         else  if (key>a[mid])
        {
            low=mid+ 1;
        }
         else
             return mid;

    }

     return  0;

 }

  int Inerpolation_Search( int *a, int n, int key) //插值查找,二分法的一种改进
 {
     int low,high,mid;                        //试用于数据分布比较均匀的数列,不适合数据分布极端不均的数据
    low= 1;
    high=n;
     while(low<=high)
    {
        mid=low+(key-a[low])/(a[high]-a[low])*(high-low);
         if (key<a[mid])
        {
            high=mid- 1;
        }

         else  if (key>a[mid])
        {
            low=mid+ 1;
        }
         else
             return mid;
    }

     return  0;
 }


  int Fibonacci_Search( int * a , int n, int key) //斐波那契查找,不是很明白 //大数据时用会提高效率 F为斐波那契数组
 {
     int low,high,mid,i,k;
    low= 1;
    high=n;
    k= 0;
     while(n>F[k]- 1)
        k++;
     for (i=n;i<F[k]- 1;i++)
    {
        a[i]=a[n];
    }
     while (low<=high)
    {
        mid=low+F[k- 1]- 1;
         if (key<a[mid])
        {
            high=mid- 1;
            k=k- 1;
        }
         else   if (key>a[mid])
        {
            low=mid+ 1;
            k=k- 2;
        }
         else
        {
             if (mid<=n)
            {
                 return mid;
            }
             else
                 return n;
        }
    }
     return  0;
 }


// 有序查找
  //以下为排序算法
#define MAXSIZE  10
typedef  struct
{
     int r[MAXSIZE+ 1]; //存储排序数组,r[0]用作哨兵
     int length;      //记录表长
}SqList;

  void swap(SqList*L, int i, int j) //交换函数,频繁用到
 {
     int temp=L->r[i];
    L->r[i]=L->r[j];
    L->r[j]=temp;
 }

  void BubbleSort0(SqList*L) //简单的冒泡排序,简单的交换排序
 {
     int i,j;
     for (i= 1;i<L->length;i++)
    {
         for (j=i+ 1;j<=L->length;j++)
        {
             if (L->r[i]>L->r[j])
            {
                swap(L,i,j);
            }
        }
    }
 }

  void BubbleSort(SqList*L) //正宗的冒泡法,两两比较,反序交换
 {
     int i,j;
     for (i= 1;i<L->length;i++)
    {
         for (j=L->length- 1;j>=i;j--) //从后面开始
        {
             if (L->r[j]>L->r[j+ 1])
            {
                swap(L,j,j+ 1);
            }
        }
    }
 }

  void BubbleSort2(SqList*L) //优化后的冒泡算法
 {
     int i,j;
    BOOL flag=TRUE; //标记
     for (i= 1;i<L->length&&flag;i++)  //如果flag为true,说明有数据交换,为false说明无数据交换,可停止循环了
    {
        flag=FALSE;
         for (j=L->length- 1;j>=i;j--)
        {
             if (L->r[j]>L->r[j+ 1])
            {
                swap(L,j,j+ 1);
                flag=TRUE; //有数据交换,则值为真。
            }
        }
         if (!flag)
        {
             return;
        }
    }
 }

  void SelectSort(SqList*L) //简单的选择排序,依次比较将最小的,然后与第一个位置交换
 {
     int i,j,min;
     for (i= 1;i<L->length;i++)
    {
        min=i;
         for (j=i+ 1;j<=L->length;j++)
        {
             if (L->r[min]>L->r[j])
            {
                min=j;
            }
        }
         if (i!=min)
        {
            swap(L,i,min);
        }
    }
 }

  void InsertSort(SqList*L) //直接插入排序,将一个记录插入到已经排好序的有序表中,得到一个新的、记录数增1的有序表
 {
     int i,j;
     for (i= 2;i<=L->length;i++) //i从2开始就是假设1处为已经排好的值,其他值就是插入到它左侧还是右侧的问题
    {
         if (L->r[i]<L->r[i- 1]) //
        {
            L->r[ 0]=L->r[i]; //设置哨兵
             for (j=i- 1;L->r[j]>L->r[ 0] && j >=  0;j--)
            {
                L->r[j+ 1]=L->r[j];
            }
            L->r[j+ 1]=L->r[ 0];
        }
    }
 }

  void ShellSort(SqList*L) //希尔排序
 {
     int i,j;
     int increment=L->length;
     do
    {
        increment=increment/ 3+ 1//增量序列,每次距离减小
         for (i=increment+ 1;i<=L->length;i++)
        {
             if (L->r[i]<L->r[i-increment])
            {
                L->r[ 0]=L->r[i];
                 for (j=i-increment;j> 0&&L->r[ 0]<L->r[j];j-=increment)
                {
                    L->r[j+increment]=L->r[j]; //记录后移,查找插入位置
                }
                L->r[j+increment]=L->r[ 0]; //插入
            }
        }
    }  while (increment> 1);
 }

  //堆排序,适用于完全二叉树,元素个数为2的n次方+1
  void HeapSort(SqList *L)
 {
     int i;
     for (i=L->length/ 2;i> 0;i--) //将原始序列转为堆序列,为什么是length/2,?因为根据完全二叉树的性质,每个双亲访问其子孩子可完全遍历整棵树
    {
        HeapAdjust(L,i,L->length);
    }

     for (i=L->length;i> 1;i--) //将堆顶元素与最末元素交换,继续调整序列为堆序列
    {
        swap(L, 1,i);
        HeapAdjust(L, 1,i- 1);
    }
 } //最终L为有序序列

  void HeapAdjust(SqList*L, int s, int m)
 {
     int temp,j;
    temp=L->r[s];
     for (j= 2*s;j<=m;j*= 2)
    {
         if (j<m&&L->r[j]<L->r[j+ 1])
        {
            ++j;
        }
         if (temp>=L->r[j])
        {
             break;
        }
        L->r[s]=L->r[j];
        s=j;
    }
    L->r[s]=temp; //插入
 }

  //归并排序,占用内存较多
  void MergeSort(SqList*L)
 {
    MSort(L->r,L->r, 1,L->length);
 }

  void MSort( int SR[], int TR1[], int s, int t)
 {
     int m;
     int TR2[MAXSIZE+ 1];
     if (s==t)
    {
        TR1[s]=SR[s];
    }
     else
    {
        m=(s+t)/ 2; //将SR[s……t]平分为SR[s……m]和ST[m+1……t]
        MSort(SR,TR2,s,m); //递归将SR[s……m]归并为有序的TR2[s……m]
        MSort(SR,TR2,m+ 1,t); //递归将SR[m+1……t]归并为有序TR2[m+1……t]
        merge(TR2,TR1,s,m,t); //将TR2[s……m]和TR2[m+1……t]归并到TR1[s……t]
    }
 }

  void Merge( int SR[], int TR[], int i, int m, int n) //将有序的SR[s……m]和ST[m+1……t]归并为有序的TR[i……n]
 {
     int j,k,l;
     for (j=m+ 1,k=i;i<=m&&j<=n;k++) //将SR中记录由小到大归并乳TR
    {
         if (SR[i]<SR[j])
        {
            TR[k]=SR[i++];
        }
         else
            TR[k]=SR[j++];
    }

     if(i<=m) //将剩余的SR[i……m]复制到TR
    {
         for (l= 0;l<=m-i;l++)
        {
            TR[k+l]=SR[i+ 1];
        }

    }

     if (j<=n) //将剩余的SR[j……n]复制到TR
    {
         for (l= 0;l<=n-j;l++)
        {
            TR[k+l]=SR[j+ 1];
        }
    }
 }

  void MergeSort2(SqList* L) //不用递归的归并排序
 {
     int* TR=( int*)malloc(L->length* sizeof( int)); //申请额外空间
     int k= 1;
     while (k<L->length)
    {
        MergePass(L->r,TR,k,L->length);
        k= 2*k;
        MergePass(TR,L->r,k,L->length);
        k= 2*k;
    }
 }

  void MergePass( int SR[], int TR[], int s, int n) //将SR中相邻长度为s的子序列两两归并到TR[]
 {
     int i= 1;
     int j;
     while (i<=n- 2*s+ 1)
    {
        Merge(SR,TR,i,i+s- 1,i+ 2*s- 1);
        i=i+ 2*s;
    }
     if (i<n-s+ 1)
    {
        Merge(SR,TR,i,i+s- 1,n);

    }
     else
         for (j=i;j<=n;j++)
        {
            TR[j]=SR[j];
        }
 }

  //快速排序
  void QuickSort(SqList*L)
 {
    QSort(L, 1,L->length);
 }
  void QSort(SqList*L, int low, int high) //对顺序表L中的子序列L->r[low...high]做快速排序
 {
     int pivot;
     if (low<high)
    {
        pivot=Partition(L,low,high); //将L->r[low...high]一分为二,算出枢轴值pivot
        QSort(L,low,pivot- 1); //对低子表递归排序
        QSort(L,pivot+ 1,high); //对高子表递归排序
    }
 }

  //partition作用就是选取序列当中的一个关键字,想尽办法将其放到一个位置,使得它左边的值都比它小,右边都比它大,这样的关键字称为枢轴
  int Partition(SqList*L, int low, int high)
 {
     int pivotKey;
     //优化选取枢轴值 三值取中 开始
  //     int m=low+(high-low)/2;
  //     if (L->r[low]>L->r[high])
  //     {
  //         swap(L,low,high);
  //     }
  //     if (L->r[m]>L->r[high])
  //     {
  //         swap(L,high,m);
  //     }
  //     if (L->r[m]>L->r[low])
  //     {
  //         swap(L,m,low);
  //     }
     //此时L->r[low]已经为整个序列左中右三个关键字的中间值
     //优化选取枢轴值 三值取中 结束

    pivotKey=L->r[low]; //用子表的第一个记录做枢轴记录
     while (low<high) //从表的两端交替向中间扫描
    {
         while (low<high&&L->r[high]>=pivotKey)
        {
            high--;
        }
        swap(L,low,high); //将比枢轴记录小的记录交换到低端
         while (low<high&&L->r[low]<=pivotKey)
        {
            low++;
        }
        swap(L,low,high); //将比枢轴记录大的记录交换到高端
    }
     return low; //返回枢轴所在位置
 }

  int Partition1(SqList*L, int low, int high) //优化不必要的交换
 {
     int pivotkey;
    pivotkey=L->r[low];
    L->r[ 0]=pivotkey; //将枢轴值备份到L->r[0]
     while (low<high)
    {
         while(low<high&&L->r[high]>=pivotkey)
            high--;
        L->r[low]=L->r[high]; //采用替换而不是交换的方式进行操作
         while(low<high&&L->r[low]<=pivotkey)
            low++;
        L->r[high]=L->r[low]; //采用替换而不是交换的方式进行操作
    }
    L->r[low]=L->r[ 0]; //将枢轴值替换为L->r[low]
     return low;
 }

  //优化小数组时的排序方案,小数组排序直接插入式简单排序中性能最好的
  #define MAX_LENGTH_INSERT_SORT  7

  void QSort(SqList&L, int low, int high)
 {
     int pivot;
     if ((high-low)>MAX_LENGTH_INSERT_SORT)
    {
        pivot=Partition(&L,low,high);

        QSort(&L,low,pivot- 1);
        QSort(&L,pivot+ 1,high);
    }
     else
        InsertSort(&L);
 }

  //优化递归操作,用到了以上的优化内容,可以说是总的优化
  void QSort1(SqList*L, int low, int high)
 {
     int pivot;
     if ((high-low)>MAX_LENGTH_INSERT_SORT)
    {
         while(low<high)
        {
            pivot=Partition1(L,low,high);
            QSort1(L,low,pivot- 1);
            low=pivot+ 1;
        }
    }
     else
        InsertSort(L);
 }

  //图
  //图的存储结构
  //邻接矩阵   用两个数组来表示图,一维数组存储顶点信息,二维数组存储边或弧的信息
  typedef  char VertexType;
  typedef  int EdgeType;
  #define MAXVEX  100              //最大定点数
  #define INFINITY  65535          //用65535表示无穷
  typedef  struct
 {
    VertexType vexs[MAXVEX]; //顶点表
    EdgeType arc[MAXVEX][MAXVEX]; //邻接矩阵  NXN
     int numVertexes,numEdges; //图中当前的顶点数和边数
 }MGraph;
  void CreateMGraph(MGraph*G)   //无向图
 {
     int i,j,k,w;
    printf( "输入顶点数和边数\n");
    scanf( "%d,%d",&G->numVertexes,&G->numEdges);
     for (i= 0;i<G->numVertexes;i++) //建立顶点表
    {
        scanf(&G->vexs[i]);
    }

     for (i= 0;i<G->numVertexes;i++)   //邻接矩阵初始化
    {
         for (j= 0;j<G->numVertexes;j++)
        {
            G->arc[i][j]=INFINITY;
        }
    }

     for(k= 0;k<G->numEdges;k++)
    {
        printf( "输入边(Vi,Vj)的小标i,下标j和权w:\n"); //w非1时,就可认为是网
        scanf( "%d,%d,%d",&i,&j,&w);
        G->arc[i][j]=w;
        G->arc[j][i]=G->arc[i][j]; //无向图,矩阵对称,对于有向图此句可省去
    }
 }


  //邻接表
  typedef  struct EdgeNode //边表结点
 {
     int adjvex; //邻接点域,存储该顶点对应的下标
    EdgeType weight; //存储权值,对于非网图不需要
     struct EdgeNode* next; //指向下一个邻接点
 }EdgeNode;

  typedef  struct VertexNode //顶点表结点
 {
    VertexNode data; //顶点域,存储顶点信息
    EdgeNode* firstedge; //边表头指针
 }VertexNode,AdjList[MAXVEX];


  typedef  struct
 {
    AdjList adjList;
     int numVertexes,numEdges; //图中当前顶点数和边数
 }GraphAdjList;

  void CreateALGraph(GraphAdjList* G) //无向图邻接表的创建
 {
     int i,j,k;
    EdgeNode* e;
    printf( "输入顶点数和边数:\n");
    scanf( "%d,%d",&G->numVertexes,&G->numEdges);

     for (i= 0;i<G->numVertexes;i++)   //输入顶点信息
    {
        scanf(&G->adjList[i].data);
        G->adjList[i].firstedge= NULL;
    }

     for (k= 0;k<G->numEdges;k++)
    {
        printf( "输入边(Vi,Vj)上的顶点序号:\n");
        scanf( "%d,%d",&i,&j);

        e=(EdgeNode*)malloc( sizeof(EdgeNode));   //i要指向j
        e->adjvex=j;
        e->next=G->adjList[i].firstedge;
        G->adjList[i].firstedge=e;

        e=(EdgeNode*)malloc( sizeof(EdgeNode)); //j要指向i
        e->adjvex=i;
        e->next=G->adjList[j].firstedge;
        G->adjList[j].firstedge=e;
    }
 }


  //邻接矩阵的深度优先递归算法
  bool visisted[MAX];
  void DFS(MGraph G, int i)
 {
     int j;
    visisted[i]= true;
    printf( "%c",G.vexs[i]); //打印顶点也可以做其他操作
     for (j= 0;j<G.numVertexes;j++)
    {
         if (G.arc[i][j]== 1&&!visisted[j])
        {
            DFS(G,j); //对未访问的邻接顶点递归调用
        }
    }

 }

  //邻接矩阵的深度遍历操作
  void DFSTraverse(MGraph G)
 {
     int i;
     for (i= 0;i<G.numVertexes;i++) //初始所有顶点都是未访问过的状态
    {
        visisted[i]= false;
    }
     for (i= 0;i<G.numVertexes;i++) //对未访问过的顶点调用DFS,若是连通图,只会执行一次
    {
         if (!visisted[i])
        {
            DFS(G,i);
        }
    }
 }


  //邻接表的深度优先递归算法
  void DFS(GraphAdjList GL, int i)
 {
    EdgeNode *p;
    visisted[i]= true;
    printf( "%c",GL.adjList[i].data);
    p=GL.adjList[i].firstedge;
     while (p)
    {
         if (!visisted[p->adjvex])
        {
            DFS(GL,p->adjvex);
        }
        p=p->next;
    }
 }


  //邻接表的深度遍历操作
  void DFSTraverse(GraphAdjList GL)
 {
     int i;
     for (i= 0;i<GL.numVertexes;i++)
    {
        visisted[i]= false;
    }
     for (i= 0;i<GL.numVertexes;i++)
    {
         if (!visisted[i])
        {
            DFS(GL,i);
        }
    }
 }


  //邻接矩阵的广度遍历算法
  void BFSTraverse(MGraph G)
 {
     int i,j;
    SqQueue Q;
     for(i= 0;i<G.numVertexes;i++)
        visisted[i]= false;
    InitQueue(&Q);   //初始化辅助用队列
     for (i= 0;i<G.numVertexes;i++) //对每一个顶点做循环
    {
         if (!visisted[i])
        {
            visisted[i]= true; //设置当前点访问过
            printf( "%c",G.vexs[i]);
            EnQueue(&Q,i); //将次顶点入队列
             while(!QueueLength(Q)> 0) //若当前队列不为空
            {
                DeQueue(&Q,&i); //将队列中元素出队列赋给i
                 for (j= 0;j<G.numVertexes;j++)
                {
                     if (G.arc[i][j]== 1&&!visisted[j]) //判断其他顶点若与当前顶点存在边且未访问过
                    {
                        visisted[j]= true;
                        printf( "%c",G.vexs[j]);
                        EnQueue(&Q,j);
                    }
                }
            }

        }
    }
 }


  //邻接表的广度遍历算法
  void BFSTraverse(GraphAdjList GL)
 {
     int i;
    EdgeNode* p;
    SqQueue Q;
     for (i= 0;i<GL.numVertexes;i++)
    {
        visisted[i]= false;
    }
    InitQueue(&Q);
     for (i= 0;i<GL.numVertexes;i++)
    {
         if (!visisted[i])
        {
            visisted[i]= true;
            printf( "%c",GL.adjList[i].data);
            EnQueue(&Q,I);
             while(QueueLength(Q)> 0)
            {
                DeQueue(&Q,&i);
                p=GL.adjList[i].firstedge;
                 while(p)
                {
                     if (!visisted[p->adjvex])
                    {
                        visisted[p->adjvex]= true;
                        printf( "%c",GL.adjList[p->adjvex].data);
                        EnQueue(&Q,p->adjvex);
                    }
                    p=p->next;
                }
            }
        }
    }

 }


  //最小生成树 普里姆算法(Prim) 查找遍历每个顶点的最短路径  邻接矩阵
  void MiniSpanTree_Prim(MGraph G)
 {
     int min,i,j,k;
     int adjvex[MAXVEX]; //保存相关顶点下标

     int lowcost[MAXVEX]; //保存相关顶点间边的权值
    lowcost[ 0]= 0; //初始化第一个权值为0

    adjvex[ 0]= 0; //初始化第一个顶点下标为0
     for (i= 1;i<G.numVertexes;i++) //循环除下标为0外的全部顶点
    {
        lowcost[i]=G.arc[ 0][i]; //将V0顶点与之有边的权值存入数组
        adjvex[i]= 0; //初始化都为v0的下标
    }
     for (i= 1;i<G.numVertexes;i++)
    {
        min=INFINITY; //初始化最小权值
        j= 1;k= 0;
         while(j<G.numVertexes) //循环全部顶点
        {
             if (lowcost[j]!= 0&&lowcost[j]<min) ///如果权值不为0且小于min,则让当前权值成为最小值
            {
                min=lowcost[j];
                k=j; //将当前下标最小值下标存入k
            }
            j++;
        }
        printf( "(%d,%d)",adjvex[k],k); //打印当前顶点边中权值最小边
        lowcost[k]= 0; //将当前顶点的权值设置为0,表示此顶点已经完成任务,不再参与比较
         for (j= 1;j<G.numVertexes;j++) //循环所欲顶点
        {
             if (lowcost[j]!= 0&&G.arc[k][j]<lowcost[j])
            { //若下标为k的顶点各边权值小于此前这些顶点未被加入生成树权值
                lowcost[j]=G.arc[k][j]; //将较小的权值存入lowcost
                adjvex[j]=k; //将下标为k的顶点存入adjvex
            }
        }
    }
 }

  //Kruskal最小生成树
  typedef  struct{
     int begin;
     int end;
     int weight;
 }Edge;

  #define MAXEDGE  65535
  void MiniSpanTree_Kruskal(MGraph G)
 {
     int i,n,m;
    Edge edges[MAXEDGE];
     int parent[MAXVEX];
     for (i= 0;i<G.numVertexes;i++)
    {
        parent[i]= 0;
    }
     for (i= 0;i<G.numEdges;i++)
    {
        n=find(parent,edges[i].begin);
        m=find(parent,edges[i].begin);
         if (n!=m)
        {
            parent[n]=m;
            printf( "(%d,%d) %d",edges[i].begin,edges[i].end,edges[i].weight);
        }
    }
 }

  int Find( int *parent, int f)
 {
     while(parent[f]> 0)
        f=parent[f];
     return f;
 }

  //对于边数少的图用克鲁斯卡尔算法,对稠密图用普利姆算法

  //最短路径      迪杰斯特拉算法(Dijkstra)
  #define MAXVEX  9
  #define INFINITY  65535
  typedef  int Pathmatrix[MAXVEX];
  typedef  int ShortPathTable[MAXVEX];

  void ShortestPath_Dijkstra(MGraph G, int v0,Pathmatrix*P,ShortPathTable*D)
 {
     int v,w,k,min;
     int final[MAXVEX]; //final[w]=1表示求得顶点VO和VW的最短路径
     for (v= 0;v<G.numVertexes;v++) //初始化数据
    {
        final[v]= 0; //全部顶点初始化为未知最短路径状态
        (*D)[v]=G.arc[v0][v]; //将与v0有连线的顶点加上权值
        (*P)[v]= 0; //初始化路径数组P为0

    }

    (*D)[v0]= 0; //v0至v0路径为0
    final[v0]= 1; //v0至v0不需要求路径
     //开始主循环,每次求得v0到某个v顶点的最短路径
     for (v= 1;v<G.numVertexes;v++)
    {
        min=INFINITY; //初始化最小距离
         for (w= 0;w<G.numVertexes;w++) //寻找离v0最近的顶点
        {
             if (!final[w]&&(*D)[w]<min)
            {
                k=w;
                min=(*D)[w]; //w顶点离v0顶点更近
            }
        }
        final[k]= 1; //将目前找到的最近的顶点置为1
         for (w= 0;w<G.numVertexes;w++) //修正当前最短路径及距离
        {
             //如果经过v顶点的路径比现在这条路径的长度短的话,说明找到了更短的路径,修改D[w]和P[w]
             if (!final[w]&&(min+G.arc[k][w]<(*D)[w]))
            {
                (*D)[w]=min+G.arc[k][w];
                (*P)[w]=k;
            }
        }
    }
 }


  //佛洛依德算法,Floyd,求网图G中各顶点v到其余顶点w最短路径P[v][w]及带权长度D[v][w]
  typedef  int Pathmatrix[MAXVEX][MAXVEX];
  typedef  int ShortPathTable[MAXVEX][MAXVEX];

  void ShortestPath_Floyd(MGraph G,Pathmatrix *P,ShortPathTable*D)
 {
     int v,w,k;
     for (v= 0;v<G.numVertexes;++v) //初始化D与P
    {
         for (w= 0;w<G.numVertexes;++w)
        {
            (*D)[v][w]=G.arc[v][w]; //D[v][w]值即为对应点的权值
            (*P)[v][w]=w; //初始化P
        }
    }

     for (k= 0;k<G.numVertexes;++k) //k代表中转顶点的下标
    {
         for (v= 0;v<G.numVertexes;++v) //v代表其实顶点
        {
             for (w= 0;w<G.numVertexes;++w) //w代表结束顶点
            {
                 if ((*D)[v][w]>(*D)[v][k]+(*D)[k][w])
                { //如果经过下标为k顶点路径比原两点间路径更短,将当前两点间权值设为更小的一个
                    (*D)[v][w]=(*D)[v][k]+(*D)[k][w];
                    (*P)[v][w]=(*P)[v][k];
                }
            }
        }
    }
  //求出的最短路径的显示代码
     for (v= 0;v<G.numVertexes;++v)
    {
         for (w=v+ 1;w<G.numVertexes;w++)
        {
            printf( "v%d-v%d weight:%d",v,w,D[v][w]);
            k=P[v][w]; //获取第一个路径顶点下标
            printf( " Path:%d",v); //打印原点
             while (k!=w)
            {
                printf( "->%d",k);
                k=P[k][w]; //获取下一路径顶点下标
            }
            printf( "->%d\n",w); //打印终点
        }
        printf( "\n");
    }
 }


int _tmain( int argc, _TCHAR* argv[])
{
//  LinkStack S;
//  InitStack(&S);
//  Push(&S,3);
//  Push(&S,21);
//  Push(&S,15);
//  int e;
//  Pop(&S,&e);
//  Pop(&S,&e);
//  Pop(&S,&e);
//  cout<<e<<endl;

//  int i;
//  for (i=0;i<20;i++)
//  {
//      printf("%d\n",Fbi(i));
//  }

     return  0;
}



2积分福利。2积分福利。2积分福利。2积分福利。2积分福利。2积分福利。2积分福利。2积分福利。2积分福利。2积分福利。2积分福利。 涵盖广泛 精炼的理论讲述搭配大量经典算法示例,学习查询兼而有之。 阐述到位 算法思想、算法实现和完整示例合理搭配,相辅相成。 示例完善 示例分析精准,代码注释精确,每段代码皆可通过编译执行。 计算机技术的发展和普及不仅改变了人们的生活和娱乐方式,也改变了人们的工作方式,这其中最为重要的便是计算机编程技术。现代的设计任务大多通过代码编程交给计算机来完成,其中算法起到了至关重要的作用。可以毫不夸张地说,算法是一切程序设计的灵魂和基础。 《C/C++常用算法手册》分3篇,共13章,“第1篇算法基础篇”介绍了算法概述,重点分析了数据结构和基本算法思想;“第2篇算法基本应用篇”详细讲解了算法在排序、查找、数值计算、数论、经典趣题和游戏中的应用;“第3篇算法高级应用篇”讲解了算法的一些高级应用技术,包括在密码学和数据压缩/解压缩中的应用。 《C/C++常用算法手册》知识点覆盖全面、结构安排紧凑、讲解详细、示例丰富。《C/C++常用算法手册》对每一个知识点都给出了相应的算法及应用示例。虽然这些例子都是以C语言来编写的,但是算法并不局限于C语言。如果读者采用其他编程语言,例如C++、C#、VB、Java等,根据其语法格式进行适当的修改即可。 《C/C++常用算法手册 》主要定位于有一定C/C++语言编程基础、想通过学习算法与数据结构提升编程水平的读者,也可作为具有一定编程经验的程序员以及大中专院校学生学习数据结构和算法的参考书。 第1篇 算法基础篇 1 第1章 算法概述 2 1.1 什么是算法 2 1.2 算法的发展历史 3 1.3 算法的分类 4 1.4 算法相关概念的区别 4 1.5 算法的表示 5 1.5.1 自然语言表示 5 1.5.2 流程图表示 6 1.5.3 N-S图表示 7 1.5.4 伪代码表示 7 1.6 算法的性能评价 8 1.7 算法实例 9 1.7.1 查找数字 9 1.7.2 创建项目 11 1.7.3 编译执行 12 1.8 算法的新进展 13 1.9 小结 14 第2章 数据结构 15 2.1 数据结构概述 15 2.1.1 什么是数据结构 15 2.1.2 数据结构中的基本概念 16 2.1.3 数据结构的内容 16 2.1.4 数据结构的分类 18 2.1.5 数据结构的几种存储方式 18 2.1.6 数据类型 19 2.1.7 常用的数据结构 20 2.1.8 选择合适的数据结构解决实际问题 21 2.2 线性表 21 2.2.1 什么是线性表 21 2.2.2 线性表的基本运算 22 2.3 顺序表结构 23 2.3.1 准备数据 23 2.3.2 初始化顺序表 24 2.3.3 计算顺序表长度 24 2.3.4 插入结点 24 2.3.5 追加结点 25 2.3.6 删除结点 25 2.3.7 查找结点 25 2.3.8 显示所有结点 26 2.3.9 顺序表操作示例 26 2.4 链表结构 30 2.4.1 什么是链表结构 30 2.4.2 准备数据 31 2.4.3 追加结点 31 2.4.4 插入头结点 33 2.4.5 查找结点 33 2.4.6 插入结点 34 2.4.7 删除结点 35 2.4.8 计算链表长度 36 2.4.9 显示所有结点 36 2.4.10 链表操作示例 37 2.5 栈结构 41 2.5.1 什么是栈结构 41 2.5.2 准备数据 42 2.5.3 初始化栈结构 42 2.5.4 判断空栈 43 2.5.5 判断满栈 43 2.5.6 清空栈 43 2.5.7 释放空间 44 2.5.8 入栈 44 2.5.9 出栈 44 2.5.10 读结点数据 45 2.5.11 栈结构操作示例 45 2.6 队列结构 48 2.6.1 什么是队列结构 48 2.6.2 准备数据 49 2.6.3 初始化队列结构 49 2.6.4 判断空队列 50 2.6.5 判断满队列 50 2.6.6 清空队列 50 2.6.7 释放空间 51 2.6.8 入队列 51 2.6.9 出队列 51 2.6.10 读结点数据 52 2.6.11 计算队列长度 52 2.6.12 队列结构操作示例 53 2.7 树结构 56 2.7.1 什么是树结构 56 2.7.2 树的基本概念 56 2.7.3 二叉树 57 2.7.4 准备数据 61 2.7.5 初始化二叉树 61 2.7.6 添加结点 62 2.7.7 查找结点 63 2.7.8 获取左子树 64 2.7.9 获取右子树 64 2.7.10 判断空树 65 2.7.11 计算二叉树深度 65 2.7.12 清空二叉树 65 2.7.13 显示结点数据 66 2.7.14 遍历二叉树 66 2.7.15 树结构操作示例 68 2.8 图结构 71 2.8.1 什么是图结构 71 2.8.2 图的基本概念 72 2.8.3 准备数据 76 2.8.4 创建图 78 2.8.5 清空图 79 2.8.6 显示图 79 2.8.7 遍历图 80 2.8.8 图结构操作示例 81 2.9 小结 84 第3章 基本算法思想 85 3.1 常用算法思想概述 85 3.2 穷举算法思想 85 3.2.1 穷举算法基本思想 86 3.2.2 穷举算法示例 86 3.3 递推算法思想 88 3.3.1 递推算法基本思想 88 3.3.2 递推算法示例 88 3.4 递归算法思想 90 3.4.1 递归算法基本思想 90 3.4.2 递归算法示例 90 3.5 分治算法思想 92 3.5.1 分治算法基本思想 92 3.5.2 分治算法示例 92 3.6 概率算法思想 96 3.6.1 概率算法基本思想 96 3.6.2 概率算法示例 97 3.7 小结 98 第2篇 算法基本应用篇 99 第4章 排序算法 100 4.1 排序算法概述 100 4.2 冒泡排序法 101 4.2.1 冒泡排序算法 101 4.2.2 冒泡排序算法示例 102 4.3 选择排序法 104 4.3.1 选择排序算法 104 4.3.2 选择排序算法示例 105 4.4 插入排序法 107 4.4.1 插入排序算法 107 4.4.2 插入排序算法示例 108 4.5 Shell排序法 110 4.5.1 Shell排序算法 110 4.5.2 Shell排序算法示例 111 4.6 快速排序法 113 4.6.1 快速排序算法 113 4.6.2 快速排序算法示例 114 4.7 堆排序法 116 4.7.1 堆排序算法 116 4.7.2 堆排序算法示例 121 4.8 合并排序法 123 4.8.1 合并排序算法 123 4.8.2 合并排序算法示例 126 4.9 排序算法的效率 129 4.10 排序算法的其他应用 130 4.10.1 反序排序 130 4.10.2 字符串数组的排序 132 4.10.3 字符串的排序 135 4.11 小结 137 第5章 查找算法 138 5.1 查找算法概述 138 5.2 顺序查找 138 5.2.1 顺序查找算法 139 5.2.2 顺序查找操作示例 139 5.3 折半查找 141 5.3.1 折半查找算法 141 5.3.2 折半查找操作示例 142 5.4 数据结构中的查找算法 145 5.4.1 顺序表结构中的查找算法 145 5.4.2 链表结构中的查找算法 148 5.4.3 树结构中的查找算法 151 5.4.4 图结构中的查找算法 152 5.5 小结 153 第6章 基本数学问题 154 6.1 判断闰年 154 6.2 多项式计算 156 6.2.1 —维多项式求值 156 6.2.2 二维多项式求值 158 6.2.3 多项式乘法 160 6.2.4 多项式除法 161 6.3 随机数生成算法 164 6.4 复数运算 171 6.4.1 简单的复数运算 172 6.4.2 复数的幂运算 174 6.4.3 复指数运算 176 6.4.4 复对数运算 177 6.4.5 复正弦运算 178 6.4.6 复余弦运算 179 6.5 阶乘 180 6.6 计算π的近似值 183 6.6.1 割圆术 183 6.6.2 蒙特卡罗算法 185 6.6.3 级数公式 187 6.7 矩阵运算 190 6.7.1 矩阵加法 190 6.7.2 矩阵减法 191 6.7.3 矩阵乘法 193 6.8 方程求解 195 6.8.1 线性方程求解——高斯消元法 195 6.8.2 非线性方程求解——二分法 200 6.8.3 非线性方程求解——牛顿迭代法 202 6.9 小结 205 第7章 复杂的数值计算算法 206 7.1 拉格朗日插值 206 7.1.1 拉格朗日插值算法 206 7.1.2 拉格朗日插值示例 207 7.2 数值积分 210 7.2.1 数值积分算法 210 7.2.2 数值积分示例 211 7.3 开平方 213 7.3.1 开平方算法 213 7.3.2 开平方示例 213 7.4 极值问题的求解算法 215 7.4.1 极值求解算法 215 7.4.2 极值求解示例 217 7.5 特殊函数的计算算法 221 7.5.1 伽玛函数 221 7.5.2 贝塔函数 224 7.5.3 正弦积分函数 228 7.5.4 余弦积分函数 231 7.5.5 指数积分函数 235 7.6 小结 239 第8章 经典数据结构问題 240 8.1 动态数组排序 240 8.1.1 动态数组的存储和排序 240 8.1.2 动态数组排序示例 241 8.2 约瑟夫环 243 8.2.1 简单约瑟夫环算法 243 8.2.2 简单约瑟夫环求解 245 8.2.3 复杂约瑟夫环算法 247 8.2.4 复杂约瑟夫环求解 248 8.3 城市之间的最短总距离 250 8.3.1 最短总距离算法 250 8.3.2 最短总距离求解 253 8.4 最短路径 257 8.4.1 最短路径算法 258 8.4.2 最短路径求解 260 8.5 括号匹配 265 8.5.1 括号匹配算法 265 8.5.2 括号匹配求解 267 8.6 小结 270 第9章 数论问题 271 9.1 数论 271 9.1.1 数论概述 271 9.1.2 数论的分类 272 9.1.3 初等数论 273 9.1.4 基本概念 273 9.2 完全数 274 9.2.1 完全数概述 274 9.2.2 计算完全数算法 275 9.3 亲密数 277 9.3.1 亲密数概述 277 9.3.2 计算亲密数算法 277 9.4 水仙花数 280 9.4.1 水仙花数概述 280 9.4.2 计算水仙花数算法 281 9.5 自守数 283 9.5.1 自守数概述 283 9.5.2 计算自守数算法 284 9.6 最大公约数 287 9.6.1 计算最大公约数算法——搌转相除法 287 9.6.2 计算最大公约数算法一一Stein算法 288 9.6.3 计算最大公约数示例 289 9.7 最小公倍数 290 9.8 素数 292 9.8.1 素数概述 292 9.8.2 计算素数算法 292 9.9 回文素数 294 9.9.1 回文素数概述 294 9.9.2 计算回文素数算法 294 9.10 平方回文数 297 9.10.1 平方回文数概述 297 9.10.2 计算平方回文数算法 297 9.11 分解质因数 299 9.12 小结 301 第10 章算法经典趣题 302 0. .l 百钱买百鸡 302 10.1.1 百钱买百鸡算法 302 10.1.2 百钱买百鸡求解 303 10.2 五家共井 304 10.2.1 五家共井算法 304 10.2.2 五家共井求解 305 10.3 鸡兔同笼 307 10.3.1 鸡兔同笼算法 307 10.3.2 鸡兔同笼求解 308 10.4 猴子吃桃 308 10.4.1 猴子吃桃算法 308 10.4.2 猴子吃桃求解 309 10.5 舍罕王赏麦 310 10.5.1 舍罕王赏麦问题 310 10.5.2 舍罕王赏麦求解 311 10.6 汉诺塔 312 10.6.1 汉诺塔算法 312 10.6.2 汉诺塔求解 314 10.7 窃贼问题 315 10.7.1 窃贼问题算法 315 10.7.2 窃贼问题求解 317 10.8 马踏棋盘 320 10.8.1 马踏棋盘算法 320 10.8.2 马踏棋盘求解 321 10.9 八皇后问题 323 10.9.1 八皇后问题算法 324 10.9.2 八皇后问题求解 325 10.10 寻找假银币 327 10.10.1 寻找假银币算法 327 10.10.2 寻找假银币求解 329 10.11 青蛙过河 331 10.11.1 青蛙过河算法 331 10.11.2 青蛙过河求解 333 10.12 三色旗 335 10.12.1 三色旗算法 335 10.12.2 三色旗求解 337 10.13 渔夫捕鱼 339 10.13.1 渔夫捕鱼算法 339 10.13.2 渔夫捕魚求解 340 10.14 爱因斯坦的阶梯 341 10.14.1 爱因斯坦的阶梯算法 341 10.14.2 爱因斯坦的阶梯求解 342 10.15 兔子产仔 342 10.15.1 兔子产仔算法 343 10.15.2 兔子产仔求解 343 10.16 常胜将军 344 10.16.1 常胜将军算法 344 10.16.2 常胜将军求解 345 10.17 新郎和新娘 346 10.17.1 新郎和新娘算法 347 10.17.2 新郎和新娘求解 348 10.18 三色球 349 10.18.1 三色球算法 349 10.18.2 三色球求解 350 10.19 小结 351 第11章 游戏中的算法 352 11.1 洗扑克牌 352 11.1.1 洗扑克牌算法 352 11.1.2 洗扑克牌示例 353 11.2 取火柴游戏 356 11.2.1 取火柴游戏算法 356 11.2.2 取火柴游戏示例 357 11.3 10点半 358 11.3.1 10点半算法 358 11.3.2 10点半游戏示例 363 11.4 生命游戏 368 11.4.1 生命游戏的原理 368 11.4.2 生命游戏的算法 369 11.4.3 生命游戏示例 371 11.5 小结 376 第3篇 算法高级应用篇 377 第12章 密码学算法 378 12.1 密码学概述 378 12.1.1 密码学的发展 378 12.1.2 密码学的基本概念 379 12.1.3 柯克霍夫斯原则 379 12.1.4 经典密码学算法 380 12.2 换位加密解密 381 12.2.1 换位加密解密算法 381 12.2.2 换位加密解密算法示例 383 12.3 替换加密解密 386 12.3.1 替换加密解密算法 386 12.3.2 替换加密解密算法示例 388 12.4 位加密解密 389 12.4.1 位加密解密算法 390 12.4.2 位加密解密算法示例 391 12.5 一次一密加密解密算法 392 12.5.1 一次一密加密解密算法 392 12.5.2 一次一密加密解密算法示例 394 12.6 小结 396 第13章 压缩与解压缩算法 397 13.1 压缩与解压缩概述 397 13.1.1 压缩与解压缩分类 397 13.1.2 典型的压缩解压缩算法 397 13.2 压缩算法 398 13.3 解压缩算法 401 13.4 压缩/解压缩示例 404 13.5 小结 406
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值