├── .gitignore ├── README.md ├── include ├── chapter10 │ └── Exercise10_1_2.h ├── chapter13 │ └── redBlackTree.h ├── chapter14 │ ├── exercise14_2.h │ └── section14_1.h ├── chapter15 │ └── Exercise15_1.h ├── chapter16 │ ├── Exercise16_2_6.h │ └── chapter16.h ├── chapter20 │ └── FibHeap.h ├── chapter22 │ ├── Exercise22_3_6.h │ └── Exercise22_4_2.h ├── chapter26 │ └── MaxFlow.h ├── chapter6 │ ├── Exercise6_5_8.h │ └── Young.h ├── chapter7 │ ├── Exercise7_1_2.h │ ├── Exercise7_6.h │ └── quickSort.h ├── chapter8 │ ├── Chapter8.h │ └── chapter8.h ├── chapter9 │ ├── Chapter9.h │ └── Exercise9_1_1.h └── others │ ├── BigNumber.h │ ├── Chapter10.h │ ├── Heap.h │ ├── array.h │ ├── binarySearchTree.h │ ├── intervalTree.h │ ├── queue.h │ ├── sort.h │ └── stack.h ├── src ├── UnionFindSet.cpp ├── chapter10 │ ├── Exercise10_1_2.cpp │ ├── Exercise10_2_8.cpp │ └── Exercise10_3_4.cpp ├── chapter13 │ └── redBlackTree.cpp ├── chapter14 │ ├── exercise14_2.cpp │ ├── exercise14_3_6.cpp │ ├── section14_1.cpp │ ├── section14_2.cpp │ └── section14_3.cpp ├── chapter15 │ ├── Exercise15_1.cpp │ └── Exercise15_3.cpp ├── chapter16 │ ├── Exercise16_1_1.cpp │ ├── Exercise16_2_6.cpp │ └── chapter16.cpp ├── chapter20 │ └── FibHeap.cpp ├── chapter22 │ ├── Exercise22_3_6.cpp │ ├── Exercise22_4_2.cpp │ ├── section22_3.cpp │ ├── section22_4.cpp │ └── section22_5.cpp ├── chapter26 │ └── MaxFlow.cpp ├── chapter6 │ ├── Exercise6_5_8.cpp │ ├── Heap.h │ └── Young.cpp ├── chapter7 │ ├── Exercise7_1_2.cpp │ ├── Exercise7_4_5.cpp │ ├── Exercise7_5.cpp │ ├── Exercise7_6.cpp │ └── quickSort.cpp ├── chapter8 │ ├── Exercise8_3.cpp │ ├── Exercise8_3_4.cpp │ ├── chapter8.cpp │ └── test.cpp ├── chapter9 │ ├── Exercise9_1_1.cpp │ ├── Exercise9_3_6.cpp │ └── Exercise9_3_8.cpp └── others │ ├── BigNumber.cpp │ ├── array.cpp │ ├── binarySearchTree.cpp │ ├── intervalTree.cpp │ ├── queue.cpp │ ├── sort.cpp │ └── stack.cpp └── tst ├── Main_TestAll.cpp ├── chapter10 ├── Exercise10_1_2Test.cpp └── Exercise10_2_8Test.cpp ├── chapter13 └── redBlackTreeTest.cpp ├── chapter14 ├── makefile.mk ├── section14_1Test.cpp └── section14_3Test.cpp ├── chapter15 ├── Exercise15_1Test.cpp ├── Exercise15_3Test.cpp └── makefile.mk ├── chapter16 ├── Exercise16_2_6Test.cpp ├── chapter16Test.cpp └── makefile.mk ├── chapter20 └── FibHeapTest.cpp ├── chapter22 ├── Exercise22_3_6Test.cpp ├── Exercise22_4_2Test.cpp ├── makefile.mk └── section22_3Test.cpp ├── chapter26 └── MaxFlowTest.cpp ├── chapter6 ├── Exercise6_5_8Test.cpp └── HeapTest.cpp ├── chapter7 ├── Exercise7_1_2Test.cpp ├── Exercise7_6Test.cpp ├── makefile.mk └── quickSortTest.cpp ├── chapter8 ├── Exercise8_3Test.cpp ├── chapter8Test ├── chapter8Test.cpp └── makefile.mk ├── chapter9 ├── Exercise9_1_1Test.cpp ├── Exercise9_3_6Test.cpp ├── Exercise9_3_8Test.cpp └── makefile.mk ├── coverage.sh ├── makefile └── others ├── BigNumberTest.cpp ├── binarySearchTreeTest.cpp ├── intervalTreeTest.cpp └── sortTest.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.d 2 | *.o 3 | *.oxx 4 | *.cpp~ 5 | **/tst/testAll 6 | *.gcda 7 | *.gcno 8 | log.info 9 | result 10 | *.sh 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Hello exerciseForAlgorithmSecond 2 | 3 | STEP 1: install gtest 4 | reference: http://blog.csdn.net/mishifangxiangdefeng/article/details/49225961 5 | 6 | STEP 2: build tests 7 | cd tst 8 | make 9 | 10 | STEP 3: run tests 11 | ./testAll 12 | -------------------------------------------------------------------------------- /include/chapter10/Exercise10_1_2.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: Exercise10_1_2.h 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Sat 24 Oct 2015 03:56:10 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | //用一个数组实现两个栈 12 | class arrayWithTwoStack 13 | { 14 | //栈1和栈2的栈顶指针 15 | int top1, top2;//分别初始化为0和n+1 16 | int len;//数组长度 17 | int *s;//数组 18 | public: 19 | arrayWithTwoStack(int size):top1(0),top2(size+1),len(size){s = new int[size+1];} 20 | bool isEmpty(int index); 21 | void push(int index, int data); 22 | int pop(int index); 23 | }; 24 | -------------------------------------------------------------------------------- /include/chapter13/redBlackTree.h: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define BLACK 0 5 | #define RED 1 6 | 7 | struct node 8 | { 9 | node *left; 10 | node *right; 11 | node *p; 12 | int key; 13 | bool color; 14 | node *init; 15 | node(int k, node *init = NULL):init(init),left(init),right(init),p(init),key(k),color(BLACK){} 16 | ~node() 17 | { 18 | if(left != init) delete left; 19 | if(right != init) delete right; 20 | } 21 | void print(){ 22 | cout< File Name: ../include/chapter14/exercise14_2.h 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Sat 28 Nov 2015 04:58:08 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | #include 12 | 13 | vector josefInOsTree(vector input, int m); 14 | -------------------------------------------------------------------------------- /include/chapter14/section14_1.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: section14_1.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Mon 23 Nov 2015 07:53:37 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | #define BLACK 0 12 | #define RED 1 13 | 14 | //红黑树结点结构 15 | struct ostNode 16 | { 17 | //红黑树的基础结构 18 | ostNode *left; 19 | ostNode *right; 20 | ostNode *parent; 21 | int key; 22 | int info; 23 | bool color; 24 | int size;//以x为根的子树的(内部)结点数(包括x本身),即子树的大小 25 | ostNode *init; 26 | ostNode(ostNode *init, int k) 27 | :init(init),left(init),right(init),parent(init),key(k),color(BLACK),size(1){} 28 | ~ostNode() 29 | { 30 | if(left != init) delete left; 31 | if(right != init) delete right; 32 | } 33 | }; 34 | //顺序统计量树结构 35 | class Os_Tree 36 | { 37 | #ifdef __UT__ 38 | public: 39 | #else 40 | private: 41 | #endif 42 | ostNode *root;//根结点 43 | static ostNode *nil;//哨兵 44 | ostNode *getPositionToInsert(ostNode *z); 45 | void insertChild(ostNode *parent, ostNode *child); 46 | ostNode *search(ostNode *x, int k); 47 | ostNode * findTheNodeToRemove(ostNode *z); 48 | void removeReally(ostNode *toRemove); 49 | ostNode *getChild(ostNode *parent); 50 | ostNode *successor(ostNode *x); 51 | ostNode *minimum(ostNode *x); 52 | void insertFixup(ostNode *z); 53 | void leftRotate(ostNode *x); 54 | void rightRotate(ostNode *x); 55 | void removeFixup(ostNode *x); 56 | ostNode *select(ostNode *x, int i); 57 | public: 58 | Os_Tree(){nil->size = 0;root = nil;}; 59 | ~Os_Tree(); 60 | void insert(int key, int info /* = 0 */); 61 | ostNode *search(int k); 62 | ostNode *remove(ostNode *z); 63 | static bool isNodeNull(ostNode *z); 64 | ostNode *select(int i); 65 | }; 66 | 67 | 68 | -------------------------------------------------------------------------------- /include/chapter15/Exercise15_1.h: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | struct coord 5 | { 6 | int x; 7 | int y; 8 | }; 9 | 10 | double Double_adjustable_Euclidean_traveling_salesman(vector s); 11 | 12 | -------------------------------------------------------------------------------- /include/chapter16/Exercise16_2_6.h: -------------------------------------------------------------------------------- 1 | //物品信息 2 | struct node 3 | { 4 | int weight; 5 | int value; 6 | }; 7 | 8 | double partialPackage(int weight, int len, node *material); 9 | -------------------------------------------------------------------------------- /include/chapter16/chapter16.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //一个活动用一个结点表示 4 | struct activity 5 | { 6 | int id; 7 | int start; 8 | int finish; 9 | }; 10 | 11 | vector Reccursive_Activity_Selector(vector A); 12 | vector Greedy_Activity_Selector(vector A); 13 | -------------------------------------------------------------------------------- /include/chapter20/FibHeap.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: fibHeap.h 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Sun 25 Oct 2015 10:28:20 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | enum errorType 12 | { 13 | SUCCESS = 0, 14 | PARAM_ERROR, 15 | POINTER_NULL 16 | }; 17 | 18 | struct node 19 | { 20 | int key; 21 | node *pParent; 22 | node *pChild; 23 | node *pLeft; 24 | node *pRight; 25 | int degree; 26 | bool isOneChildDeleted; 27 | bool isHandled; 28 | node(int n) 29 | :key(n),pParent(NULL),pChild(NULL),pLeft(this),pRight(this),degree(0),isOneChildDeleted(false),isHandled(0){} 30 | }; 31 | 32 | class CFibHeap 33 | { 34 | int dataCount; 35 | node *pMinNode; 36 | 37 | void consolidate(); 38 | void link(node *y, node *x); 39 | void moveNodeToRootList(node *pNode); 40 | bool isNodeInHeap(node *pNode); 41 | void addNodeToRootList(node *pNode); 42 | void addListToRootList(node *pNode); 43 | void removeNodeFromRootList(node *pRootNode); 44 | void addChildToParent(node *pChild, node *pParent); 45 | void deleteChildFromParent(node *pNode); 46 | bool isNeedMoveToRootLost(node *pNode); 47 | public: 48 | CFibHeap():dataCount(0),pMinNode(NULL){}; 49 | errorType insert(node *x); 50 | int getDataCount(); 51 | errorType merge(CFibHeap *H2); 52 | node* extract(); 53 | errorType decreaseKey(node *pNodeToDecrease, int newKey); 54 | errorType deleteNode(node *pNode); 55 | }; 56 | -------------------------------------------------------------------------------- /include/chapter22/Exercise22_3_6.h: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define N 10 5 | #define WHITE 0 6 | #define GRAY 1 7 | #define BLACK 2 8 | 9 | //边结点结构 10 | class Edge 11 | { 12 | public: 13 | int start;//有向图的起点 14 | int end;//有向图的终点 15 | Edge *next;//指向同一个起点的下一条边 16 | int type;//边的类型 17 | Edge(int s, int e):start(s),end(e),next(NULL){} 18 | }; 19 | //顶点结点结构 20 | class Vertex 21 | { 22 | public: 23 | int id; 24 | Edge *head;//指向以该顶点为起点的下一条边 25 | int color;//顶点的颜色 26 | Vertex *p;//指向遍历结果的父结点 27 | int d, f;//第一次被发现的时间和结束检查的时间 28 | Vertex(int i):head(NULL),color(WHITE),p(NULL),d(0x7fffffff),id(i){} 29 | }; 30 | //图结构 31 | class Graph 32 | { 33 | public: 34 | Vertex *V[N+1];//N个顶点 35 | Graph() 36 | { 37 | int i; 38 | for(i = 1; i <= N; i++) 39 | V[i] = new Vertex(i); 40 | } 41 | ~Graph() 42 | { 43 | int i; 44 | for(i = 1; i <= N; i++) 45 | delete V[i]; 46 | } 47 | }; 48 | 49 | void InsertEdge(Graph *G, Edge *E); 50 | void DFS(Graph *G); 51 | -------------------------------------------------------------------------------- /include/chapter22/Exercise22_4_2.h: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | namespace exercise22_4_2 5 | { 6 | #define MAX_NUM_OF_VERTEX 100 7 | 8 | //边结点结构 9 | class Edge 10 | { 11 | public: 12 | int start;//有向图的起点 13 | int end;//有向图的终点 14 | Edge *next;//指向同一个起点的下一条边 15 | int type;//边的类型 16 | Edge(int s, int e):start(s),end(e),next(NULL){} 17 | }; 18 | //顶点结点结构 19 | class Vertex 20 | { 21 | public: 22 | int indegree; 23 | Edge *head;//指向以该顶点为起点的下一条边 24 | Vertex():head(NULL),indegree(0){} 25 | }; 26 | 27 | //图结构 28 | class Graph 29 | { 30 | int numOfVertex; 31 | public: 32 | Vertex *V[MAX_NUM_OF_VERTEX+1];//N个顶点 33 | Graph(int n):numOfVertex(n) 34 | { 35 | int i; 36 | for(i = 1; i <= n; i++) 37 | V[i] = new Vertex(); 38 | } 39 | ~Graph() 40 | { 41 | int i; 42 | for(i = 1; i <= numOfVertex; i++) 43 | delete V[i]; 44 | } 45 | void InsertEdge(Edge *E); 46 | int countWays(int start, int end); 47 | }; 48 | }; 49 | -------------------------------------------------------------------------------- /include/chapter26/MaxFlow.h: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include 5 | 6 | #define NMAX 210 7 | 8 | class Mat_Flow 9 | { 10 | public: 11 | int n;//点的个数。其中0是源点,1是汇点 12 | int map[NMAX][NMAX];//网络费用 13 | int net[NMAX][NMAX];//剩余网络 14 | int path[NMAX];//增广路径,path[v]=u说明(u,v)在增广路径上 15 | int ecost[NMAX];//源点到各点的最短路径 16 | 17 | Mat_Flow(int num):n(num) 18 | { 19 | memset(map, 0, sizeof(map)); 20 | } 21 | void AddSingleEdge(int start, int end, int value = 1) 22 | { 23 | map[start][end] = value; 24 | } 25 | void MakeGraph(int m); 26 | bool bellman_ford(); 27 | int max_flow(); 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /include/chapter6/Exercise6_5_8.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace std; 4 | #include 5 | #include 6 | 7 | struct node 8 | { 9 | int list; 10 | int value; 11 | node(){ } 12 | node(const node& A){list = A.list; value = A.value;} 13 | bool operator < (node& B)const 14 | { 15 | return value (const node& B)const 18 | { 19 | return value>B.value; 20 | } 21 | bool operator == (const node& B)const 22 | { 23 | return value == B.value; 24 | } 25 | static node getMaxNode() 26 | { 27 | node ret; 28 | ret.value = 0x7FFFFFFF; 29 | return ret; 30 | } 31 | }; 32 | 33 | #define ARRAY vector 34 | 35 | ARRAY solve_6_5_8(vector inputParam); 36 | -------------------------------------------------------------------------------- /include/chapter6/Young.h: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define SIZE_OF_YOUNG 100 5 | #define INIT_DATA 0x7fffffff 6 | 7 | enum errorType 8 | { 9 | SUCCESS = 0, 10 | SIZE_OVERFLOW, 11 | OUT_OF_SIZE, 12 | PARAM_ERROR, 13 | }; 14 | 15 | struct structCoordinate 16 | { 17 | int h_index; 18 | int w_index; 19 | structCoordinate(int h, int w):h_index(h),w_index(w){} 20 | }; 21 | 22 | class Young 23 | { 24 | int Y[SIZE_OF_YOUNG+1][SIZE_OF_YOUNG+1]; 25 | int height, width; 26 | 27 | bool isInRange(structCoordinate position); 28 | void build(); 29 | void YoungifyWithSon(structCoordinate position); 30 | void YoungifyWithParent(structCoordinate position); 31 | void setDataInPosition(structCoordinate position, int data); 32 | int getDataFromPosition(structCoordinate position); 33 | void swapDatainPosition(structCoordinate c1, structCoordinate c2); 34 | void Print(); 35 | public: 36 | Young(int h = SIZE_OF_YOUNG, int w = SIZE_OF_YOUNG); 37 | void fillData(int *data, int size); 38 | int extractMin(); 39 | bool findKey(int key); 40 | errorType insert(int key); 41 | errorType decreaseKey(structCoordinate position, int key); 42 | int getMinimum(); 43 | vector sort(); 44 | errorType deleteData(structCoordinate position); 45 | }; -------------------------------------------------------------------------------- /include/chapter7/Exercise7_1_2.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: ../../include/chapter7/Exercise7_1_2.h 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Sun 29 Nov 2015 11:26:27 AM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | void QuickSort7_1_2(int *A, int p, int r); 12 | -------------------------------------------------------------------------------- /include/chapter7/Exercise7_6.h: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | struct section 5 | { 6 | int start; 7 | int end; 8 | bool operator<(const section& b)const 9 | { 10 | return end < b.start; 11 | } 12 | bool operator==(const section & b)const 13 | { 14 | return (end >= b .start) && (start <= b.end); 15 | } 16 | bool operator>(const section & b)const 17 | { 18 | return start > b.end; 19 | } 20 | }; 21 | 22 | //????:0 -> a????,a+1 -> b-1????,b -> length_A???? 23 | struct divid 24 | { 25 | int a; 26 | int b; 27 | }; 28 | 29 | #define ARRAY vector
30 | 31 | void Exercise7_6(ARRAY & array); 32 | -------------------------------------------------------------------------------- /include/chapter7/quickSort.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: ../../include/chapter7/quickSort.h 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Sat 24 Oct 2015 12:10:50 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | void QuickSort(int *A, int p, int r); 12 | void Randomized_QuickSort(int *A, int p, int r); 13 | -------------------------------------------------------------------------------- /include/chapter8/Chapter8.h: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define ARRAY vector 5 | 6 | ARRAY solve8_3(const ARRAY & A); 7 | -------------------------------------------------------------------------------- /include/chapter8/chapter8.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: ../include/chapter8/chapter8.h 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Sun 29 Nov 2015 12:35:35 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | void Counting_Sort(int *A, int *B, int length_A, int k); 12 | void Radix_Sort(int *A, int *B, int length_A, int digit); 13 | -------------------------------------------------------------------------------- /include/chapter9/Chapter9.h: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "array.h" 5 | 6 | 7 | class CArrayFor_9_3_6:public CArray 8 | { 9 | public: 10 | CArrayFor_9_3_6(int size); 11 | CArrayFor_9_3_6(const int *initData, const int len); 12 | CArrayFor_9_3_6(const CArrayFor_9_3_6 & origin); 13 | CArrayFor_9_3_6 getPart(int start, int end)const; 14 | 15 | }; 16 | 17 | class CArrayFor_9_3_8:public CArray 18 | { 19 | public: 20 | CArrayFor_9_3_8(int size); 21 | CArrayFor_9_3_8(int *initData, int len); 22 | void cutPrevHalf(); 23 | void cutBackHalf(); 24 | int getStart(); 25 | int getEnd(); 26 | int getUpMiddle(); 27 | int getDownMiddle(); 28 | 29 | }; 30 | 31 | void exercise_9_3_8(); 32 | int solve_9_3_8(CArrayFor_9_3_8 A, CArrayFor_9_3_8 B); 33 | 34 | #define ARRAY vector 35 | ARRAY solve9_3_6(CArrayFor_9_3_6 & array, int k); 36 | -------------------------------------------------------------------------------- /include/chapter9/Exercise9_1_1.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: ../include/chapter9/Exercise9_1_1.h 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Wed 11 Nov 2015 09:31:57 AM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | #include 12 | 13 | int solve9_1_1(vector array); 14 | -------------------------------------------------------------------------------- /include/others/BigNumber.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace std; 4 | 5 | #define MAX_CELL_COUNT 200 6 | #define DIGIT_PER_CELL 18 7 | 8 | class CBigNumber 9 | { 10 | //protected: 11 | public: 12 | long long cell[MAX_CELL_COUNT]; 13 | bool isInRecord(); 14 | int numberInCells2Digits(int *digit); 15 | void reverseDigit(int *digit, int len); 16 | CBigNumber digit2Number(int *digit, int len); 17 | public: 18 | int usedCells; 19 | CBigNumber(); 20 | CBigNumber(const CBigNumber &B); 21 | CBigNumber(long long normalData); 22 | CBigNumber(string number); 23 | bool isUpOverflow(); 24 | bool isPalindrome(); 25 | void print(); 26 | CBigNumber &operator=(const CBigNumber & B); 27 | bool operator==(const CBigNumber & B); 28 | CBigNumber getReverseNumber(); 29 | CBigNumber operator+(const CBigNumber & number); 30 | long long toLongLong() const; 31 | bool operator<(const CBigNumber & number) const; 32 | }; 33 | 34 | 35 | -------------------------------------------------------------------------------- /include/others/Chapter10.h: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | //10.2-8 5 | struct nodeOfOnePointerDoubleLinkedList 6 | { 7 | int key;//? 8 | unsigned int pointer;//??,???32??,??????????? 9 | nodeOfOnePointerDoubleLinkedList(int k):key(k),pointer(0){} 10 | void changePreNode(nodeOfOnePointerDoubleLinkedList *pFromNode, nodeOfOnePointerDoubleLinkedList *pToNode); 11 | void changeNextNode(nodeOfOnePointerDoubleLinkedList *pFromNode, nodeOfOnePointerDoubleLinkedList *pToNode); 12 | nodeOfOnePointerDoubleLinkedList *getPreFromNext(nodeOfOnePointerDoubleLinkedList *pNextNode); 13 | nodeOfOnePointerDoubleLinkedList *getNextFromPre(nodeOfOnePointerDoubleLinkedList *pPreNode); 14 | }; 15 | //?? 16 | class listOfOnePointerDoubleLink 17 | { 18 | private: 19 | nodeOfOnePointerDoubleLinkedList *pHeadNode;//???,????,????????? 20 | public: 21 | listOfOnePointerDoubleLink(){pHeadNode = new nodeOfOnePointerDoubleLinkedList(0);} 22 | ~listOfOnePointerDoubleLink(){delete pHeadNode;} 23 | void Insert(int key); 24 | vector Print(); 25 | void Delete(int key); 26 | }; 27 | 28 | //10.3-4 29 | class CCompactMultipleArray 30 | { 31 | private: 32 | int *key; 33 | int *next; 34 | int *prev; 35 | int size; 36 | int head; 37 | int f; 38 | public: 39 | CCompactMultipleArray(int n = 100); 40 | ~CCompactMultipleArray(); 41 | void insert(int x); 42 | void remove(int x); 43 | }; 44 | -------------------------------------------------------------------------------- /include/others/Heap.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windmissing/exerciseForAlgorithmSecond/c6ade0da2d7ca6be3415dece65e4f73ade5b4444/include/others/Heap.h -------------------------------------------------------------------------------- /include/others/array.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define ARRAY_SIZE 50 4 | 5 | class CArray 6 | { 7 | protected: 8 | public: 9 | int start; 10 | int end; 11 | int data[ARRAY_SIZE+1]; 12 | CArray(int size); 13 | CArray(const int *initData, const int len); 14 | void insertArray(CArray B); 15 | void sortData(); 16 | void makeRadomData(); 17 | void Print(); 18 | virtual int remainDataCount() const; 19 | }; 20 | 21 | -------------------------------------------------------------------------------- /include/others/binarySearchTree.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | struct BST_Node 6 | { 7 | int key;//??? 8 | int data;//???? 9 | BST_Node *left;//??? 10 | BST_Node *right;//??? 11 | BST_Node *p;//??? 12 | 13 | BST_Node(int x):key(x),data(x),left(NULL),right(NULL),p(NULL){} 14 | }; 15 | 16 | //???????? 17 | class CBinarySearchTree 18 | { 19 | #ifdef __UT__ 20 | public: 21 | #else 22 | private: 23 | #endif 24 | BST_Node *root; 25 | CBinarySearchTree():root(NULL){} 26 | BST_Node *successor(BST_Node *x); 27 | BST_Node *search(BST_Node *x, int k); 28 | BST_Node *iterativeSearch(BST_Node *x, int k); 29 | BST_Node *iterativeMinimum(BST_Node *x); 30 | BST_Node *iterativeMaximum(BST_Node *x); 31 | public: 32 | void iterativeInsert(BST_Node *z); 33 | BST_Node *remove(BST_Node *z); 34 | void inorderWalk(BST_Node *x); 35 | BST_Node *search(int k); 36 | BST_Node *iterativeSearch(int k); 37 | }; 38 | -------------------------------------------------------------------------------- /include/others/intervalTree.h: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #define BLACK 0 5 | #define RED 1 6 | 7 | int Max(int a, int b, int c) 8 | { 9 | if(a > b) 10 | return a > c ? a : c; 11 | else 12 | return b > c ? b : c; 13 | } 14 | //???? 15 | struct interval 16 | { 17 | int low; 18 | int high; 19 | interval(int l, int h):low(l), high(h){} 20 | }; 21 | //??????? 22 | struct node 23 | { 24 | node *left; 25 | node *right; 26 | node *p; 27 | int key; 28 | bool color; 29 | interval inte; 30 | int max; 31 | node(node *init, int l, int h):left(init),right(init),p(init),key(l),inte(l,h),max(h),color(BLACK){} 32 | }; 33 | //a?b????,???,??1 34 | bool Overlap(interval a, interval b) 35 | { 36 | //a?b??? 37 | if(a.high < b.low) 38 | return 0; 39 | //a?b??? 40 | if(a.low > b.high) 41 | return 0; 42 | return 1; 43 | } 44 | 45 | //????? 46 | class Interval_Tree 47 | { 48 | public: 49 | node *root;//??? 50 | node *nil;//?? 51 | /*????*/ 52 | Interval_Tree(){nil = new node(NULL, -1, -1);root = nil;}; 53 | /*???????*/ 54 | void Left_Rotate(node *x);//?? 55 | void Right_Rotate(node *x);//?? 56 | void Insert_Fixup(node *z);//???? 57 | void Insert(node *z);//?? 58 | void Delete_Fixup(node *x);//???? 59 | node *Delete(node *z);//?? 60 | void Print();//?? 61 | void Print(node *x);//?? 62 | node *Search(node *x, int k);//?x??????????k??? 63 | node *Tree_Successor(node *x);//??? 64 | node *Tree_Minimum(node *x);//???????? 65 | /*???????*/ 66 | node *Interval_Search(interval i); 67 | }; 68 | //??,?y = x->right, ????x?y??????????? 69 | //????????:x,y,y->left,?node={p,l,r},??????: 70 | //x={x->p,x->left,y}??{y,x->left,y->left} 71 | //y={x,y->left,y->right}??{x->p,x,y->right} 72 | //y->left={y,y->left->left,y->left->right}??{x,y->left->left,y->left->right} 73 | void Interval_Tree::Left_Rotate(node *x) 74 | { 75 | //?y = x->right 76 | node *y = x->right; 77 | //????????????????,????????? 78 | x->right = y->left; 79 | if(y->left != nil) 80 | y->left->p = x; 81 | y->p = x->p; 82 | if(x->p == nil)//????:x???? 83 | root = y; 84 | else if(x == x->p->left) 85 | x->p->left = y; 86 | else 87 | x->p->right = y; 88 | y->left = x; 89 | x->p = y; 90 | //???????? 91 | y->max = x->max; 92 | x->max = Max(x->inte.high, x->left->max, x->right->max); 93 | } 94 | //??,?y = x->left, ????x?y??????????? 95 | //????????? 96 | void Interval_Tree::Right_Rotate(node *x) 97 | { 98 | node *y = x->left; 99 | x->left = y->right; 100 | if(y->right != nil) 101 | y->right->p = x; 102 | y->p = x->p; 103 | if(x->p == nil) 104 | root = y; 105 | else if(x == x->p->right) 106 | x->p->right = y; 107 | else 108 | x->p->left = y; 109 | y->right = x; 110 | x->p = y; 111 | //???????? 112 | y->max = x->max; 113 | x->max = Max(x->inte.high, x->left->max, x->right->max); 114 | } 115 | //????? 116 | void Interval_Tree::Insert_Fixup(node *z) 117 | { 118 | node *y; 119 | //?????????,??????2???,???????2,???? 120 | while(z->p->color == RED) 121 | { 122 | //p[z]?????,????? 123 | if(z->p == z->p->p->left) 124 | { 125 | //?y?z???? 126 | y = z->p->p->right; 127 | //?????,z???y???? 128 | if(y->color == RED) 129 | { 130 | //?p[z]?y????????z?p[z]??????? 131 | z->p->color = BLACK; 132 | y->color = BLACK; 133 | //?p[p[z]]?????????5 134 | z->p->p->color = RED; 135 | //?p[p[z]]???????z???while?? 136 | z = z->p->p; 137 | } 138 | else 139 | { 140 | //?????:z???????,?z???? 141 | if(z == z->p->right) 142 | { 143 | //?p[z]??,??????? 144 | z = z->p; 145 | Left_Rotate(z); 146 | } 147 | //?????:z???????,?z???? 148 | //??p[z]?p[p[z]]???,??? 149 | z->p->color = BLACK; 150 | z->p->p->color = RED; 151 | Right_Rotate(z->p->p); 152 | } 153 | } 154 | //p[z]?????,?????,????? 155 | else if(z->p == z->p->p->right) 156 | { 157 | y = z->p->p->left; 158 | if(y->color == RED) 159 | { 160 | z->p->color = BLACK; 161 | y->color = BLACK; 162 | z->p->p->color = RED; 163 | z = z->p->p; 164 | } 165 | else 166 | { 167 | if(z == z->p->left) 168 | { 169 | z = z->p; 170 | Right_Rotate(z); 171 | } 172 | z->p->color = BLACK; 173 | z->p->p->color = RED; 174 | Left_Rotate(z->p->p); 175 | } 176 | } 177 | } 178 | //??????? 179 | root->color = BLACK; 180 | } 181 | //?????? 182 | void Interval_Tree::Insert(node *z) 183 | { 184 | node *y = nil, *x = root; 185 | //?????????,??????????? 186 | while(x != nil) 187 | { 188 | x->max = max(x->max, z->max); 189 | y = x; 190 | if(z->key < x->key) 191 | x = x->left; 192 | else 193 | x = x->right; 194 | } 195 | z->p = y; 196 | if(y == nil) 197 | root = z; 198 | else if(z->key < y->key) 199 | y->left = z; 200 | else 201 | y->right = z; 202 | z->left = nil; 203 | z->right = nil; 204 | //??????????? 205 | z->color = RED; 206 | //?????????,???? 207 | Insert_Fixup(z); 208 | } 209 | //??????,x????????,???????????????? 210 | void Interval_Tree::Delete_Fixup(node *x) 211 | { 212 | node *w; 213 | //??????????????????????,??????????,????????? 214 | while(x != root && x->color == BLACK) 215 | { 216 | //?x???????(?????????) 217 | if(x == x->p->left) 218 | { 219 | //?w?x???,??w???,????????? 220 | //???????x????????,???????x??????? 221 | w = x->p->right; 222 | //?????:w???? 223 | if(w->color == RED) 224 | { 225 | //??w?p[x]??? 226 | w->color = BLACK; 227 | x->p->color = RED; 228 | //?p[x]?????? 229 | Left_Rotate(x->p); 230 | //?w?x???? 231 | w = x->p->right; 232 | //??2.3.4?????? 233 | } 234 | //????:w???,w?????????? 235 | if(w->left->color == BLACK && w->right->color == BLACK) 236 | { 237 | //??w?x??? 238 | //w??????,??????,x????????,????????? 239 | w->color = RED; 240 | //?p[x]?????? 241 | x = x->p; 242 | //???x????????,??for?????? 243 | } 244 | //?????,w????,w->left????,w->right???? 245 | else 246 | { 247 | if(w->right->color == BLACK) 248 | { 249 | //??w?left[x]??? 250 | w->left->color = BLACK; 251 | w->color = RED; 252 | //?w?????? 253 | Right_Rotate(w); 254 | //?w?x???? 255 | w = x->p->right; 256 | //?????????? 257 | } 258 | //?????:w????,w->left????,w->right???? 259 | //??w?p[x]??? 260 | w->color =x->p->color; 261 | x->p->color = BLACK; 262 | w->right->color = BLACK; 263 | //?p[x]?????? 264 | Left_Rotate(x->p); 265 | //????????,?x???????????? 266 | x = root; 267 | } 268 | } 269 | //?x???????(?????????) 270 | else if(x == x->p->right) 271 | { 272 | //?w?x???,??w???,????????? 273 | //???????x????????,???????x??????? 274 | w = x->p->left; 275 | //?????:w???? 276 | if(w->color == RED) 277 | { 278 | //??w?p[x]??? 279 | w->color = BLACK; 280 | x->p->color = RED; 281 | //?p[x]?????? 282 | Right_Rotate(x->p); 283 | //?w?x???? 284 | w = x->p->left; 285 | //??2.3.4?????? 286 | } 287 | //????:w???,w?????????? 288 | if(w->right->color == BLACK && w->left->color == BLACK) 289 | { 290 | //??w?x??? 291 | //w??????,??????,x????????,????????? 292 | w->color = RED; 293 | //?p[x]?????? 294 | x = x->p; 295 | //???x????????,??for?????? 296 | } 297 | //?????,w????,w->right????,w->left???? 298 | else 299 | { 300 | if(w->left->color == BLACK) 301 | { 302 | //??w?right[x]??? 303 | w->right->color = BLACK; 304 | w->color = RED; 305 | //?w?????? 306 | Left_Rotate(w); 307 | //?w?x???? 308 | w = x->p->left; 309 | //?????????? 310 | } 311 | //?????:w????,w->right????,w->left???? 312 | //??w?p[x]??? 313 | w->color =x->p->color; 314 | x->p->color = BLACK; 315 | w->left->color = BLACK; 316 | //?p[x]?????? 317 | Right_Rotate(x->p); 318 | //????????,?x???????????? 319 | x = root; 320 | } 321 | } 322 | } 323 | //???????? 324 | x->color = BLACK; 325 | } 326 | //???? 327 | node *Interval_Tree::Tree_Minimum(node *x) 328 | { 329 | //???????????? 330 | while(x->left != nil) 331 | x = x->left; 332 | return x; 333 | } 334 | //???????x?????,?????key[x]?????? 335 | node *Interval_Tree::Tree_Successor(node *x) 336 | { 337 | //?????? 338 | if(x->right != nil) 339 | //???????? 340 | return Tree_Minimum(x->right); 341 | //??x???????x???y,??y?x???????,?y?????? 342 | node *y = x->p; 343 | while(y != NULL && x == y->right) 344 | { 345 | x = y; 346 | y = y->p; 347 | } 348 | return y; 349 | } 350 | //?????????? 351 | node *Interval_Tree::Search(node *x, int k) 352 | { 353 | //???????????,???????????? 354 | if(x->key == -1 || k == x->key) 355 | return x; 356 | //???????????????? 357 | if(k < x->key) 358 | return Search(x->left, k); 359 | //???????????????? 360 | else 361 | return Search(x->right, k); 362 | } 363 | //?????? 364 | node *Interval_Tree::Delete(node *z) 365 | { 366 | //??????????,??????????????? 367 | node *x, *y, *p; 368 | if(z->left == nil || z->right == nil) 369 | { 370 | y = z; 371 | p = y->p; 372 | p->max = p->inte.high; 373 | p = p->p; 374 | while(p->max == y->max) 375 | { 376 | p->max = Max(p->max, p->left->max, p->right->max); 377 | p = p->p; 378 | } 379 | } 380 | else y = Tree_Successor(z); 381 | //???????? 382 | p = y->p; 383 | p->max = p->inte.high; 384 | p = p->p; 385 | while(p->max == y->max) 386 | { 387 | p->max = Max(p->max, p->left->max, p->right->max); 388 | p = p->p; 389 | } 390 | //??y?? 391 | if(y->left != nil) 392 | x = y->left; 393 | else x = y->right; 394 | x->p = y->p; 395 | if(y->p == nil) 396 | root = x; 397 | else if(y == y->p->left) 398 | y->p->left = x; 399 | else 400 | y->p->right = x; 401 | //?? 402 | if(y != z) 403 | { 404 | z->inte = y->inte; 405 | z->key = y->key; 406 | z->max = y->max; 407 | p = z->p; 408 | while(p->max < z->max) 409 | { 410 | p->max = z->max; 411 | p = p->p; 412 | } 413 | } 414 | //????????????,????? 415 | if(y->color == BLACK) 416 | Delete_Fixup(x); 417 | return y; 418 | } 419 | void Interval_Tree::Print(node *x) 420 | { 421 | if(x->key == -1) 422 | return; 423 | Print(x->left); 424 | cout<inte.low<<' '<inte.high<right); 426 | } 427 | 428 | void Interval_Tree::Print() 429 | { 430 | Print(root); 431 | cout<inte)) 441 | { 442 | //????? 443 | if(x->left != nil && x->left->max >= i.low) 444 | x = x->left; 445 | //????? 446 | else 447 | x = x->right; 448 | } 449 | return x; 450 | } -------------------------------------------------------------------------------- /include/others/queue.h: -------------------------------------------------------------------------------- 1 | //10.1???? 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | #define MAX_SIZE 1000 8 | class CQueue 9 | { 10 | public: 11 | int tail;//????? 12 | int head;//????? 13 | int length;//???? 14 | int *s;//?? 15 | CQueue(int size = MAX_SIZE); 16 | ~CQueue(); 17 | bool isEmpty(); 18 | void enqueue(int x); 19 | int dequeue(); 20 | }; 21 | -------------------------------------------------------------------------------- /include/others/sort.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windmissing/exerciseForAlgorithmSecond/c6ade0da2d7ca6be3415dece65e4f73ade5b4444/include/others/sort.h -------------------------------------------------------------------------------- /include/others/stack.h: -------------------------------------------------------------------------------- 1 | #define MAX_SIZE 100 2 | 3 | class CStack 4 | { 5 | public: 6 | int top; 7 | int *s; 8 | CStack(int size = MAX_SIZE); 9 | ~CStack(); 10 | void Print(CStack S); 11 | bool isEmpty(); 12 | void push(int x); 13 | int pop(); 14 | }; 15 | -------------------------------------------------------------------------------- /src/UnionFindSet.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | UnionFindSet.h 3 | 并查集,非递归方法,含路径压缩,数组从0开始 4 | */ 5 | #include 6 | using namespace std; 7 | 8 | #define MAXN 30005 9 | 10 | class UFS 11 | { 12 | public: 13 | int n; 14 | int p[MAXN+1];//集合根结点 15 | int rank[MAXN+1]; //集合中点的个数 16 | public: 17 | UFS(int size = MAXN); 18 | void clear(); 19 | int Find_Set(int x); 20 | //a并入b中,不区分大小 21 | void Union(int x, int y); 22 | void Make_Set(int x); 23 | void Link(int x, int y); 24 | }; 25 | UFS::UFS(int size):n(size) 26 | { 27 | //必须从0开始 28 | for(int i = 0; i <= n; i++) 29 | Make_Set(i); 30 | } 31 | void UFS::Make_Set(int x) 32 | { 33 | p[x] = x; 34 | rank[x] = 0; 35 | } 36 | void UFS::clear() 37 | { 38 | for(int i = 0; i <= n; i++) 39 | Make_Set(i); 40 | } 41 | int UFS::Find_Set(int x) 42 | { 43 | if(x != p[x]) 44 | p[x] = Find_Set(p[x]); 45 | return p[x]; 46 | } 47 | void UFS::Union(int x, int y) 48 | { 49 | Link(Find_Set(x), Find_Set(y)); 50 | } 51 | void UFS::Link(int x, int y) 52 | { 53 | if(rank[x] > rank[y]) 54 | p[y] = x; 55 | else 56 | { 57 | p[x] = y; 58 | if(rank[x] == rank[y]) 59 | rank[y]++; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/chapter10/Exercise10_1_2.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: Exercise10_1_2.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Sat 24 Oct 2015 03:48:01 PM CST 6 | ************************************************************************/ 7 | #include 8 | using namespace std; 9 | #include "Exercise10_1_2.h" 10 | 11 | bool arrayWithTwoStack::isEmpty(int index) 12 | { 13 | if(index == 0 && top1 < 1) 14 | return true; 15 | if(index == 1 && top2 > len) 16 | return true; 17 | return false; 18 | } 19 | 20 | void arrayWithTwoStack::push(int index, int data) 21 | { 22 | //已满 23 | if(top1 > top2)// cout<<"error:overflow"< len) 64 | { 65 | //cout<<"error:underflow"< 2 | #include 3 | using namespace std; 4 | 5 | #include "Chapter10.h" 6 | #if 1 7 | unsigned int node2Addr(nodeOfOnePointerDoubleLinkedList *pNode); 8 | nodeOfOnePointerDoubleLinkedList * addr2Node(unsigned int addr); 9 | 10 | void nodeOfOnePointerDoubleLinkedList::changePreNode(nodeOfOnePointerDoubleLinkedList *pFromNode, nodeOfOnePointerDoubleLinkedList *pToNode) 11 | { 12 | pointer = pointer ^ node2Addr(pFromNode) ^ node2Addr(pToNode); 13 | } 14 | 15 | void nodeOfOnePointerDoubleLinkedList::changeNextNode(nodeOfOnePointerDoubleLinkedList *pFromNode, nodeOfOnePointerDoubleLinkedList *pToNode) 16 | { 17 | pointer = pointer ^ node2Addr(pFromNode) ^ node2Addr(pToNode); 18 | } 19 | 20 | nodeOfOnePointerDoubleLinkedList* nodeOfOnePointerDoubleLinkedList::getPreFromNext(nodeOfOnePointerDoubleLinkedList *pNextNode) 21 | { 22 | unsigned int addrNext = node2Addr(pNextNode); 23 | unsigned int addrPre = pointer ^ addrNext; 24 | 25 | return addr2Node(addrPre); 26 | } 27 | 28 | nodeOfOnePointerDoubleLinkedList* nodeOfOnePointerDoubleLinkedList::getNextFromPre(nodeOfOnePointerDoubleLinkedList *pPreNode) 29 | { 30 | unsigned int addrPre = node2Addr(pPreNode); 31 | unsigned int addrNext = pointer ^ addrPre; 32 | 33 | return addr2Node(addrNext); 34 | } 35 | 36 | void listOfOnePointerDoubleLink::Insert(int key) 37 | { 38 | nodeOfOnePointerDoubleLinkedList *pNewNode = new nodeOfOnePointerDoubleLinkedList(key); 39 | nodeOfOnePointerDoubleLinkedList *pHeadNext = pHeadNode->getNextFromPre(NULL); 40 | 41 | pNewNode->changePreNode(NULL, pHeadNode); 42 | pNewNode->changeNextNode(NULL, pHeadNext); 43 | 44 | if(pHeadNext != NULL) 45 | { 46 | pHeadNext->changePreNode(pHeadNode, pNewNode); 47 | } 48 | pHeadNode->changeNextNode(pHeadNext, pNewNode); 49 | } 50 | 51 | vector listOfOnePointerDoubleLink::Print() 52 | { 53 | vector retVec; 54 | nodeOfOnePointerDoubleLinkedList *pCurrentNode = pHeadNode->getNextFromPre(NULL); 55 | nodeOfOnePointerDoubleLinkedList *pPreNode = pHeadNode; 56 | nodeOfOnePointerDoubleLinkedList *pNextNode = NULL; 57 | while(pCurrentNode != NULL) 58 | { 59 | retVec.push_back(pCurrentNode->key); 60 | 61 | pNextNode = pCurrentNode->getNextFromPre(pPreNode); 62 | pPreNode = pCurrentNode; 63 | pCurrentNode = pNextNode; 64 | 65 | } 66 | return retVec; 67 | } 68 | 69 | void listOfOnePointerDoubleLink::Delete(int key) 70 | { 71 | nodeOfOnePointerDoubleLinkedList *pCurrentNode = addr2Node(pHeadNode->pointer); 72 | nodeOfOnePointerDoubleLinkedList *pPreNode = pHeadNode; 73 | nodeOfOnePointerDoubleLinkedList *pNextNode = NULL; 74 | 75 | while(pCurrentNode != NULL) 76 | { 77 | pNextNode = pCurrentNode->getNextFromPre(pPreNode); 78 | 79 | if(pCurrentNode->key == key) 80 | break; 81 | pPreNode = pCurrentNode; 82 | pCurrentNode = pNextNode; 83 | } 84 | 85 | if(pCurrentNode == NULL) 86 | return ; 87 | pPreNode->changeNextNode(pCurrentNode, pNextNode); 88 | if(pNextNode != NULL) 89 | pNextNode->changePreNode(pCurrentNode, pPreNode); 90 | delete pCurrentNode; 91 | } 92 | 93 | unsigned int node2Addr(nodeOfOnePointerDoubleLinkedList *pNode) 94 | { 95 | return *(unsigned int *)&pNode; 96 | } 97 | 98 | nodeOfOnePointerDoubleLinkedList * addr2Node(unsigned int addr) 99 | { 100 | return (nodeOfOnePointerDoubleLinkedList*)addr; 101 | } 102 | #endif 103 | -------------------------------------------------------------------------------- /src/chapter10/Exercise10_3_4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | #include "Chapter10.h" 7 | 8 | CCompactMultipleArray::CCompactMultipleArray(int n) 9 | { 10 | key = new int[n]; 11 | next = new int[n]; 12 | prev = new int[n]; 13 | } 14 | 15 | CCompactMultipleArray::~CCompactMultipleArray() 16 | { 17 | delete key; 18 | delete next; 19 | delete prev; 20 | } 21 | 22 | void CCompactMultipleArray::insert(int x) 23 | { 24 | //???? 25 | if(f == size-1) 26 | { 27 | cout<<"error:overflow"<= 0) 37 | prev[head] = f; 38 | head = f; 39 | } 40 | //?????? 41 | void CCompactMultipleArray::remove(int x) 42 | { 43 | //????????? 44 | if(f == -1) 45 | { 46 | cout<<"error:underflow"<>str; 98 | if(str == "I") 99 | { 100 | x = rand() % 100; 101 | cout<>x; 107 | Delete(key, next, prev, x); 108 | } 109 | else if(str == "P") 110 | { 111 | Print(key, next, prev); 112 | } 113 | } 114 | return 0; 115 | }*/ 116 | -------------------------------------------------------------------------------- /src/chapter13/redBlackTree.cpp: -------------------------------------------------------------------------------- 1 | #include "redBlackTree.h" 2 | 3 | node * CRedBlackTree::nil = new node(-1, CRedBlackTree::nil); 4 | 5 | CRedBlackTree::CRedBlackTree() 6 | { 7 | root = nil; 8 | } 9 | 10 | CRedBlackTree::~CRedBlackTree() 11 | { 12 | if(root != nil) 13 | delete root; 14 | } 15 | 16 | void CRedBlackTree::insert(int key) 17 | { 18 | node *z = new node(key, nil); 19 | z->color = RED; 20 | if(root == nil) 21 | root = z; 22 | else 23 | { 24 | node *y = getPositionToInsert(z); 25 | insertChild(y, z); 26 | } 27 | insertFixup(z); 28 | } 29 | 30 | node * CRedBlackTree::getPositionToInsert(node *z) 31 | { 32 | node *y = nil, *x = root; 33 | while(x != nil) 34 | { 35 | y = x; 36 | if(z->key < x->key) 37 | x = x->left; 38 | else 39 | x = x->right; 40 | } 41 | return y; 42 | } 43 | 44 | void CRedBlackTree::insertChild(node *parent, node *child) 45 | { 46 | child->p = parent; 47 | if(child->key < parent->key) 48 | parent->left = child; 49 | else 50 | parent->right = child; 51 | child->left = nil; 52 | child->right = nil; 53 | } 54 | 55 | node *CRedBlackTree::search(int k) 56 | { 57 | return search(root, k); 58 | } 59 | 60 | node *CRedBlackTree::search(node *x, int k) 61 | { 62 | if(x == nil || k == x->key) 63 | return x; 64 | if(k < x->key) 65 | return search(x->left, k); 66 | else 67 | return search(x->right, k); 68 | } 69 | 70 | void CRedBlackTree::remove(node *z) 71 | { 72 | node * toRemove = findTheNodeToRemove(z); 73 | node *child = getChild(toRemove); 74 | if(toRemove != z) 75 | z->key = toRemove->key; 76 | removeReally(toRemove); 77 | if(toRemove->color == BLACK) 78 | removeFixup(child); 79 | } 80 | 81 | node * CRedBlackTree::findTheNodeToRemove(node *z) 82 | { 83 | if(z->left == nil || z->right == nil) 84 | return z; 85 | else 86 | return successor(z); 87 | } 88 | 89 | void CRedBlackTree::removeReally(node *toRemove) 90 | { 91 | node *child = getChild(toRemove); 92 | child->p = toRemove->p; 93 | if(toRemove->p == nil) 94 | root = child; 95 | else if(toRemove == toRemove->p->left) 96 | toRemove->p->left = child; 97 | else 98 | toRemove->p->right = child; 99 | 100 | } 101 | 102 | node * CRedBlackTree::getChild(node *parent) 103 | { 104 | if(parent->left != nil) 105 | return parent->left; 106 | else 107 | return parent->right; 108 | } 109 | 110 | node *CRedBlackTree::successor(node *x) 111 | { 112 | if(x->right != nil) 113 | return minimum(x->right); 114 | node *y = x->p; 115 | while(x == y->right) 116 | { 117 | x = y; 118 | y = y->p; 119 | } 120 | return y; 121 | } 122 | 123 | node *CRedBlackTree::minimum(node *x) 124 | { 125 | while(x->left != nil) 126 | x = x->left; 127 | return x; 128 | } 129 | 130 | void CRedBlackTree::insertFixup(node *z) 131 | { 132 | node *y; 133 | //?????????,??????2???,???????2,???? 134 | while(z->p->color == RED) 135 | { 136 | //p[z]?????,????? 137 | if(z->p == z->p->p->left) 138 | { 139 | //?y?z???? 140 | y = z->p->p->right; 141 | //?????,z???y???? 142 | if(y->color == RED) 143 | { 144 | //?p[z]?y????????z?p[z]??????? 145 | z->p->color = BLACK; 146 | y->color = BLACK; 147 | //?p[p[z]]?????????5 148 | z->p->p->color = RED; 149 | //?p[p[z]]???????z???while?? 150 | z = z->p->p; 151 | } 152 | else 153 | { 154 | //?????:z???????,?z???? 155 | if(z == z->p->right) 156 | { 157 | //?p[z]??,??????? 158 | z = z->p; 159 | leftRotate(z); 160 | } 161 | //?????:z???????,?z???? 162 | //??p[z]?p[p[z]]???,??? 163 | z->p->color = BLACK; 164 | z->p->p->color = RED; 165 | rightRotate(z->p->p); 166 | } 167 | } 168 | //p[z]?????,?????,????? 169 | else if(z->p == z->p->p->right) 170 | { 171 | y = z->p->p->left; 172 | if(y->color == RED) 173 | { 174 | z->p->color = BLACK; 175 | y->color = BLACK; 176 | z->p->p->color = RED; 177 | z = z->p->p; 178 | } 179 | else 180 | { 181 | if(z == z->p->left) 182 | { 183 | z = z->p; 184 | rightRotate(z); 185 | } 186 | z->p->color = BLACK; 187 | z->p->p->color = RED; 188 | leftRotate(z->p->p); 189 | } 190 | } 191 | } 192 | //??????? 193 | root->color = BLACK; 194 | } 195 | //??,?y = x->right, ????x?y??????????? 196 | //????????:x,y,y->left,?node={p,l,r},??????: 197 | //x={x->p,x->left,y}??{y,x->left,y->left} 198 | //y={x,y->left,y->right}??{x->p,x,y->right} 199 | //y->left={y,y->left->left,y->left->right}??{x,y->left->left,y->left->right} 200 | void CRedBlackTree::leftRotate(node *x) 201 | { 202 | //?y = x->right 203 | node *y = x->right; 204 | //????????????????,????????? 205 | x->right = y->left; 206 | if(y->left != nil) 207 | y->left->p = x; 208 | y->p = x->p; 209 | if(x->p == nil)//????:x???? 210 | root = y; 211 | else if(x == x->p->left) 212 | x->p->left = y; 213 | else 214 | x->p->right = y; 215 | y->left = x; 216 | x->p = y; 217 | } 218 | //??,?y = x->left, ????x?y??????????? 219 | //????????? 220 | void CRedBlackTree::rightRotate(node *x) 221 | { 222 | node *y = x->left; 223 | x->left = y->right; 224 | if(y->right != nil) 225 | y->right->p = x; 226 | y->p = x->p; 227 | if(x->p == nil) 228 | root = y; 229 | else if(x == x->p->right) 230 | x->p->right = y; 231 | else 232 | x->p->left = y; 233 | y->right = x; 234 | x->p = y; 235 | } 236 | //????? 237 | 238 | //?????? 239 | 240 | //??????,x????????,???????????????? 241 | void CRedBlackTree::removeFixup(node *x) 242 | { 243 | node *w; 244 | //??????????????????????,??????????,????????? 245 | while(x != root && x->color == BLACK) 246 | { 247 | //?x???????(?????????) 248 | if(x == x->p->left) 249 | { 250 | //?w?x???,??w???,????????? 251 | //???????x????????,???????x??????? 252 | w = x->p->right; 253 | //?????:w???? 254 | if(w->color == RED) 255 | { 256 | //??w?p[x]??? 257 | w->color = BLACK; 258 | x->p->color = RED; 259 | //?p[x]?????? 260 | leftRotate(x->p); 261 | //?w?x???? 262 | w = x->p->right; 263 | //??2.3.4?????? 264 | } 265 | //????:w???,w?????????? 266 | if(w->left->color == BLACK && w->right->color == BLACK) 267 | { 268 | //??w?x??? 269 | //w??????,??????,x????????,????????? 270 | w->color = RED; 271 | //?p[x]?????? 272 | x = x->p; 273 | //???x????????,??for?????? 274 | } 275 | //?????,w????,w->left????,w->right???? 276 | else 277 | { 278 | if(w->right->color == BLACK) 279 | { 280 | //??w?left[x]??? 281 | w->left->color = BLACK; 282 | w->color = RED; 283 | //?w?????? 284 | rightRotate(w); 285 | //?w?x???? 286 | w = x->p->right; 287 | //?????????? 288 | } 289 | //?????:w????,w->left????,w->right???? 290 | //??w?p[x]??? 291 | w->color =x->p->color; 292 | x->p->color = BLACK; 293 | w->right->color = BLACK; 294 | //?p[x]?????? 295 | leftRotate(x->p); 296 | //????????,?x???????????? 297 | x = root; 298 | } 299 | } 300 | //?x???????(?????????) 301 | else if(x == x->p->right) 302 | { 303 | //?w?x???,??w???,????????? 304 | //???????x????????,???????x??????? 305 | w = x->p->left; 306 | //?????:w???? 307 | if(w->color == RED) 308 | { 309 | //??w?p[x]??? 310 | w->color = BLACK; 311 | x->p->color = RED; 312 | //?p[x]?????? 313 | rightRotate(x->p); 314 | //?w?x???? 315 | w = x->p->left; 316 | //??2.3.4?????? 317 | } 318 | //????:w???,w?????????? 319 | if(w->right->color == BLACK && w->left->color == BLACK) 320 | { 321 | //??w?x??? 322 | //w??????,??????,x????????,????????? 323 | w->color = RED; 324 | //?p[x]?????? 325 | x = x->p; 326 | //???x????????,??for?????? 327 | } 328 | //?????,w????,w->right????,w->left???? 329 | else 330 | { 331 | if(w->left->color == BLACK) 332 | { 333 | //??w?right[x]??? 334 | w->right->color = BLACK; 335 | w->color = RED; 336 | //?w?????? 337 | leftRotate(w); 338 | //?w?x???? 339 | w = x->p->left; 340 | //?????????? 341 | } 342 | //?????:w????,w->right????,w->left???? 343 | //??w?p[x]??? 344 | w->color =x->p->color; 345 | x->p->color = BLACK; 346 | w->left->color = BLACK; 347 | //?p[x]?????? 348 | rightRotate(x->p); 349 | //????????,?x???????????? 350 | x = root; 351 | } 352 | } 353 | } 354 | //???????? 355 | x->color = BLACK; 356 | } 357 | 358 | bool CRedBlackTree::isNodeNull(node *z) 359 | { 360 | if (z == nil) 361 | return true; 362 | return false; 363 | } 364 | -------------------------------------------------------------------------------- /src/chapter14/exercise14_2.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: ../src/chapter14/exercise14_2.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Sat 28 Nov 2015 04:44:08 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | #include "exercise14_2.h" 12 | #include "section14_1.h" 13 | 14 | vector josefInOsTree(vector input, int m) 15 | { 16 | //生成一棵动态顺序统计树 17 | Os_Tree *T = new Os_Tree; 18 | //将1.,n依次插入到树中 19 | for(int i = 0; i < input.size(); i++) 20 | T->insert(i, input[i]); 21 | int t = input.size(), start = 0; 22 | //还有剩余结点 23 | while(t) 24 | { 25 | //计算下一个要删除的结点在剩余结点中的位置 26 | start = (start + m - 1) % t; 27 | //找到这个结点 28 | ostNode *ret = T->select(start+1); 29 | cout<key<<' '; 30 | //删除这个结点 31 | T->remove(ret); 32 | t--; 33 | } 34 | cout< File Name: section14_1.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Mon 23 Nov 2015 07:53:37 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | #include "section14_1.h" 11 | 12 | ostNode * Os_Tree::nil = new ostNode(NULL, -1); 13 | //对附加信息的维护 14 | void Maintaining(ostNode *x) 15 | { 16 | while(x->key >= 0) 17 | { 18 | x->size = x->left->size + x->right->size + 1; 19 | x = x->parent; 20 | } 21 | } 22 | //左旋,令y = x->right, 左旋是以x和y之间的链为支轴进行旋转 23 | //涉及到的结点包括:x,y,y->left,令ostNode={p,l,r},具体变化如下: 24 | //x={x->parent,x->left,y}变为{y,x->left,y->left} 25 | //y={x,y->left,y->right}变为{x->parent,x,y->right} 26 | //y->left={y,y->left->left,y->left->right}变为{x,y->left->left,y->left->right} 27 | void Os_Tree::leftRotate(ostNode *x) 28 | { 29 | //令y = x->right 30 | ostNode *y = x->right; 31 | //按照上面的方式修改三个结点的指针,注意修改指针的顺序 32 | x->right = y->left; 33 | if(y->left != nil) 34 | y->left->parent = x; 35 | y->parent = x->parent; 36 | if(x->parent == nil)//特殊情况:x是根结点 37 | root = y; 38 | else if(x == x->parent->left) 39 | x->parent->left = y; 40 | else 41 | x->parent->right = y; 42 | y->left = x; 43 | x->parent = y; 44 | //对附加信息的维护 45 | y->size = x->size; 46 | x->size = x->left->size + x->right->size + 1; 47 | } 48 | //右旋,令y = x->left, 左旋是以x和y之间的链为支轴进行旋转 49 | //旋转过程与上文类似 50 | void Os_Tree::rightRotate(ostNode *x) 51 | { 52 | ostNode *y = x->left; 53 | x->left = y->right; 54 | if(y->right != nil) 55 | y->right->parent = x; 56 | y->parent = x->parent; 57 | if(x->parent == nil) 58 | root = y; 59 | else if(x == x->parent->right) 60 | x->parent->right = y; 61 | else 62 | x->parent->left = y; 63 | y->right = x; 64 | x->parent = y; 65 | //对附加信息的维护 66 | y->size = x->size; 67 | x->size = x->left->size + x->right->size + 1; 68 | } 69 | //红黑树调整 70 | void Os_Tree::insertFixup(ostNode *z) 71 | { 72 | ostNode *y; 73 | //唯一需要调整的情况,就是违反性质2的时候,如果不违反性质2,调整结束 74 | while(z->parent->color == RED) 75 | { 76 | //parent[z]是左孩子时,有三种情况 77 | if(z->parent == z->parent->parent->left) 78 | { 79 | //令y是z的叔结点 80 | y = z->parent->parent->right; 81 | //第一种情况,z的叔叔y是红色的 82 | if(y->color == RED) 83 | { 84 | //将parent[z]和y都着为黑色以解决z和parent[z]都是红色的问题 85 | z->parent->color = BLACK; 86 | y->color = BLACK; 87 | //将parent[parent[z]]着为红色以保持性质5 88 | z->parent->parent->color = RED; 89 | //把parent[parent[z]]当作新增的结点z来重复while循环 90 | z = z->parent->parent; 91 | } 92 | else 93 | { 94 | //第二种情况:z的叔叔是黑色的,且z是右孩子 95 | if(z == z->parent->right) 96 | { 97 | //对parent[z]左旋,转为第三种情况 98 | z = z->parent; 99 | leftRotate(z); 100 | } 101 | //第三种情况:z的叔叔是黑色的,且z是左孩子 102 | //交换parent[z]和parent[parent[z]]的颜色,并右旋 103 | z->parent->color = BLACK; 104 | z->parent->parent->color = RED; 105 | rightRotate(z->parent->parent); 106 | } 107 | } 108 | //parent[z]是右孩子时,有三种情况,与上面类似 109 | else if(z->parent == z->parent->parent->right) 110 | { 111 | y = z->parent->parent->left; 112 | if(y->color == RED) 113 | { 114 | z->parent->color = BLACK; 115 | y->color = BLACK; 116 | z->parent->parent->color = RED; 117 | z = z->parent->parent; 118 | } 119 | else 120 | { 121 | if(z == z->parent->left) 122 | { 123 | z = z->parent; 124 | rightRotate(z); 125 | } 126 | z->parent->color = BLACK; 127 | z->parent->parent->color = RED; 128 | leftRotate(z->parent->parent); 129 | } 130 | } 131 | } 132 | //根结点置为黑色 133 | root->color = BLACK; 134 | } 135 | 136 | //插入一个结点 137 | void Os_Tree::insert(int key, int info) 138 | { 139 | ostNode *z = new ostNode(nil, key); 140 | z->info = info; 141 | //将新插入的结点转为红色 142 | z->color = RED; 143 | if(root == nil) 144 | root = z; 145 | else 146 | { 147 | ostNode *y = getPositionToInsert(z); 148 | insertChild(y, z); 149 | } 150 | //从新插入的结点开始,向上调整 151 | insertFixup(z); 152 | Maintaining(z); 153 | } 154 | ostNode * Os_Tree::getPositionToInsert(ostNode *z) 155 | { 156 | ostNode *y = nil, *x = root; 157 | //找到应该插入的位置,与二叉查找树的插入相同 158 | while(x != nil) 159 | { 160 | y = x; 161 | if(z->key < x->key) 162 | x = x->left; 163 | else if(z->key > x->key) 164 | x = x->right; 165 | } 166 | return y; 167 | } 168 | 169 | void Os_Tree::insertChild(ostNode *parent, ostNode *child) 170 | { 171 | child->parent = parent; 172 | if(child->key < parent->key) 173 | parent->left = child; 174 | else 175 | parent->right = child; 176 | child->left = nil; 177 | child->right = nil; 178 | } 179 | 180 | //对树进行调整,x指向一个红黑结点,调整的过程是将额外的黑色沿树上移 181 | void Os_Tree::removeFixup(ostNode *x) 182 | { 183 | ostNode *w; 184 | //如果这个额外的黑色在一个根结点或一个红结点上,结点会吸收额外的黑色,成为一个黑色的结点 185 | while(x != root && x->color == BLACK) 186 | { 187 | //若x是其父的左结点(右结点的情况相对应) 188 | if(x == x->parent->left) 189 | { 190 | //令w为x的兄弟,根据w的不同,分为三种情况来处理 191 | //执行删除操作前x肯定是没有兄弟的,执行删除操作后x肯定是有兄弟的 192 | w = x->parent->right; 193 | //第一种情况:w是红色的 194 | if(w->color == RED) 195 | { 196 | //改变w和parent[x]的颜色 197 | w->color = BLACK; 198 | x->parent->color = RED; 199 | //对parent[x]进行一次左旋 200 | leftRotate(x->parent); 201 | //令w为x的新兄弟 202 | w = x->parent->right; 203 | //转为2.3.4三种情况之一 204 | } 205 | //第二情况:w为黑色,w的两个孩子也都是黑色 206 | if(w->left->color == BLACK && w->right->color == BLACK) 207 | { 208 | //去掉w和x的黑色 209 | //w只有一层黑色,去掉变为红色,x有多余的一层黑色,去掉后恢复原来颜色 210 | w->color = RED; 211 | //在parent[x]上补一层黑色 212 | x = x->parent; 213 | //现在新x上有个额外的黑色,转入for循环继续处理 214 | } 215 | //第三种情况,w是黑色的,w->left是红色的,w->right是黑色的 216 | else 217 | { 218 | if(w->right->color == BLACK) 219 | { 220 | //改变w和left[x]的颜色 221 | w->left->color = BLACK; 222 | w->color = RED; 223 | //对w进行一次右旋 224 | rightRotate(w); 225 | //令w为x的新兄弟 226 | w = x->parent->right; 227 | //此时转变为第四种情况 228 | } 229 | //第四种情况:w是黑色的,w->left是黑色的,w->right是红色的 230 | //修改w和parent[x]的颜色 231 | w->color =x->parent->color; 232 | x->parent->color = BLACK; 233 | w->right->color = BLACK; 234 | //对parent[x]进行一次左旋 235 | leftRotate(x->parent); 236 | //此时调整已经结束,将x置为根结点是为了结束循环 237 | x = root; 238 | } 239 | } 240 | //若x是其父的左结点(右结点的情况相对应) 241 | else if(x == x->parent->right) 242 | { 243 | //令w为x的兄弟,根据w的不同,分为三种情况来处理 244 | //执行删除操作前x肯定是没有兄弟的,执行删除操作后x肯定是有兄弟的 245 | w = x->parent->left; 246 | //第一种情况:w是红色的 247 | if(w->color == RED) 248 | { 249 | //改变w和parent[x]的颜色 250 | w->color = BLACK; 251 | x->parent->color = RED; 252 | //对parent[x]进行一次左旋 253 | rightRotate(x->parent); 254 | //令w为x的新兄弟 255 | w = x->parent->left; 256 | //转为2.3.4三种情况之一 257 | } 258 | //第二情况:w为黑色,w的两个孩子也都是黑色 259 | if(w->right->color == BLACK && w->left->color == BLACK) 260 | { 261 | //去掉w和x的黑色 262 | //w只有一层黑色,去掉变为红色,x有多余的一层黑色,去掉后恢复原来颜色 263 | w->color = RED; 264 | //在parent[x]上补一层黑色 265 | x = x->parent; 266 | //现在新x上有个额外的黑色,转入for循环继续处理 267 | } 268 | //第三种情况,w是黑色的,w->right是红色的,w->left是黑色的 269 | else 270 | { 271 | if(w->left->color == BLACK) 272 | { 273 | //改变w和right[x]的颜色 274 | w->right->color = BLACK; 275 | w->color = RED; 276 | //对w进行一次右旋 277 | leftRotate(w); 278 | //令w为x的新兄弟 279 | w = x->parent->left; 280 | //此时转变为第四种情况 281 | } 282 | //第四种情况:w是黑色的,w->right是黑色的,w->left是红色的 283 | //修改w和parent[x]的颜色 284 | w->color =x->parent->color; 285 | x->parent->color = BLACK; 286 | w->left->color = BLACK; 287 | //对parent[x]进行一次左旋 288 | rightRotate(x->parent); 289 | //此时调整已经结束,将x置为根结点是为了结束循环 290 | x = root; 291 | } 292 | } 293 | } 294 | //吸收了额外的黑色 295 | x->color = BLACK; 296 | } 297 | //找最小值 298 | ostNode *Os_Tree::minimum(ostNode *x) 299 | { 300 | //只要有比当前结点小的结点 301 | while(x->left != nil) 302 | x = x->left; 303 | return x; 304 | } 305 | //查找中序遍历下x结点的后继,后继是大于key[x]的最小的结点 306 | ostNode *Os_Tree::successor(ostNode *x) 307 | { 308 | //如果有右孩子 309 | if(x->right != nil) 310 | //右子树中的最小值 311 | return minimum(x->right); 312 | //如果x的右子树为空且x有后继y,那么y是x的最低祖先结点,且y的左儿子也是 313 | ostNode *y = x->parent; 314 | while(y != NULL && x == y->right) 315 | { 316 | x = y; 317 | y = y->parent; 318 | } 319 | return y; 320 | } 321 | 322 | ostNode *Os_Tree::search(int k) 323 | { 324 | return search(root, k); 325 | } 326 | 327 | //递归地查询二叉查找树 328 | ostNode *Os_Tree::search(ostNode *x, int k) 329 | { 330 | //找到叶子结点了还没找到,或当前结点是所查找的结点 331 | if(x->key == -1 || k == x->key) 332 | return x; 333 | //所查找的结点位于当前结点的左子树 334 | if(k < x->key) 335 | return search(x->left, k); 336 | //所查找的结点位于当前结点的左子树 337 | else 338 | return search(x->right, k); 339 | } 340 | //红黑树的删除 341 | ostNode *Os_Tree::remove(ostNode *z) 342 | { 343 | ostNode * toRemove = findTheNodeToRemove(z); 344 | ostNode *child = getChild(toRemove); 345 | if(toRemove != z) 346 | z->key = toRemove->key; 347 | removeReally(toRemove); 348 | if(toRemove != z) 349 | Maintaining(z); 350 | if(toRemove->color == BLACK) 351 | removeFixup(child); 352 | } 353 | 354 | ostNode * Os_Tree::findTheNodeToRemove(ostNode *z) 355 | { 356 | //找到结点的位置并删除,这一部分与二叉查找树的删除相同 357 | ostNode *x, *y; 358 | if(z->left == nil || z->right == nil) 359 | return z; 360 | else 361 | return successor(z); 362 | } 363 | 364 | ostNode * Os_Tree::getChild(ostNode *parent) 365 | { 366 | if(parent->left != nil) 367 | return parent->left; 368 | else 369 | return parent->right; 370 | } 371 | 372 | void Os_Tree::removeReally(ostNode *toRemove) 373 | { 374 | ostNode *child = getChild(toRemove); 375 | child->parent = toRemove->parent; 376 | if(toRemove->parent == nil) 377 | root = child; 378 | else if(toRemove == toRemove->parent->left) 379 | toRemove->parent->left = child; 380 | else 381 | toRemove->parent->right = child; 382 | Maintaining(toRemove->parent); 383 | } 384 | 385 | ostNode *Os_Tree::select(int i) 386 | { 387 | select(root, i); 388 | } 389 | 390 | //查找以x为根结点的树中第i大的结点 391 | ostNode *Os_Tree::select(ostNode *x, int i) 392 | { 393 | //令x左子树中点的个数为r-1, 394 | int r = x->left->size +1; 395 | //那么x是x树中第r大的结点 396 | if(r == i) 397 | return x; 398 | //第i大的元素在x->left中 399 | else if(i < r) 400 | return select(x->left, i); 401 | //第i大的元素在x->right中 402 | else 403 | return select(x->right, i - r); 404 | } 405 | 406 | -------------------------------------------------------------------------------- /src/chapter14/section14_2.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: section14_2.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Mon 23 Nov 2015 07:52:29 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | #define BLACK 0 12 | #define RED 1 13 | 14 | //红黑树结点结构 15 | struct node 16 | { 17 | //红黑树的基础结构 18 | node *left; 19 | node *right; 20 | node *parent; 21 | int key; 22 | bool color; 23 | int size;//以x为根的子树的(内部)结点数(包括x本身),即子树的大小 24 | node(node *init, int k) 25 | :left(init),right(init),parent(init),key(k),color(BLACK),size(1){} 26 | }; 27 | //顺序统计量树结构 28 | struct Os_Tree 29 | { 30 | node *root;//根结点 31 | node *nil;//哨兵 32 | Os_Tree(){nil = new node(NULL, -1);nil->size = 0;root = nil;}; 33 | }; 34 | //对附加信息的维护 35 | void Maintaining(node *x) 36 | { 37 | while(x->key >= 0) 38 | { 39 | x->size = x->left->size + x->right->size + 1; 40 | x = x->parent; 41 | } 42 | } 43 | //左旋,令y = x->right, 左旋是以x和y之间的链为支轴进行旋转 44 | //涉及到的结点包括:x,y,y->left,令node={p,l,r},具体变化如下: 45 | //x={x->parent,x->left,y}变为{y,x->left,y->left} 46 | //y={x,y->left,y->right}变为{x->parent,x,y->right} 47 | //y->left={y,y->left->left,y->left->right}变为{x,y->left->left,y->left->right} 48 | void Left_Rotate(Os_Tree *T, node *x) 49 | { 50 | //令y = x->right 51 | node *y = x->right; 52 | //按照上面的方式修改三个结点的指针,注意修改指针的顺序 53 | x->right = y->left; 54 | if(y->left != T->nil) 55 | y->left->parent = x; 56 | y->parent = x->parent; 57 | if(x->parent == T->nil)//特殊情况:x是根结点 58 | T->root = y; 59 | else if(x == x->parent->left) 60 | x->parent->left = y; 61 | else 62 | x->parent->right = y; 63 | y->left = x; 64 | x->parent = y; 65 | //对附加信息的维护 66 | y->size = x->size; 67 | x->size = x->left->size + x->right->size + 1; 68 | } 69 | //右旋,令y = x->left, 左旋是以x和y之间的链为支轴进行旋转 70 | //旋转过程与上文类似 71 | void Right_Rotate(Os_Tree *T, node *x) 72 | { 73 | node *y = x->left; 74 | x->left = y->right; 75 | if(y->right != T->nil) 76 | y->right->parent = x; 77 | y->parent = x->parent; 78 | if(x->parent == T->nil) 79 | T->root = y; 80 | else if(x == x->parent->right) 81 | x->parent->right = y; 82 | else 83 | x->parent->left = y; 84 | y->right = x; 85 | x->parent = y; 86 | //对附加信息的维护 87 | y->size = x->size; 88 | x->size = x->left->size + x->right->size + 1; 89 | } 90 | //红黑树调整 91 | void Os_Tree_Insert_Fixup(Os_Tree *T, node *z) 92 | { 93 | node *y; 94 | //唯一需要调整的情况,就是违反性质2的时候,如果不违反性质2,调整结束 95 | while(z->parent->color == RED) 96 | { 97 | //parent[z]是左孩子时,有三种情况 98 | if(z->parent == z->parent->parent->left) 99 | { 100 | //令y是z的叔结点 101 | y = z->parent->parent->right; 102 | //第一种情况,z的叔叔y是红色的 103 | if(y->color == RED) 104 | { 105 | //将parent[z]和y都着为黑色以解决z和parent[z]都是红色的问题 106 | z->parent->color = BLACK; 107 | y->color = BLACK; 108 | //将parent[parent[z]]着为红色以保持性质5 109 | z->parent->parent->color = RED; 110 | //把parent[parent[z]]当作新增的结点z来重复while循环 111 | z = z->parent->parent; 112 | } 113 | else 114 | { 115 | //第二种情况:z的叔叔是黑色的,且z是右孩子 116 | if(z == z->parent->right) 117 | { 118 | //对parent[z]左旋,转为第三种情况 119 | z = z->parent; 120 | Left_Rotate(T, z); 121 | } 122 | //第三种情况:z的叔叔是黑色的,且z是左孩子 123 | //交换parent[z]和parent[parent[z]]的颜色,并右旋 124 | z->parent->color = BLACK; 125 | z->parent->parent->color = RED; 126 | Right_Rotate(T, z->parent->parent); 127 | } 128 | } 129 | //parent[z]是右孩子时,有三种情况,与上面类似 130 | else if(z->parent == z->parent->parent->right) 131 | { 132 | y = z->parent->parent->left; 133 | if(y->color == RED) 134 | { 135 | z->parent->color = BLACK; 136 | y->color = BLACK; 137 | z->parent->parent->color = RED; 138 | z = z->parent->parent; 139 | } 140 | else 141 | { 142 | if(z == z->parent->left) 143 | { 144 | z = z->parent; 145 | Right_Rotate(T, z); 146 | } 147 | z->parent->color = BLACK; 148 | z->parent->parent->color = RED; 149 | Left_Rotate(T, z->parent->parent); 150 | } 151 | } 152 | } 153 | //根结点置为黑色 154 | T->root->color = BLACK; 155 | } 156 | //插入一个结点 157 | void Os_Tree_Insert(Os_Tree *T, node *z) 158 | { 159 | node *y = T->nil, *x = T->root; 160 | //找到应该插入的位置,与二叉查找树的插入相同 161 | while(x != T->nil) 162 | { 163 | y = x; 164 | if(z->key < x->key) 165 | x = x->left; 166 | else if(z->key > x->key) 167 | x = x->right; 168 | } 169 | z->parent = y; 170 | if(y == T->nil) 171 | T->root = z; 172 | else if(z->key < y->key) 173 | y->left = z; 174 | else 175 | y->right = z; 176 | z->left = T->nil; 177 | z->right = T->nil; 178 | //将新插入的结点转为红色 179 | z->color = RED; 180 | //从新插入的结点开始,向上调整 181 | Os_Tree_Insert_Fixup(T, z); 182 | Maintaining(z); 183 | } 184 | //对树进行调整,x指向一个红黑结点,调整的过程是将额外的黑色沿树上移 185 | void Os_Tree_Delete_Fixup(Os_Tree *T, node *x) 186 | { 187 | node *w; 188 | //如果这个额外的黑色在一个根结点或一个红结点上,结点会吸收额外的黑色,成为一个黑色的结点 189 | while(x != T->root && x->color == BLACK) 190 | { 191 | //若x是其父的左结点(右结点的情况相对应) 192 | if(x == x->parent->left) 193 | { 194 | //令w为x的兄弟,根据w的不同,分为三种情况来处理 195 | //执行删除操作前x肯定是没有兄弟的,执行删除操作后x肯定是有兄弟的 196 | w = x->parent->right; 197 | //第一种情况:w是红色的 198 | if(w->color == RED) 199 | { 200 | //改变w和parent[x]的颜色 201 | w->color = BLACK; 202 | x->parent->color = RED; 203 | //对parent[x]进行一次左旋 204 | Left_Rotate(T, x->parent); 205 | //令w为x的新兄弟 206 | w = x->parent->right; 207 | //转为2.3.4三种情况之一 208 | } 209 | //第二情况:w为黑色,w的两个孩子也都是黑色 210 | if(w->left->color == BLACK && w->right->color == BLACK) 211 | { 212 | //去掉w和x的黑色 213 | //w只有一层黑色,去掉变为红色,x有多余的一层黑色,去掉后恢复原来颜色 214 | w->color = RED; 215 | //在parent[x]上补一层黑色 216 | x = x->parent; 217 | //现在新x上有个额外的黑色,转入for循环继续处理 218 | } 219 | //第三种情况,w是黑色的,w->left是红色的,w->right是黑色的 220 | else 221 | { 222 | if(w->right->color == BLACK) 223 | { 224 | //改变w和left[x]的颜色 225 | w->left->color = BLACK; 226 | w->color = RED; 227 | //对w进行一次右旋 228 | Right_Rotate(T, w); 229 | //令w为x的新兄弟 230 | w = x->parent->right; 231 | //此时转变为第四种情况 232 | } 233 | //第四种情况:w是黑色的,w->left是黑色的,w->right是红色的 234 | //修改w和parent[x]的颜色 235 | w->color =x->parent->color; 236 | x->parent->color = BLACK; 237 | w->right->color = BLACK; 238 | //对parent[x]进行一次左旋 239 | Left_Rotate(T, x->parent); 240 | //此时调整已经结束,将x置为根结点是为了结束循环 241 | x = T->root; 242 | } 243 | } 244 | //若x是其父的左结点(右结点的情况相对应) 245 | else if(x == x->parent->right) 246 | { 247 | //令w为x的兄弟,根据w的不同,分为三种情况来处理 248 | //执行删除操作前x肯定是没有兄弟的,执行删除操作后x肯定是有兄弟的 249 | w = x->parent->left; 250 | //第一种情况:w是红色的 251 | if(w->color == RED) 252 | { 253 | //改变w和parent[x]的颜色 254 | w->color = BLACK; 255 | x->parent->color = RED; 256 | //对parent[x]进行一次左旋 257 | Right_Rotate(T, x->parent); 258 | //令w为x的新兄弟 259 | w = x->parent->left; 260 | //转为2.3.4三种情况之一 261 | } 262 | //第二情况:w为黑色,w的两个孩子也都是黑色 263 | if(w->right->color == BLACK && w->left->color == BLACK) 264 | { 265 | //去掉w和x的黑色 266 | //w只有一层黑色,去掉变为红色,x有多余的一层黑色,去掉后恢复原来颜色 267 | w->color = RED; 268 | //在parent[x]上补一层黑色 269 | x = x->parent; 270 | //现在新x上有个额外的黑色,转入for循环继续处理 271 | } 272 | //第三种情况,w是黑色的,w->right是红色的,w->left是黑色的 273 | else 274 | { 275 | if(w->left->color == BLACK) 276 | { 277 | //改变w和right[x]的颜色 278 | w->right->color = BLACK; 279 | w->color = RED; 280 | //对w进行一次右旋 281 | Left_Rotate(T, w); 282 | //令w为x的新兄弟 283 | w = x->parent->left; 284 | //此时转变为第四种情况 285 | } 286 | //第四种情况:w是黑色的,w->right是黑色的,w->left是红色的 287 | //修改w和parent[x]的颜色 288 | w->color =x->parent->color; 289 | x->parent->color = BLACK; 290 | w->left->color = BLACK; 291 | //对parent[x]进行一次左旋 292 | Right_Rotate(T, x->parent); 293 | //此时调整已经结束,将x置为根结点是为了结束循环 294 | x = T->root; 295 | } 296 | } 297 | } 298 | //吸收了额外的黑色 299 | x->color = BLACK; 300 | } 301 | //找最小值 302 | node *Os_Tree_Minimum(Os_Tree *T, node *x) 303 | { 304 | //只要有比当前结点小的结点 305 | while(x->left != T->nil) 306 | x = x->left; 307 | return x; 308 | } 309 | //查找中序遍历下x结点的后继,后继是大于key[x]的最小的结点 310 | node *Os_Tree_Successor(Os_Tree *T, node *x) 311 | { 312 | //如果有右孩子 313 | if(x->right != T->nil) 314 | //右子树中的最小值 315 | return Os_Tree_Minimum(T, x->right); 316 | //如果x的右子树为空且x有后继y,那么y是x的最低祖先结点,且y的左儿子也是 317 | node *y = x->parent; 318 | while(y != NULL && x == y->right) 319 | { 320 | x = y; 321 | y = y->parent; 322 | } 323 | return y; 324 | } 325 | //递归地查询二叉查找树 326 | node *Os_Tree_Search(node *x, int k) 327 | { 328 | //找到叶子结点了还没找到,或当前结点是所查找的结点 329 | if(x->key == -1 || k == x->key) 330 | return x; 331 | //所查找的结点位于当前结点的左子树 332 | if(k < x->key) 333 | return Os_Tree_Search(x->left, k); 334 | //所查找的结点位于当前结点的左子树 335 | else 336 | return Os_Tree_Search(x->right, k); 337 | } 338 | //红黑树的删除 339 | node *Os_Tree_Delete(Os_Tree *T, node *z) 340 | { 341 | //找到结点的位置并删除,这一部分与二叉查找树的删除相同 342 | node *x, *y; 343 | if(z->left == T->nil || z->right == T->nil) 344 | y = z; 345 | else y = Os_Tree_Successor(T, z); 346 | if(y->left != T->nil) 347 | x = y->left; 348 | else x = y->right; 349 | x->parent = y->parent; 350 | if(y->parent == T->nil) 351 | T->root = x; 352 | else if(y == y->parent->left) 353 | y->parent->left = x; 354 | else 355 | y->parent->right = x; 356 | Maintaining(y->parent); 357 | if(y != z) 358 | { 359 | z->key = y->key; 360 | Maintaining(z); 361 | } 362 | //如果被删除的结点是黑色的,则需要调整 363 | if(y->color == BLACK) 364 | Os_Tree_Delete_Fixup(T, x); 365 | return y; 366 | } 367 | 368 | //查找以x为根结点的树中第i大的结点 369 | node *Os_Tree_Select(node *x, int i) 370 | { 371 | //令x左子树中点的个数为r-1, 372 | int r = x->left->size +1; 373 | //那么x是x树中第r大的结点 374 | if(r == i) 375 | return x; 376 | //第i大的元素在x->left中 377 | else if(i < r) 378 | return Os_Tree_Select(x->left, i); 379 | //第i大的元素在x->right中 380 | else 381 | return Os_Tree_Select(x->right, i - r); 382 | } 383 | 384 | int main() 385 | { 386 | //生成一棵动态顺序统计树 387 | Os_Tree *T = new Os_Tree; 388 | int m, n, i; 389 | while(cin>>n>>m) 390 | { 391 | //将1.,n依次插入到树中 392 | for(i = 1; i <= n; i++) 393 | { 394 | node *z = new node(T->nil, i); 395 | Os_Tree_Insert(T, z); 396 | } 397 | int t = n, start = 0; 398 | //还有剩余结点 399 | while(t) 400 | { 401 | //计算下一个要删除的结点在剩余结点中的位置 402 | start = (start + m - 1) % t; 403 | //找到这个结点 404 | node *ret = Os_Tree_Select(T->root, start+1); 405 | cout<key<<' '; 406 | //删除这个结点 407 | Os_Tree_Delete(T, ret); 408 | t--; 409 | } 410 | cout< File Name: section14_3.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Tue 01 Dec 2015 07:34:26 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | #define BLACK 0 12 | #define RED 1 13 | 14 | int Max(int a, int b, int c) 15 | { 16 | if(a > b) 17 | return a > c ? a : c; 18 | else 19 | return b > c ? b : c; 20 | } 21 | //区间结构 22 | struct interval 23 | { 24 | int low; 25 | int high; 26 | interval(int l, int h):low(l), high(h){} 27 | }; 28 | //区间树结点结构 29 | struct node 30 | { 31 | node *left; 32 | node *right; 33 | node *p; 34 | int key; 35 | bool color; 36 | interval inte; 37 | int max; 38 | node(node *init, int l, int h):left(init),right(init),p(init),key(l),inte(l,h),max(h),color(BLACK){} 39 | }; 40 | //a和b是否重叠,若重叠,返回1 41 | bool Overlap(interval a, interval b) 42 | { 43 | //a在b的左边 44 | if(a.high < b.low) 45 | return 0; 46 | //a在b的右边 47 | if(a.low > b.high) 48 | return 0; 49 | return 1; 50 | } 51 | 52 | //区间树结构 53 | class Interval_Tree 54 | { 55 | public: 56 | node *root;//根结点 57 | node *nil;//哨兵 58 | /*构造函数*/ 59 | Interval_Tree(){nil = new node(NULL, -1, -1);root = nil;}; 60 | /*红黑树相关函数*/ 61 | void Left_Rotate(node *x);//左旋 62 | void Right_Rotate(node *x);//右旋 63 | void Insert_Fixup(node *z);//插入调整 64 | void Insert(node *z);//插入 65 | void Delete_Fixup(node *x);//删除调整 66 | node *Delete(node *z);//删除 67 | void Print();//输出 68 | void Print(node *x);//输出 69 | node *Search(node *x, int k);//在x的子树中查找关键字为k的结点 70 | node *Tree_Successor(node *x);//求后继 71 | node *Tree_Minimum(node *x);//求关键字最小的点 72 | /*区间树相关函数*/ 73 | node *Interval_Search(interval i); 74 | }; 75 | //左旋,令y = x->right, 左旋是以x和y之间的链为支轴进行旋转 76 | //涉及到的结点包括:x,y,y->left,令node={p,l,r},具体变化如下: 77 | //x={x->p,x->left,y}变为{y,x->left,y->left} 78 | //y={x,y->left,y->right}变为{x->p,x,y->right} 79 | //y->left={y,y->left->left,y->left->right}变为{x,y->left->left,y->left->right} 80 | void Interval_Tree::Left_Rotate(node *x) 81 | { 82 | //令y = x->right 83 | node *y = x->right; 84 | //按照上面的方式修改三个结点的指针,注意修改指针的顺序 85 | x->right = y->left; 86 | if(y->left != nil) 87 | y->left->p = x; 88 | y->p = x->p; 89 | if(x->p == nil)//特殊情况:x是根结点 90 | root = y; 91 | else if(x == x->p->left) 92 | x->p->left = y; 93 | else 94 | x->p->right = y; 95 | y->left = x; 96 | x->p = y; 97 | //对附加信息的维护 98 | y->max = x->max; 99 | x->max = Max(x->inte.high, x->left->max, x->right->max); 100 | } 101 | //右旋,令y = x->left, 左旋是以x和y之间的链为支轴进行旋转 102 | //旋转过程与上文类似 103 | void Interval_Tree::Right_Rotate(node *x) 104 | { 105 | node *y = x->left; 106 | x->left = y->right; 107 | if(y->right != nil) 108 | y->right->p = x; 109 | y->p = x->p; 110 | if(x->p == nil) 111 | root = y; 112 | else if(x == x->p->right) 113 | x->p->right = y; 114 | else 115 | x->p->left = y; 116 | y->right = x; 117 | x->p = y; 118 | //对附加信息的维护 119 | y->max = x->max; 120 | x->max = Max(x->inte.high, x->left->max, x->right->max); 121 | } 122 | //红黑树调整 123 | void Interval_Tree::Insert_Fixup(node *z) 124 | { 125 | node *y; 126 | //唯一需要调整的情况,就是违反性质2的时候,如果不违反性质2,调整结束 127 | while(z->p->color == RED) 128 | { 129 | //p[z]是左孩子时,有三种情况 130 | if(z->p == z->p->p->left) 131 | { 132 | //令y是z的叔结点 133 | y = z->p->p->right; 134 | //第一种情况,z的叔叔y是红色的 135 | if(y->color == RED) 136 | { 137 | //将p[z]和y都着为黑色以解决z和p[z]都是红色的问题 138 | z->p->color = BLACK; 139 | y->color = BLACK; 140 | //将p[p[z]]着为红色以保持性质5 141 | z->p->p->color = RED; 142 | //把p[p[z]]当作新增的结点z来重复while循环 143 | z = z->p->p; 144 | } 145 | else 146 | { 147 | //第二种情况:z的叔叔是黑色的,且z是右孩子 148 | if(z == z->p->right) 149 | { 150 | //对p[z]左旋,转为第三种情况 151 | z = z->p; 152 | Left_Rotate(z); 153 | } 154 | //第三种情况:z的叔叔是黑色的,且z是左孩子 155 | //交换p[z]和p[p[z]]的颜色,并右旋 156 | z->p->color = BLACK; 157 | z->p->p->color = RED; 158 | Right_Rotate(z->p->p); 159 | } 160 | } 161 | //p[z]是右孩子时,有三种情况,与上面类似 162 | else if(z->p == z->p->p->right) 163 | { 164 | y = z->p->p->left; 165 | if(y->color == RED) 166 | { 167 | z->p->color = BLACK; 168 | y->color = BLACK; 169 | z->p->p->color = RED; 170 | z = z->p->p; 171 | } 172 | else 173 | { 174 | if(z == z->p->left) 175 | { 176 | z = z->p; 177 | Right_Rotate(z); 178 | } 179 | z->p->color = BLACK; 180 | z->p->p->color = RED; 181 | Left_Rotate(z->p->p); 182 | } 183 | } 184 | } 185 | //根结点置为黑色 186 | root->color = BLACK; 187 | } 188 | //插入一个结点 189 | void Interval_Tree::Insert(node *z) 190 | { 191 | node *y = nil, *x = root; 192 | //找到应该插入的位置,与二叉查找树的插入相同 193 | while(x != nil) 194 | { 195 | x->max = max(x->max, z->max); 196 | y = x; 197 | if(z->key < x->key) 198 | x = x->left; 199 | else 200 | x = x->right; 201 | } 202 | z->p = y; 203 | if(y == nil) 204 | root = z; 205 | else if(z->key < y->key) 206 | y->left = z; 207 | else 208 | y->right = z; 209 | z->left = nil; 210 | z->right = nil; 211 | //将新插入的结点转为红色 212 | z->color = RED; 213 | //从新插入的结点开始,向上调整 214 | Insert_Fixup(z); 215 | } 216 | //对树进行调整,x指向一个红黑结点,调整的过程是将额外的黑色沿树上移 217 | void Interval_Tree::Delete_Fixup(node *x) 218 | { 219 | node *w; 220 | //如果这个额外的黑色在一个根结点或一个红结点上,结点会吸收额外的黑色,成为一个黑色的结点 221 | while(x != root && x->color == BLACK) 222 | { 223 | //若x是其父的左结点(右结点的情况相对应) 224 | if(x == x->p->left) 225 | { 226 | //令w为x的兄弟,根据w的不同,分为三种情况来处理 227 | //执行删除操作前x肯定是没有兄弟的,执行删除操作后x肯定是有兄弟的 228 | w = x->p->right; 229 | //第一种情况:w是红色的 230 | if(w->color == RED) 231 | { 232 | //改变w和p[x]的颜色 233 | w->color = BLACK; 234 | x->p->color = RED; 235 | //对p[x]进行一次左旋 236 | Left_Rotate(x->p); 237 | //令w为x的新兄弟 238 | w = x->p->right; 239 | //转为2.3.4三种情况之一 240 | } 241 | //第二情况:w为黑色,w的两个孩子也都是黑色 242 | if(w->left->color == BLACK && w->right->color == BLACK) 243 | { 244 | //去掉w和x的黑色 245 | //w只有一层黑色,去掉变为红色,x有多余的一层黑色,去掉后恢复原来颜色 246 | w->color = RED; 247 | //在p[x]上补一层黑色 248 | x = x->p; 249 | //现在新x上有个额外的黑色,转入for循环继续处理 250 | } 251 | //第三种情况,w是黑色的,w->left是红色的,w->right是黑色的 252 | else 253 | { 254 | if(w->right->color == BLACK) 255 | { 256 | //改变w和left[x]的颜色 257 | w->left->color = BLACK; 258 | w->color = RED; 259 | //对w进行一次右旋 260 | Right_Rotate(w); 261 | //令w为x的新兄弟 262 | w = x->p->right; 263 | //此时转变为第四种情况 264 | } 265 | //第四种情况:w是黑色的,w->left是黑色的,w->right是红色的 266 | //修改w和p[x]的颜色 267 | w->color =x->p->color; 268 | x->p->color = BLACK; 269 | w->right->color = BLACK; 270 | //对p[x]进行一次左旋 271 | Left_Rotate(x->p); 272 | //此时调整已经结束,将x置为根结点是为了结束循环 273 | x = root; 274 | } 275 | } 276 | //若x是其父的左结点(右结点的情况相对应) 277 | else if(x == x->p->right) 278 | { 279 | //令w为x的兄弟,根据w的不同,分为三种情况来处理 280 | //执行删除操作前x肯定是没有兄弟的,执行删除操作后x肯定是有兄弟的 281 | w = x->p->left; 282 | //第一种情况:w是红色的 283 | if(w->color == RED) 284 | { 285 | //改变w和p[x]的颜色 286 | w->color = BLACK; 287 | x->p->color = RED; 288 | //对p[x]进行一次左旋 289 | Right_Rotate(x->p); 290 | //令w为x的新兄弟 291 | w = x->p->left; 292 | //转为2.3.4三种情况之一 293 | } 294 | //第二情况:w为黑色,w的两个孩子也都是黑色 295 | if(w->right->color == BLACK && w->left->color == BLACK) 296 | { 297 | //去掉w和x的黑色 298 | //w只有一层黑色,去掉变为红色,x有多余的一层黑色,去掉后恢复原来颜色 299 | w->color = RED; 300 | //在p[x]上补一层黑色 301 | x = x->p; 302 | //现在新x上有个额外的黑色,转入for循环继续处理 303 | } 304 | //第三种情况,w是黑色的,w->right是红色的,w->left是黑色的 305 | else 306 | { 307 | if(w->left->color == BLACK) 308 | { 309 | //改变w和right[x]的颜色 310 | w->right->color = BLACK; 311 | w->color = RED; 312 | //对w进行一次右旋 313 | Left_Rotate(w); 314 | //令w为x的新兄弟 315 | w = x->p->left; 316 | //此时转变为第四种情况 317 | } 318 | //第四种情况:w是黑色的,w->right是黑色的,w->left是红色的 319 | //修改w和p[x]的颜色 320 | w->color =x->p->color; 321 | x->p->color = BLACK; 322 | w->left->color = BLACK; 323 | //对p[x]进行一次左旋 324 | Right_Rotate(x->p); 325 | //此时调整已经结束,将x置为根结点是为了结束循环 326 | x = root; 327 | } 328 | } 329 | } 330 | //吸收了额外的黑色 331 | x->color = BLACK; 332 | } 333 | //找最小值 334 | node *Interval_Tree::Tree_Minimum(node *x) 335 | { 336 | //只要有比当前结点小的结点 337 | while(x->left != nil) 338 | x = x->left; 339 | return x; 340 | } 341 | //查找中序遍历下x结点的后继,后继是大于key[x]的最小的结点 342 | node *Interval_Tree::Tree_Successor(node *x) 343 | { 344 | //如果有右孩子 345 | if(x->right != nil) 346 | //右子树中的最小值 347 | return Tree_Minimum(x->right); 348 | //如果x的右子树为空且x有后继y,那么y是x的最低祖先结点,且y的左儿子也是 349 | node *y = x->p; 350 | while(y != NULL && x == y->right) 351 | { 352 | x = y; 353 | y = y->p; 354 | } 355 | return y; 356 | } 357 | //递归地查询二叉查找树 358 | node *Interval_Tree::Search(node *x, int k) 359 | { 360 | //找到叶子结点了还没找到,或当前结点是所查找的结点 361 | if(x->key == -1 || k == x->key) 362 | return x; 363 | //所查找的结点位于当前结点的左子树 364 | if(k < x->key) 365 | return Search(x->left, k); 366 | //所查找的结点位于当前结点的左子树 367 | else 368 | return Search(x->right, k); 369 | } 370 | //红黑树的删除 371 | node *Interval_Tree::Delete(node *z) 372 | { 373 | //找到结点的位置并删除,这一部分与二叉查找树的删除相同 374 | node *x, *y, *p; 375 | if(z->left == nil || z->right == nil) 376 | { 377 | y = z; 378 | p = y->p; 379 | p->max = p->inte.high; 380 | p = p->p; 381 | while(p->max == y->max) 382 | { 383 | p->max = Max(p->max, p->left->max, p->right->max); 384 | p = p->p; 385 | } 386 | } 387 | else y = Tree_Successor(z); 388 | //对附加信息的维护 389 | p = y->p; 390 | p->max = p->inte.high; 391 | p = p->p; 392 | while(p->max == y->max) 393 | { 394 | p->max = Max(p->max, p->left->max, p->right->max); 395 | p = p->p; 396 | } 397 | //删除y结点 398 | if(y->left != nil) 399 | x = y->left; 400 | else x = y->right; 401 | x->p = y->p; 402 | if(y->p == nil) 403 | root = x; 404 | else if(y == y->p->left) 405 | y->p->left = x; 406 | else 407 | y->p->right = x; 408 | //替换 409 | if(y != z) 410 | { 411 | z->inte = y->inte; 412 | z->key = y->key; 413 | z->max = y->max; 414 | p = z->p; 415 | while(p->max < z->max) 416 | { 417 | p->max = z->max; 418 | p = p->p; 419 | } 420 | } 421 | //如果被删除的结点是黑色的,则需要调整 422 | if(y->color == BLACK) 423 | Delete_Fixup(x); 424 | return y; 425 | } 426 | void Interval_Tree::Print(node *x) 427 | { 428 | if(x->key == -1) 429 | return; 430 | Print(x->left); 431 | cout<inte.low<<' '<inte.high<right); 433 | } 434 | 435 | void Interval_Tree::Print() 436 | { 437 | Print(root); 438 | cout<inte)) 448 | { 449 | //在左子树中 450 | if(x->left != nil && x->left->max >= i.low) 451 | x = x->left; 452 | //在右子树中 453 | else 454 | x = x->right; 455 | } 456 | return x; 457 | } 458 | -------------------------------------------------------------------------------- /src/chapter15/Exercise15_1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | #define ARRAY_SIZE 15 7 | #include "Exercise15_1.h" 8 | 9 | //用于排序 10 | static bool cmp(coord a, coord b) 11 | { 12 | return a.x < b.x; 13 | } 14 | //计算d[i][j] 15 | double dis(const vector &s, int i, int j) 16 | { 17 | double temp = pow((s[i].x-s[j].x)*1.0, 2) + pow((s[i].y-s[j].y)*1.0, 2); 18 | return sqrt(temp); 19 | } 20 | 21 | double Double_adjustable_Euclidean_traveling_salesman(vector s) 22 | { 23 | return 0; 24 | //int n = s.size(); 25 | //if(n == 0)return 0; 26 | // int i, j, k; 27 | //根据x从小到大排序 28 | // sort(s.begin(), s.end(), cmp); 29 | double ans[ARRAY_SIZE][ARRAY_SIZE] = {0}; 30 | #if 0 31 | for(i = 0; i < n; i++) 32 | { 33 | //s[0][0]=0 34 | //(2)当j=i时,s[i][j]=s[i][i]=s[i][i-1]+d[i-1][i] 35 | if(i)ans[i][i] = ans[i][i-1] + dis(s, i-1, i); 36 | //(3)当j=i+1时,s[i][j]=MIN(s[i][k]+d[k][j]),其中0<=ki+1时,s[i][j]=s[i][j-1]+d[j-1][j] 57 | for(j = i + 2; j < n; j++) 58 | { 59 | //s[i][j]=s[j][i] 60 | ans[i][j] = ans[i][j-1] + dis(s, j-1, j); 61 | ans[j][i] = ans[i][j]; 62 | } 63 | } 64 | #endif 65 | //cout< File Name: Exercise16_1_1.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Tue 24 Nov 2015 07:16:57 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | #define N 11 13 | //一个活动用一个结点表示 14 | struct node 15 | { 16 | int id; //id号,因为要排序 17 | int start; //开始时间 18 | int finish; //结束时间 19 | }A[N+2]; 20 | bool cmp(node a, node b) 21 | { 22 | return a.finish < b.finish; 23 | } 24 | int s[N+2][N+2] = {0}; 25 | //16.1-1 26 | void DP() 27 | { 28 | int step, i, j, k; 29 | //根据Sij的定义,当jA[j].start时,Sij为空集,c[i][j]=0 39 | if(A[i].finish <= A[j].start) 40 | { 41 | for(k = i + 1; k < j; k++) 42 | { 43 | //根据公式16.3,取k的条件是Ak属于Sij 44 | if(A[k].start < A[i].finish || A[k].finish > A[j].start) 45 | continue; 46 | //根据公式16.3计算 47 | int temp = s[i][k] + s[k][j] + 1; 48 | if(temp > s[i][j]) 49 | s[i][j] = temp; 50 | } 51 | } 52 | } 53 | } 54 | } 55 | cout< A[end].start) 70 | continue; 71 | if(s[start][k] + s[k][end] + 1 == s[start][end]) 72 | { 73 | //输出第K个活动之前的活动 74 | Print(start, k); 75 | //输出第k个活动的id 76 | cout<>A[i].start>>A[i].finish; 107 | } 108 | //增加结束活动AN+1,s[AN+1] = 0x7fffffff 109 | A[i].id = i; 110 | A[i].start = A[i].finish = 0x7fffffff; 111 | //按结束时间从小到大排序 112 | sort(A, A+N+2, cmp); 113 | //DP 114 | DP(); 115 | //输出结果 116 | Print(0, N+1); 117 | cout< File Name: Exercise16_2_6.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Thu 22 Oct 2015 06:21:45 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | #include 12 | #include "Exercise16_2_6.h" 13 | 14 | int Partition(node *A, int p, int r) 15 | { 16 | node x = A[r]; 17 | int i = p-1, j; 18 | for(j = p; j < r; j++) 19 | { 20 | //划分的依据是avg = value / weight 21 | double t1 = x.value * 1.0 / x.weight; 22 | double t2 = A[j].value * 1.0 / A[j].weight; 23 | if(t2 >= t1) 24 | { 25 | i++; 26 | swap(A[i], A[j]); 27 | } 28 | } 29 | swap(A[i+1], A[r]); 30 | return i+1; 31 | } 32 | 33 | int Randomized_Partition(node *A, int p, int r) 34 | { 35 | //随机选择数组中一个数作为主元 36 | int i = rand() % (r-p+1) + p; 37 | swap(A[r], A[i]); 38 | //划分 39 | return Partition(A, p, r); 40 | } 41 | //i是从1开使计数的,不是从p开始 42 | double Randomized_Select(node *A, int p, int r, int weight, int value) 43 | { 44 | if(p == r) 45 | { 46 | if(A[p].weight <= weight) 47 | return value + A[p].value; 48 | else 49 | return value + (double)A[p].value * weight / A[p].weight; 50 | } 51 | else if(p > r) 52 | return value; 53 | //以某个元素为主元,把数组分为两组,A[p..q-1] < A[q] < A[q+1..r],返回主元在整个数组中的位置 54 | int q = Randomized_Partition(A, p, r); 55 | //主元是整个数组中的第q个元素 56 | int i, w = 0, v = 0; 57 | //求SG 58 | for(i = p; i < q; i++) 59 | { 60 | w = w + A[i].weight; 61 | v = v + A[i].value; 62 | } 63 | if(w == weight)//正是所求的元素 64 | return value + v; 65 | //主元物品取一部分 66 | else if(w < weight && w + A[q].weight >= weight) 67 | return value + v + (double)A[q].value * (weight-w) / A[q].weight; 68 | else if(w > weight)//所求元素<主元,则在A[p..q-1]中继续寻找 69 | return Randomized_Select(A, p, q-1, weight, value); 70 | else//所求元素>主元,则在A[q+1..r]中继续寻找 71 | return Randomized_Select(A, q+1, r, weight - w - A[q].weight, value + v + A[q].value); 72 | } 73 | 74 | double partialPackage(int weight, int len, node *material) 75 | { 76 | if(weight == 0 || len == 0) 77 | return 0; 78 | return Randomized_Select(material, 1, len-1, weight, 0); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /src/chapter16/chapter16.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "chapter16.h" 5 | 6 | void Reccursive_Activity_Selector(const vector &A, int i, vector &ret) 7 | { 8 | //找到第一个开始时间在第i个活动结束之后的活动 9 | int m = i+1, n = A.size(); 10 | while(m < n && A[m].start < A[i].finish) 11 | m++; 12 | //若找到了 13 | if(m < n) 14 | { 15 | //将这个活动作为执行活动 16 | ret.push_back(m); 17 | //递归第m个活动执行结束之后的贪心策略 18 | return Reccursive_Activity_Selector(A, m, ret); 19 | } 20 | return; 21 | } 22 | 23 | //递归贪心算法,在第i个活动执行结束之后的贪心策略,初始时i=0 24 | vector Reccursive_Activity_Selector(vector A) 25 | { 26 | vector ret; 27 | Reccursive_Activity_Selector(A, 0, ret); 28 | return ret; 29 | } 30 | 31 | //迭代的贪心算法 32 | vector Greedy_Activity_Selector(vector A) 33 | { 34 | vector ret; 35 | //在第i个活动执行结束之后的贪心策略,初始时i=0 36 | int n = A.size(), i = 0, m; 37 | for(m = 1; m < n; m++) 38 | { 39 | //找到第一个开始时间在第i个活动结束之后的活动 40 | if(A[m].start >= A[i].finish) 41 | { 42 | //将这个活动作为执行活动 43 | ret.push_back(A[m].id); 44 | //递归第m个活动执行结束之后的贪心策略 45 | i = m; 46 | } 47 | } 48 | return ret; 49 | } 50 | -------------------------------------------------------------------------------- /src/chapter20/FibHeap.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: fibHeap.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Sun 25 Oct 2015 10:15:52 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | #include 12 | #include "FibHeap.h" 13 | 14 | #define MIN_KEY -0x7fffffff 15 | 16 | errorType CFibHeap::insert(node *pNode) 17 | { 18 | if(pNode == NULL) 19 | return POINTER_NULL; 20 | 21 | addNodeToRootList(pNode); 22 | dataCount++; 23 | return SUCCESS; 24 | } 25 | 26 | int CFibHeap::getDataCount() 27 | { 28 | return dataCount; 29 | } 30 | 31 | errorType CFibHeap::merge(CFibHeap *H2) 32 | { 33 | if(H2 == NULL ) 34 | return POINTER_NULL; 35 | if( H2->getDataCount() == 0) 36 | return SUCCESS; 37 | if(pMinNode == NULL) 38 | { 39 | pMinNode = H2->pMinNode; 40 | dataCount = H2->dataCount; 41 | return SUCCESS; 42 | } 43 | 44 | addListToRootList(H2->pMinNode); 45 | dataCount += H2->dataCount; 46 | return SUCCESS; 47 | } 48 | 49 | node* CFibHeap::extract() 50 | { 51 | if(pMinNode == NULL) 52 | return NULL; 53 | 54 | node *pChildOfMin = pMinNode->pChild; 55 | if(pChildOfMin != NULL) 56 | { 57 | while(pChildOfMin != NULL && pChildOfMin->pParent == pMinNode) 58 | { 59 | pChildOfMin->pParent = NULL; 60 | pChildOfMin = pChildOfMin->pRight; 61 | } 62 | pMinNode->pChild = NULL; 63 | addListToRootList(pChildOfMin); 64 | } 65 | 66 | node *pRetNode = pMinNode; 67 | removeNodeFromRootList(pRetNode); 68 | if(pMinNode != NULL) 69 | consolidate(); 70 | dataCount--; 71 | return pRetNode; 72 | } 73 | 74 | errorType CFibHeap::decreaseKey(node *pNodeToDecrease, int newKey) 75 | { 76 | if(pNodeToDecrease == NULL) 77 | return POINTER_NULL; 78 | if(pNodeToDecrease->key < newKey) 79 | return PARAM_ERROR; 80 | if(isNodeInHeap(pNodeToDecrease) == false) 81 | return PARAM_ERROR; 82 | 83 | pNodeToDecrease->key = newKey; 84 | node *pParent = pNodeToDecrease->pParent; 85 | if(pParent != NULL && pNodeToDecrease->key < pParent->key) 86 | moveNodeToRootList(pNodeToDecrease); 87 | if(pNodeToDecrease->key < pMinNode->key) 88 | pMinNode = pNodeToDecrease; 89 | return SUCCESS; 90 | } 91 | 92 | errorType CFibHeap::deleteNode(node *pNode) 93 | { 94 | if(pNode == NULL) 95 | return POINTER_NULL; 96 | if(isNodeInHeap(pNode) == false) 97 | return PARAM_ERROR; 98 | 99 | decreaseKey(pNode, MIN_KEY); 100 | extract(); 101 | return SUCCESS; 102 | } 103 | 104 | void CFibHeap::consolidate() 105 | { 106 | int degreeOfHeap = log(dataCount*1.0) / log(2.0), i; 107 | node **A = new node*[degreeOfHeap+1]; 108 | for(int i = 0; i <= degreeOfHeap; i++) 109 | A[i] = NULL; 110 | 111 | node *pNodeOfList = pMinNode; 112 | node *pCurrentNode = pNodeOfList; 113 | do 114 | { 115 | pCurrentNode->isHandled = false; 116 | pCurrentNode = pCurrentNode->pRight; 117 | } while (pCurrentNode != pMinNode); 118 | 119 | 120 | while(pNodeOfList->isHandled == false) 121 | { 122 | pNodeOfList->isHandled = true; 123 | pCurrentNode = pNodeOfList; 124 | pNodeOfList = pNodeOfList->pRight; 125 | int degreeOfCurrentNode = pCurrentNode->degree; 126 | while(A[degreeOfCurrentNode] != NULL) 127 | { 128 | node *pNodeInA = A[degreeOfCurrentNode]; 129 | if(pNodeInA->key < pCurrentNode->key) 130 | swap(*pNodeInA, *pCurrentNode); 131 | link(pNodeInA, pCurrentNode); 132 | A[degreeOfCurrentNode] = NULL; 133 | degreeOfCurrentNode++; 134 | } 135 | A[degreeOfCurrentNode] = pCurrentNode; 136 | } 137 | 138 | pMinNode = NULL; 139 | for(int i = 0; i <= degreeOfHeap; i++) 140 | if(A[i] != NULL) 141 | addNodeToRootList(A[i]); 142 | 143 | delete []A; 144 | } 145 | 146 | void CFibHeap::link(node *y, node *x) 147 | { 148 | removeNodeFromRootList(y); 149 | addChildToParent(y, x); 150 | y->isOneChildDeleted = false; 151 | } 152 | 153 | void CFibHeap::moveNodeToRootList(node *pNode) 154 | { 155 | node *pParent = pNode->pParent; 156 | deleteChildFromParent(pNode); 157 | addNodeToRootList(pNode); 158 | pNode->isOneChildDeleted = false; 159 | 160 | if(pParent->isOneChildDeleted == false) 161 | pParent->isOneChildDeleted = true; 162 | else if(pParent->pParent != NULL) 163 | moveNodeToRootList(pParent); 164 | } 165 | 166 | bool CFibHeap::isNodeInHeap(node *pNode) 167 | { 168 | node *pRootOfNode = pNode; 169 | while(pRootOfNode->pParent != NULL) 170 | pRootOfNode = pRootOfNode->pParent; 171 | node *pCurrentNode = pRootOfNode; 172 | do 173 | { 174 | if(pCurrentNode == pMinNode) 175 | break; 176 | else 177 | pCurrentNode = pCurrentNode->pRight; 178 | } while (pCurrentNode != pRootOfNode); 179 | if(pCurrentNode != pMinNode) 180 | return false; 181 | else 182 | return true; 183 | } 184 | void CFibHeap::addNodeToRootList(node *pNode) 185 | { 186 | pNode->pParent = NULL; 187 | if(pMinNode != NULL) 188 | { 189 | pNode->pRight = pMinNode->pRight; 190 | pNode->pLeft = pMinNode; 191 | pMinNode->pRight->pLeft = pNode; 192 | pMinNode->pRight = pNode; 193 | } 194 | if(pMinNode == NULL || pNode->key < pMinNode->key) 195 | { 196 | pMinNode = pNode; 197 | } 198 | } 199 | 200 | void CFibHeap::addListToRootList(node *pNodeOfList) 201 | { 202 | node *t = pMinNode->pRight; 203 | pMinNode->pRight = pNodeOfList; 204 | pNodeOfList->pLeft->pRight = t; 205 | t->pLeft = pNodeOfList->pLeft; 206 | pNodeOfList->pLeft = pMinNode; 207 | if(pMinNode->key > pNodeOfList->key) 208 | pMinNode = pNodeOfList; 209 | } 210 | 211 | void CFibHeap::removeNodeFromRootList(node *pRootNode) 212 | { 213 | if(pRootNode->pRight == pRootNode) 214 | pMinNode = NULL; 215 | else 216 | { 217 | if(pMinNode == pRootNode) 218 | pMinNode = pRootNode->pRight; 219 | pRootNode->pRight->pLeft = pRootNode->pLeft; 220 | pRootNode->pLeft->pRight = pRootNode->pRight; 221 | } 222 | } 223 | 224 | void CFibHeap::addChildToParent(node *pChild, node *pParent) 225 | { 226 | if(pParent->pChild == NULL) 227 | { 228 | pParent->pChild = pChild; 229 | pChild->pRight = pChild; 230 | pChild->pLeft = pChild; 231 | } 232 | else 233 | { 234 | node *pOriginChildOfParent = pParent->pChild; 235 | pChild->pRight = pOriginChildOfParent->pRight; 236 | pChild->pLeft = pOriginChildOfParent; 237 | pOriginChildOfParent->pRight->pLeft = pChild; 238 | pOriginChildOfParent->pRight = pChild; 239 | } 240 | pChild->pParent = pParent; 241 | pParent->degree++; 242 | } 243 | 244 | void CFibHeap::deleteChildFromParent(node *pNode) 245 | { 246 | node *pParent = pNode->pParent; 247 | if(pNode->pRight == pNode) 248 | pParent->pChild = NULL; 249 | else 250 | { 251 | if(pParent->pChild == pNode) 252 | pParent->pChild = pNode->pRight; 253 | pNode->pRight->pLeft = pNode->pLeft; 254 | pNode->pLeft->pRight = pNode->pRight; 255 | } 256 | pParent->degree--; 257 | } 258 | -------------------------------------------------------------------------------- /src/chapter22/Exercise22_3_6.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | #include "Exercise22_3_6.h" 6 | 7 | stack S;//用栈代替递归实现DFS 8 | int depth = 0; 9 | 10 | //插入边 11 | void InsertEdge(Graph *G, Edge *E) 12 | { 13 | //如果没有相同起点的边 14 | if(G->V[E->start]->head == NULL) 15 | G->V[E->start]->head =E; 16 | //如果有,加入到链表中,递增顺序排列,便于查重 17 | else 18 | { 19 | //链表的插入,不解释 20 | Edge *e1 = G->V[E->start]->head, *e2 = e1; 21 | while(e1 && e1->end < E->end) 22 | { 23 | e2 = e1; 24 | e1 = e1->next; 25 | } 26 | if(e1 && e1->end == E->end) 27 | return; 28 | if(e1 == e2) 29 | { 30 | E->next = e1; 31 | G->V[E->start]->head =E; 32 | } 33 | else 34 | { 35 | e2->next = E; 36 | E->next = e1; 37 | } 38 | } 39 | } 40 | //访问某顶点 41 | void DFS_Visit(Graph *G, Vertex *u) 42 | { 43 | //将u置为黑色 44 | u->color = GRAY; 45 | //使全局变量depth增值 46 | depth++; 47 | //将depth的新值记录为发现时间 48 | u->d = depth; 49 | //当前元素出发的第一条边入栈 50 | Edge *E = u->head; 51 | if(E) 52 | S.push(E); 53 | while(!S.empty()) 54 | { 55 | //取栈顶元素 56 | Edge *e = S.top(); 57 | //检查和栈顶元素相邻的每个顶点v 58 | Vertex *v = G->V[e->end]; 59 | //如果顶点为白色 60 | if(v->color == WHITE) 61 | { 62 | //递归访问顶点 63 | v->color = GRAY; 64 | depth++; 65 | v->d = depth; 66 | v->p = u; 67 | e->type = 1; 68 | //将下一条边入栈,下一条边可能有两种情况 69 | if(v->head) 70 | S.push(v->head); 71 | else 72 | { 73 | while(e && e->next == NULL) 74 | { 75 | depth++; 76 | G->V[e->end]->f = depth; 77 | G->V[e->end]->color = BLACK; 78 | S.pop(); 79 | if(S.empty())e = NULL; 80 | else e = S.top(); 81 | } 82 | if(e && e->next) 83 | S.push(e->next); 84 | } 85 | 86 | } 87 | else 88 | { 89 | //判断边的类型 90 | if(v->color == BLACK) 91 | { 92 | if(u->d < v->d) 93 | e->type = 3; 94 | else 95 | e->type = 4; 96 | } 97 | else if(v->color == GRAY) 98 | e->type = 2; 99 | //出栈,并将下一条边入栈 100 | while(e && e->next == NULL) 101 | { 102 | depth++; 103 | G->V[e->start]->f = depth; 104 | G->V[e->start]->color = BLACK; 105 | S.pop(); 106 | if(S.empty())e = NULL; 107 | else e = S.top(); 108 | } 109 | if(e && e->next) 110 | { 111 | S.pop(); 112 | S.push(e->next); 113 | } 114 | } 115 | } 116 | } 117 | //深度优先搜索 118 | void DFS(Graph *G) 119 | { 120 | int i; 121 | //对每个顶点初始化 122 | for(i = 1; i <= N; i++) 123 | { 124 | G->V[i]->color = WHITE; 125 | G->V[i]->p = NULL; 126 | } 127 | //时间戳初始化 128 | depth = 0; 129 | //依次检索V中的顶点,发现白色顶点时,调用DFS_Visit访问该顶点 130 | for(i = 1; i <= N; i++) 131 | { 132 | if(G->V[i]->color == WHITE) 133 | DFS_Visit(G, G->V[i]); 134 | } 135 | } 136 | //输出 137 | void Print(Graph *G) 138 | { 139 | int i; 140 | //遍历每个顶点 141 | for(i = 1; i <= N; i++) 142 | { 143 | cout<V[i]->head; 146 | while(e) 147 | { 148 | cout<end<<' '; 149 | e = e->next; 150 | } 151 | cout< 2 | using namespace std; 3 | #include 4 | #include "Exercise22_4_2.h" 5 | using namespace exercise22_4_2; 6 | 7 | namespace exercise22_4_2 8 | { 9 | //插入边 10 | void Graph::InsertEdge(Edge *E) 11 | { 12 | V[E->end]->indegree++; 13 | //如果没有相同起点的边 14 | if(V[E->start]->head == NULL) 15 | V[E->start]->head =E; 16 | //如果有,加入到链表中,递增顺序排列,便于查重 17 | else 18 | { 19 | //链表的插入,不解释 20 | Edge *e1 = V[E->start]->head, *e2 = e1; 21 | while(e1 && e1->end < E->end) 22 | { 23 | e2 = e1; 24 | e1 = e1->next; 25 | } 26 | if(e1 && e1->end == E->end) 27 | return; 28 | if(e1 == e2) 29 | { 30 | E->next = e1; 31 | V[E->start]->head =E; 32 | } 33 | else 34 | { 35 | e2->next = E; 36 | E->next = e1; 37 | } 38 | } 39 | } 40 | 41 | int Graph::countWays(int start, int end) 42 | { 43 | int count[MAX_NUM_OF_VERTEX+1] = {0}; 44 | count[start] = 1; 45 | queue Q; 46 | for(int i = 1;i <= numOfVertex; i++ ) 47 | { 48 | if(V[i]->indegree == 0) 49 | Q.push(i); 50 | } 51 | while(Q.empty() == false) 52 | { 53 | int q = Q.front(); 54 | Q.pop(); 55 | if(q == end) 56 | return count[q]; 57 | Edge *head = V[q]->head; 58 | while(head != NULL) 59 | { 60 | V[head->end]->indegree--; 61 | count[head->end] += count[q]; 62 | if(V[head->end]->indegree == 0) 63 | Q.push(head->end); 64 | head = head->next; 65 | } 66 | } 67 | return 0; 68 | } 69 | }; 70 | -------------------------------------------------------------------------------- /src/chapter22/section22_3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | #define N 100 6 | 7 | #define WHITE 0 8 | #define GRAY 1 9 | #define BLACK 2 10 | 11 | #define NONE 0 12 | #define TREE 1 13 | #define BACK 2 14 | #define FORWARD 3 15 | #define CROSS 4 16 | 17 | struct Edge 18 | { 19 | int start; 20 | int end; 21 | int value; 22 | int type; 23 | Edge *next; 24 | Edge(int s, int e, int v) 25 | :start(s),end(e),value(v),type(NONE),next(NULL){} 26 | }; 27 | struct Vertex 28 | { 29 | int d, f;//第一次被发现的时间和结束检查的时间 30 | int color;//顶点的颜色 31 | int p;//指向遍历结果的父结点 32 | Edge *head;//指向以该顶点为起点的下一条边 33 | Vertex():color(WHITE),p(0),head(NULL){}; 34 | }; 35 | class Link_Graph 36 | { 37 | public: 38 | int time; 39 | int n; 40 | Vertex *V; 41 | Link_Graph(int num):n(num) 42 | { 43 | V = new Vertex[n+1]; 44 | } 45 | ~Link_Graph(){delete []V;} 46 | void AddSingleEdge(int start, int end, int value = 1) 47 | { 48 | Edge *NewEdge = new Edge(start, end, value); 49 | if(V[start].head == NULL || V[start].head->end > end) 50 | { 51 | NewEdge->next = V[start].head; 52 | V[start].head = NewEdge; 53 | } 54 | else 55 | { 56 | Edge *e = V[start].head, *pre = e; 57 | while(e != NULL && e->end < end) 58 | { 59 | pre = e; 60 | e = e->next; 61 | } 62 | if(e && e->end == end) 63 | { 64 | delete NewEdge; 65 | return; 66 | } 67 | NewEdge->next = e; 68 | pre->next = NewEdge; 69 | } 70 | } 71 | void AddDoubleEdge(int a, int b, int value = 1) 72 | { 73 | AddSingleEdge(a, b, value); 74 | AddSingleEdge(b, a, value); 75 | } 76 | void DeleteSingleEdge(int start, int end) 77 | { 78 | Edge *e = V[start].head, *pre = e; 79 | while(e && e->end < end) 80 | { 81 | pre = e; 82 | e = e->next; 83 | } 84 | if(e == NULL || e->end > end) return; 85 | if(e == V[start].head) 86 | V[start].head = e->next; 87 | else 88 | pre->next = e->next; 89 | delete e; 90 | } 91 | void DeleteDoubleEdge(int a, int b) 92 | { 93 | DeleteSingleEdge(a, b); 94 | DeleteSingleEdge(b, a); 95 | } 96 | //22.3 97 | void DFS(); 98 | void DFS_Visit(int u); 99 | void Print_Vertex_Time(); 100 | void Print_Edge_Type(); 101 | }; 102 | 103 | void Link_Graph::DFS() 104 | { 105 | int u; 106 | //对每个顶点初始化 107 | for(u = 1; u <= n; u++) 108 | { 109 | V[u].color = WHITE; 110 | V[u].p = NULL; 111 | } 112 | //时间戳初始化 113 | time = 0; 114 | //依次检索V中的顶点,发现白色顶点时,调用DFS_Visit访问该顶点 115 | for(u = 1; u <= n; u++) 116 | if(V[u].color == WHITE) 117 | DFS_Visit(u); 118 | } 119 | 120 | void Link_Graph::DFS_Visit(int u) 121 | { 122 | int v; 123 | Edge *e; 124 | //将u置为灰色 125 | V[u].color = GRAY; 126 | //使全局变量time增值 127 | time++; 128 | //将time的新值记录为发现时间 129 | V[u].d = time; 130 | e = V[u].head; 131 | while(e) 132 | { 133 | v = e->end; 134 | //如果顶点为白色 135 | if(V[v].color == WHITE) 136 | { 137 | //递归访问顶点 138 | V[v].p = u; 139 | DFS_Visit(v); 140 | //树边 141 | e->type = TREE; 142 | } 143 | else if(V[v].color == GRAY) 144 | { 145 | //反向边 146 | e->type = BACK; 147 | } 148 | else if(V[v].color == BLACK) 149 | { 150 | //正向边 151 | if(V[u].d < V[v].d) 152 | e->type = FORWARD; 153 | //交叉边 154 | else 155 | e->type = CROSS; 156 | } 157 | e = e->next; 158 | } 159 | //以u为起点的所有边都被探寻后,置u为黑色 160 | V[u].color = BLACK; 161 | //并将完成时间记录在f[u]中 162 | time++; 163 | V[u].f = time; 164 | } 165 | 166 | void Link_Graph::Print_Vertex_Time() 167 | { 168 | int i; 169 | for(i = 1; i <= n; i++) 170 | { 171 | //因为书中的例子中用从q开始的字母编号的,所以输出的时候有这样一个转换 172 | cout<start+'p')<<"->"<end+'p')<<": "; 186 | switch (e->type) 187 | { 188 | case TREE: 189 | cout<<"树边"<next; 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /src/chapter22/section22_4.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: section22_4.cpp 3 | > Created Time: Mon 23 Nov 2015 07:57:00 PM CST 4 | ************************************************************************/ 5 | 6 | //用邻接表实现图的转置 7 | #include 8 | using namespace std; 9 | 10 | #define N 14 11 | #define WHITE 0 12 | #define GRAY 1 13 | #define BLACK 2 14 | 15 | 16 | //边结点结构 17 | struct Edge 18 | { 19 | int start;//有向图的起点 20 | int end;//有向图的终点 21 | Edge *next;//指向同一个起点的下一条边 22 | int type;//边的类型 23 | Edge(int s, int e):start(s),end(e),next(NULL){} 24 | }; 25 | //顶点结点结构 26 | struct Vertex 27 | { 28 | int id; 29 | Edge *head;//指向以该顶点为起点的下一条边 30 | int color;//顶点的颜色 31 | Vertex *p;//指向遍历结果的父结点 32 | int d, f;//第一次被发现的时间和结束检查的时间 33 | Vertex(int i):head(NULL),color(WHITE),p(NULL),d(0x7fffffff),id(i){} 34 | }; 35 | //图结构 36 | struct Graph 37 | { 38 | Vertex *V[N+1];//N个顶点 39 | Graph() 40 | { 41 | int i; 42 | for(i = 1; i <= N; i++) 43 | V[i] = new Vertex(i); 44 | } 45 | ~Graph() 46 | { 47 | int i; 48 | for(i = 1; i <= N; i++) 49 | delete V[i]; 50 | } 51 | }; 52 | 53 | int time = 0; 54 | 55 | //插入边 56 | void InsertEdge(Graph *G, Edge *E) 57 | { 58 | //如果没有相同起点的边 59 | if(G->V[E->start]->head == NULL) 60 | G->V[E->start]->head =E; 61 | //如果有,加入到链表中,递增顺序排列,便于查重 62 | else 63 | { 64 | //链表的插入,不解释 65 | Edge *e1 = G->V[E->start]->head, *e2 = e1; 66 | while(e1 && e1->end < E->end) 67 | { 68 | e2 = e1; 69 | e1 = e1->next; 70 | } 71 | if(e1 && e1->end == E->end) 72 | return; 73 | if(e1 == e2) 74 | { 75 | E->next = e1; 76 | G->V[E->start]->head =E; 77 | } 78 | else 79 | { 80 | e2->next = E; 81 | E->next = e1; 82 | } 83 | } 84 | } 85 | //访问某顶点 86 | void DFS_Visit(Graph *G, Vertex *u) 87 | { 88 | //将u置为黑色 89 | u->color = GRAY; 90 | //使全局变量time增值 91 | time++; 92 | //将time的新值记录为发现时间 93 | u->d = time; 94 | //检查和u相邻的每个顶点v 95 | Vertex *v; 96 | Edge *e = u->head; 97 | while(e) 98 | { 99 | v = G->V[e->end]; 100 | //如果顶点为白色 101 | if(v->color == WHITE) 102 | { 103 | //递归访问顶点 104 | v->p = u; 105 | DFS_Visit(G, v); 106 | //树边 107 | e->type = 1; 108 | } 109 | else if(v->color == GRAY) 110 | { 111 | //反向边 112 | e->type = 2; 113 | } 114 | else if(v->color == BLACK) 115 | { 116 | //正向边 117 | if(u->d < v->d) 118 | e->type = 3; 119 | //交叉边 120 | else 121 | e->type = 4; 122 | } 123 | e = e->next; 124 | } 125 | //以u为起点的所有边都被探寻后,置u为黑色 126 | u->color = BLACK; 127 | //并将完成时间记录在f[u]中 128 | time++; 129 | //按最后访问时间f输出 130 | cout<<(char)(u->id + 'l')<<' '; 131 | u->f = time; 132 | } 133 | //深度优先搜索 134 | void DFS(Graph *G) 135 | { 136 | int i; 137 | //对每个顶点初始化 138 | for(i = 1; i <= N; i++) 139 | { 140 | G->V[i]->color = WHITE; 141 | G->V[i]->p = NULL; 142 | } 143 | //时间戳初始化 144 | time = 0; 145 | //依次检索V中的顶点,发现白色顶点时,调用DFS_Visit访问该顶点 146 | for(i = 1; i <= N; i++) 147 | { 148 | if(G->V[i]->color == WHITE) 149 | DFS_Visit(G, G->V[i]); 150 | } 151 | } 152 | //输出 153 | void Print(Graph *G) 154 | { 155 | int i; 156 | //遍历每个顶点 157 | for(i = 1; i <= N; i++) 158 | { 159 | cout<V[i]->head; 162 | while(e) 163 | { 164 | cout<end<<' '; 165 | e = e->next; 166 | } 167 | cout<>start>>end; 205 | E = new Edge(start-'l', end-'l'); 206 | InsertEdge(G, E); 207 | //无向图,要加两条边 208 | // E = new Edge(end, start); 209 | // InsertEdge(G, E); 210 | } 211 | Print(G); 212 | //深度优先搜索,并输出排序结果 213 | DFS(G); 214 | return 0; 215 | } 216 | 217 | -------------------------------------------------------------------------------- /src/chapter22/section22_5.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: section22_5.cpp 3 | > Created Time: Mon 23 Nov 2015 07:55:49 PM CST 4 | ************************************************************************/ 5 | 6 | #include 7 | using namespace std; 8 | 9 | #define N 10 10 | #define WHITE 0 11 | #define GRAY 1 12 | #define BLACK 2 13 | 14 | 15 | //边结点结构 16 | struct Edge 17 | { 18 | int start;//有向图的起点 19 | int end;//有向图的终点 20 | Edge *next;//指向同一个起点的下一条边 21 | int type;//边的类型 22 | Edge(int s, int e):start(s),end(e),next(NULL){} 23 | }; 24 | //顶点结点结构 25 | struct Vertex 26 | { 27 | int id; 28 | Edge *head;//指向以该顶点为起点的下一条边 29 | int color;//顶点的颜色 30 | Vertex *p;//指向遍历结果的父结点 31 | int d, f;//第一次被发现的时间和结束检查的时间 32 | Vertex(int i):head(NULL),color(WHITE),p(NULL),d(0x7fffffff),id(i){} 33 | }; 34 | //图结构 35 | struct Graph 36 | { 37 | Vertex *V[N+1];//N个顶点 38 | Graph() 39 | { 40 | int i; 41 | for(i = 1; i <= N; i++) 42 | V[i] = new Vertex(i); 43 | } 44 | ~Graph() 45 | { 46 | int i; 47 | for(i = 1; i <= N; i++) 48 | delete V[i]; 49 | } 50 | }; 51 | 52 | int time = 0; 53 | bool flag = 0; 54 | int Sort[N+1] = {N}; 55 | 56 | //插入边 57 | void InsertEdge(Graph *G, Edge *E) 58 | { 59 | //如果没有相同起点的边 60 | if(G->V[E->start]->head == NULL) 61 | G->V[E->start]->head =E; 62 | //如果有,加入到链表中,递增顺序排列,便于查重 63 | else 64 | { 65 | //链表的插入,不解释 66 | Edge *e1 = G->V[E->start]->head, *e2 = e1; 67 | while(e1 && e1->end < E->end) 68 | { 69 | e2 = e1; 70 | e1 = e1->next; 71 | } 72 | if(e1 && e1->end == E->end) 73 | return; 74 | if(e1 == e2) 75 | { 76 | E->next = e1; 77 | G->V[E->start]->head =E; 78 | } 79 | else 80 | { 81 | e2->next = E; 82 | E->next = e1; 83 | } 84 | } 85 | } 86 | //转置 87 | Graph* Reverse(Graph *G) 88 | { 89 | Graph *ret = new Graph; 90 | int i; 91 | //遍历图G中的每一条边,以终点为起点,以起点为终点,加入到新图RET中 92 | for(i = 1; i <= N; i++) 93 | { 94 | Edge *E = G->V[i]->head; 95 | while(E) 96 | { 97 | Edge *e = new Edge(E->end, E->start); 98 | InsertEdge(ret, e); 99 | E = E->next; 100 | } 101 | } 102 | return ret; 103 | } 104 | //访问某顶点 105 | void DFS_Visit(Graph *G, Vertex *u) 106 | { 107 | //在第一次访问时输出 108 | if(flag)cout<id)<<' '; 109 | //将u置为黑色 110 | u->color = GRAY; 111 | //使全局变量time增值 112 | time++; 113 | //将time的新值记录为发现时间 114 | u->d = time; 115 | //检查和u相邻的每个顶点v 116 | Vertex *v; 117 | Edge *e = u->head; 118 | while(e) 119 | { 120 | v = G->V[e->end]; 121 | //如果顶点为白色 122 | if(v->color == WHITE) 123 | { 124 | //递归访问顶点 125 | v->p = u; 126 | DFS_Visit(G, v); 127 | //树边 128 | e->type = 1; 129 | } 130 | else if(v->color == GRAY) 131 | { 132 | //反向边 133 | e->type = 2; 134 | } 135 | else if(v->color == BLACK) 136 | { 137 | //正向边 138 | if(u->d < v->d) 139 | e->type = 3; 140 | //交叉边 141 | else 142 | e->type = 4; 143 | } 144 | e = e->next; 145 | } 146 | //以u为起点的所有边都被探寻后,置u为黑色 147 | u->color = BLACK; 148 | //并将完成时间记录在f[u]中 149 | time++; 150 | u->f = time; 151 | //把结果按照f从大到小的顺序保存于Sort数组中 152 | if(flag == 0) 153 | { 154 | Sort[Sort[0]] = u->id; 155 | Sort[0]--; 156 | } 157 | } 158 | //深度优先搜索 159 | void DFS(Graph *G) 160 | { 161 | int i; 162 | //对每个顶点初始化 163 | for(i = 1; i <= N; i++) 164 | { 165 | G->V[i]->id = i; 166 | G->V[i]->color = WHITE; 167 | G->V[i]->p = NULL; 168 | } 169 | //时间戳初始化 170 | time = 0; 171 | //依次检索V中的顶点,发现白色顶点时,调用DFS_Visit访问该顶点 172 | for(i = 1; i <= N; i++) 173 | { 174 | 175 | int j; 176 | //第一次是以正常顺序 177 | if(flag == 0) 178 | j = i; 179 | //第二次是以f从大到小的顺序,这个顺序在第一次dfs次保存于Sort数组中 180 | else j = Sort[i]; 181 | //发现白色顶点时,调用DFS_Visit访问该顶点 182 | if(G->V[j]->color == WHITE) 183 | { 184 | DFS_Visit(G, G->V[j]); 185 | if(flag)cout<>start>>end; 229 | E = new Edge(start-'p', end-'p'); 230 | InsertEdge(G, E); 231 | //无向图,要加两条边 232 | // E = new Edge(end, start); 233 | // InsertEdge(G, E); 234 | } 235 | //计算强联通分量 236 | Strongly_Connected_Component(G); 237 | return 0; 238 | } 239 | 240 | 241 | -------------------------------------------------------------------------------- /src/chapter26/MaxFlow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #include "MaxFlow.h" 4 | #define INT_MAX 0x7FFFFFFF 5 | 6 | void Mat_Flow::MakeGraph(int m) 7 | { 8 | int start, end, value; 9 | while(m--) 10 | { 11 | cin>>start>>end>>value; 12 | AddSingleEdge(start, end, value); 13 | } 14 | } 15 | bool Mat_Flow::bellman_ford() 16 | { 17 | int i, j; 18 | memset(path, -1, sizeof(path)); 19 | fill(ecost, ecost+NMAX, INT_MAX); 20 | ecost[0] = 0; 21 | 22 | bool flag = true; 23 | while(flag) 24 | { 25 | flag = false; 26 | for(i = 0; i <= n; i++) 27 | { 28 | if(ecost[i] == INT_MAX) 29 | continue; 30 | for(j = 0; j <= n; j++) 31 | { 32 | if(net[i][j] > 0 && ecost[i] + 1 < ecost[j]) 33 | { 34 | flag = true; 35 | ecost[j] = ecost[i] + 1; 36 | path[j] = i; 37 | } 38 | } 39 | } 40 | } 41 | return ecost[n] != INT_MAX; 42 | } 43 | 44 | int Mat_Flow::max_flow() 45 | { 46 | int i, j; 47 | //初始时,剩余网络即为整个网络 48 | for(i = 0; i <= n; i++) 49 | { 50 | for(j = 0; j <= n; j++) 51 | net[i][j] = map[i][j]; 52 | } 53 | int maxflow = 0; 54 | //while there exists a path p from s to t int the residual network G1 55 | //从剩余网络中找到一条增广路径,增广路径存在在path中 56 | while(bellman_ford()) 57 | { 58 | //do c|f(p) <- min {c|f(u,v):(u,v) is in p} 59 | //计算增广路径上的净流 60 | int v = n, cfp = INT_MAX, u; 61 | while(v != 0) 62 | { 63 | //path存储的是增广路径,path[v]=u说明(u,v)在增广路径上 64 | u = path[v]; 65 | cfp = min(cfp, net[u][v]); 66 | v = u; 67 | } 68 | //更新最大流的大小 69 | maxflow += cfp; 70 | //更新剩余网络 71 | //for each edge(u,v) in p 72 | v = n; 73 | while(v != 0) 74 | { 75 | u = path[v]; 76 | //f[u,v] <- f[u,v] + cfp 77 | net[u][v] -= cfp; 78 | net[v][u] += cfp; 79 | //f[v,u] <- -f[u,v] 80 | v = u; 81 | } 82 | } 83 | return maxflow; 84 | } 85 | -------------------------------------------------------------------------------- /src/chapter6/Exercise6_5_8.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windmissing/exerciseForAlgorithmSecond/c6ade0da2d7ca6be3415dece65e4f73ade5b4444/src/chapter6/Exercise6_5_8.cpp -------------------------------------------------------------------------------- /src/chapter6/Heap.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windmissing/exerciseForAlgorithmSecond/c6ade0da2d7ca6be3415dece65e4f73ade5b4444/src/chapter6/Heap.h -------------------------------------------------------------------------------- /src/chapter6/Young.cpp: -------------------------------------------------------------------------------- 1 | #include "Young.h" 2 | #include 3 | using namespace std; 4 | 5 | enum directionType 6 | { 7 | EAST = 0, 8 | SOUTH, 9 | WEST, 10 | NORTH 11 | }; 12 | 13 | structCoordinate directionStep[4] = {structCoordinate(0, 1), 14 | structCoordinate(1, 0), 15 | structCoordinate(0, -1), 16 | structCoordinate(-1, 0)}; 17 | 18 | structCoordinate getNeibourCoordinate(directionType direction, structCoordinate currentPosition) 19 | { 20 | currentPosition.h_index += directionStep[direction].h_index; 21 | currentPosition.w_index += directionStep[direction].w_index; 22 | return currentPosition; 23 | } 24 | 25 | Young::Young(int h, int w):height(h),width(w) 26 | { 27 | if(height < 1 || height > SIZE_OF_YOUNG) 28 | height = SIZE_OF_YOUNG; 29 | if(width < 1 || width > SIZE_OF_YOUNG) 30 | width = SIZE_OF_YOUNG; 31 | for(int i = 1; i <= height; i++) 32 | for(int j = 1; j <= width; j++) 33 | Y[i][j] = INIT_DATA; 34 | } 35 | 36 | void Young::fillData(int *data, int size) 37 | { 38 | int i, j, cnt = 0; 39 | for(i = 1; i <= height; i++) 40 | { 41 | if(cnt >= size) 42 | break; 43 | for(j = 1; j <= width; j++) 44 | { 45 | if(cnt >= size) 46 | break; 47 | Y[i][j] = data[cnt]; 48 | cnt++; 49 | } 50 | } 51 | build(); 52 | } 53 | 54 | int Young::extractMin() 55 | { 56 | structCoordinate minDataPosition(1, 1); 57 | int minData = getDataFromPosition(minDataPosition); 58 | setDataInPosition(minDataPosition, INIT_DATA); 59 | YoungifyWithSon(minDataPosition); 60 | return minData; 61 | } 62 | 63 | bool Young::findKey(int key) 64 | { 65 | structCoordinate currentPosition(height, 1); 66 | while(isInRange(currentPosition) == true) 67 | { 68 | if(getDataFromPosition(currentPosition) == key) 69 | return true; 70 | else if(getDataFromPosition(currentPosition) < key) 71 | currentPosition = getNeibourCoordinate(EAST, currentPosition); 72 | else if(getDataFromPosition(currentPosition) > key) 73 | currentPosition = getNeibourCoordinate(NORTH, currentPosition); 74 | } 75 | return false; 76 | } 77 | 78 | errorType Young::insert(int key) 79 | { 80 | structCoordinate currentPosition(height, width); 81 | if(getDataFromPosition(currentPosition) < INIT_DATA) 82 | return SIZE_OVERFLOW; 83 | 84 | setDataInPosition(currentPosition, key); 85 | YoungifyWithParent(currentPosition); 86 | return SUCCESS; 87 | } 88 | 89 | errorType Young::decreaseKey(structCoordinate position, int key) 90 | { 91 | if(false == isInRange(position)) 92 | return OUT_OF_SIZE; 93 | if(getDataFromPosition(position) < key) 94 | return PARAM_ERROR; 95 | 96 | setDataInPosition(position, key); 97 | YoungifyWithParent(position); 98 | return SUCCESS; 99 | } 100 | 101 | int Young::getMinimum() 102 | { 103 | return Y[1][1]; 104 | } 105 | 106 | vector Young::sort() 107 | { 108 | vector ret; 109 | while(getMinimum() != INIT_DATA) 110 | { 111 | ret.push_back(extractMin()); 112 | } 113 | return ret; 114 | } 115 | 116 | errorType Young::deleteData(structCoordinate position) 117 | { 118 | if(false == isInRange(position)) 119 | return OUT_OF_SIZE; 120 | if(getDataFromPosition(position) == INIT_DATA) 121 | return PARAM_ERROR; 122 | 123 | setDataInPosition(position, INIT_DATA); 124 | YoungifyWithSon(position); 125 | } 126 | 127 | bool Young::isInRange(structCoordinate position) 128 | { 129 | if(position.h_index < 1 || position.w_index < 1) 130 | return false; 131 | if(position.h_index > height || position.w_index > width) 132 | return false; 133 | return true; 134 | } 135 | 136 | void Young::build() 137 | { 138 | int h, w, step; 139 | 140 | int maxHeight = height, minHeight = 1; 141 | int maxWidth = width, minWidth = 1; 142 | int maxStep = maxHeight + maxWidth; 143 | int minStep = minHeight + minWidth; 144 | 145 | for(step = maxStep; step >= minStep; step--) 146 | { 147 | for(h = minHeight; h <= maxHeight; h++) 148 | { 149 | w = step - h; 150 | if(w > maxWidth)continue; 151 | if(w < minWidth)break; 152 | YoungifyWithSon(structCoordinate(h, w)); 153 | } 154 | } 155 | } 156 | 157 | void Young::YoungifyWithSon(structCoordinate position) 158 | { 159 | int Min = getDataFromPosition(position); 160 | int i = position.h_index, j = position.w_index; 161 | structCoordinate minDataPosition = position; 162 | 163 | structCoordinate southNeibour = getNeibourCoordinate(SOUTH, position); 164 | if(isInRange(southNeibour) && 165 | getDataFromPosition(southNeibour) < getDataFromPosition(minDataPosition)) 166 | { 167 | minDataPosition = southNeibour; 168 | } 169 | 170 | structCoordinate eastNeibour = getNeibourCoordinate(EAST, position); 171 | if(isInRange(eastNeibour) && 172 | getDataFromPosition(eastNeibour) < getDataFromPosition(minDataPosition)) 173 | { 174 | minDataPosition = eastNeibour; 175 | } 176 | 177 | if(getDataFromPosition(position) != getDataFromPosition(minDataPosition)) 178 | { 179 | swapDatainPosition(position, minDataPosition); 180 | YoungifyWithSon(minDataPosition); 181 | } 182 | } 183 | 184 | void Young::YoungifyWithParent(structCoordinate position) 185 | { 186 | structCoordinate maxDataPosition = position; 187 | while(true) 188 | { 189 | structCoordinate northNeibour = getNeibourCoordinate(NORTH, position); 190 | if(isInRange(northNeibour) && 191 | getDataFromPosition(maxDataPosition) < getDataFromPosition(northNeibour)) 192 | { 193 | maxDataPosition = northNeibour; 194 | } 195 | 196 | structCoordinate westNeibour = getNeibourCoordinate(WEST, position); 197 | if(isInRange(westNeibour) && 198 | getDataFromPosition(maxDataPosition) < getDataFromPosition(westNeibour)) 199 | { 200 | maxDataPosition = westNeibour; 201 | } 202 | 203 | if(getDataFromPosition(maxDataPosition) == getDataFromPosition(position)) 204 | break; 205 | swapDatainPosition(maxDataPosition, position); 206 | position = maxDataPosition; 207 | } 208 | } 209 | 210 | void Young::setDataInPosition(structCoordinate position, int data) 211 | { 212 | Y[position.h_index][position.w_index] = data; 213 | } 214 | 215 | int Young::getDataFromPosition(structCoordinate position) 216 | { 217 | return Y[position.h_index][position.w_index]; 218 | } 219 | 220 | void Young::swapDatainPosition(structCoordinate c1, structCoordinate c2) 221 | { 222 | int data1 = getDataFromPosition(c1); 223 | int data2 = getDataFromPosition(c2); 224 | setDataInPosition(c1, data2); 225 | setDataInPosition(c2, data1); 226 | } 227 | 228 | void Young::Print() 229 | { 230 | for(int i = 1; i <= height; i++) 231 | { 232 | for(int j = 1; j <= width; j++) 233 | cout< File Name: Exercise7_1_2.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Tue 20 Oct 2015 08:48:00 AM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | //划分 12 | static int Partition(int *A, int p, int r) 13 | { 14 | //选择A[r]作为主元 15 | int x = A[r]; 16 | int i = p - 1, j; 17 | bool flag = 0; 18 | for(j = p; j < r; j++) 19 | { 20 | //小于主元的放在左边 21 | if(A[j] < x || (A[j] == x && flag)) 22 | { 23 | i++; 24 | //把大于主元的交换到右边 25 | swap(A[i],A[j]); 26 | if(A[j] == x)flag = !flag; 27 | } 28 | } 29 | swap(A[i+1], A[r]); 30 | //返回最终主元的位置 31 | return i+1; 32 | } 33 | 34 | void QuickSort7_1_2(int *A, int p, int r) 35 | { 36 | if(p < r) 37 | { 38 | //以某个主元为标准,把数组分为两部分,左边都比主元小,右边都比主元大 39 | int q = Partition(A, p, r); 40 | //分别对左边和右边排序 41 | QuickSort7_1_2(A, p, q-1); 42 | QuickSort7_1_2(A, q+1, r); 43 | } 44 | } 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/chapter7/Exercise7_4_5.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: Exercise7_4_5.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Tue 20 Oct 2015 08:50:25 AM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | //7.4-5利用插入排序改善快排 12 | int k = 4; 13 | //划分 14 | int Partition(int *A, int p, int r) 15 | { 16 | //选择A[r]作为主元 17 | int x = A[r]; 18 | int i = p - 1, j; 19 | bool flag = 0; 20 | for(j = p; j < r; j++) 21 | { 22 | //小于主元的放在左边 23 | if(A[j] < x || (A[j] == x && flag)) 24 | { 25 | i++; 26 | //把大于主元的交换到右边 27 | swap(A[i],A[j]); 28 | if(A[j] == x)flag = !flag; 29 | } 30 | } 31 | swap(A[i+1], A[r]); 32 | //返回最终主元的位置 33 | return i+1; 34 | } 35 | //快速排序 36 | void QuickSort(int *A, int p, int r) 37 | { 38 | //长度小于k的子数组不排序 39 | if(r - p >= k) 40 | { 41 | //以某个主元为标准,把数组分为两部分,左边都比主元小,右边都比主元大 42 | int q = Partition(A, p, r); 43 | //分别对左边和右边排序 44 | QuickSort(A, p, q-1); 45 | QuickSort(A, q+1, r); 46 | } 47 | } 48 | //插入排序 49 | void InsertSort(int *A, int p, int r) 50 | { 51 | int i, j; 52 | for(i = p + 1; i <= r; i++) 53 | { 54 | int temp = A[i]; 55 | j = i; 56 | while(A[j-1] > temp) 57 | { 58 | A[j] = A[j-1]; 59 | j--; 60 | } 61 | A[j] = temp; 62 | } 63 | } 64 | void Sort(int *A, int p, int r) 65 | { 66 | //先进行粗粒度的快排 67 | QuickSort(A, p, r); 68 | //逐个进行插入排序 69 | InsertSort(A, p, r); 70 | } 71 | -------------------------------------------------------------------------------- /src/chapter7/Exercise7_5.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: Exercise7_5.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Tue 20 Oct 2015 08:52:48 AM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | //三数取中 12 | int GetMid(int *A, int p, int r) 13 | { 14 | int a = -1, b = -1, c = -1; 15 | while(a < p)a = rand() % (r+1); 16 | while(b < p)b = rand() % (r+1); 17 | while(c < p)c = rand() % (r+1); 18 | if((A[a]-A[b])*(A[a]-A[c])<=0)return a; 19 | if((A[b]-A[a])*(A[b]-A[c])<=0)return b; 20 | if((A[c]-A[a])*(A[c]-A[b])<=0)return c; 21 | } 22 | //划分 23 | int Partition(int *A, int p, int r) 24 | { 25 | //选择A[r]作为主元 26 | int m = GetMid(A, p , r); 27 | swap(A[m], A[r]); 28 | int x = A[r]; 29 | int i = p - 1, j; 30 | bool flag = 0; 31 | for(j = p; j < r; j++) 32 | { 33 | //小于主元的放在左边 34 | if(A[j] < x || (A[j] == x && flag)) 35 | { 36 | i++; 37 | //把大于主元的交换到右边 38 | swap(A[i],A[j]); 39 | if(A[j] == x)flag = !flag; 40 | } 41 | } 42 | swap(A[i+1], A[r]); 43 | //返回最终主元的位置 44 | return i+1; 45 | } 46 | //快速排序 47 | void QuickSort(int *A, int p, int r) 48 | { 49 | //长度小于k的子数组不排序 50 | if(r > p) 51 | { 52 | //以某个主元为标准,把数组分为两部分,左边都比主元小,右边都比主元大 53 | int q = Partition(A, p, r); 54 | //分别对左边和右边排序 55 | QuickSort(A, p, q-1); 56 | QuickSort(A, q+1, r); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/chapter7/Exercise7_6.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "Exercise7_6.h" 5 | 6 | static void quickSort(ARRAY & array, int left, int right); 7 | static divid partition(ARRAY &array, int left, int right); 8 | void moveToLeft(ARRAY &array, int& index, divid &pivotIndex); 9 | void moveToRight(ARRAY &array, int& index, divid &pivotIndex); 10 | section getPublicSection(const section &a, const section & b); 11 | static void exchange(section &a, section &b); 12 | 13 | void Exercise7_6(ARRAY & array) 14 | { 15 | if(array.size() == 0) 16 | return; 17 | quickSort(array, 0, array.size()-1); 18 | } 19 | 20 | static void quickSort(ARRAY & array, int left, int right) 21 | { 22 | if(left == right) 23 | return; 24 | divid pivotIndex = partition(array, left, right); 25 | if(pivotIndex.a > 0) 26 | quickSort(array, left, pivotIndex.a); 27 | if(pivotIndex.b > 0) 28 | quickSort(array, pivotIndex.b, right); 29 | } 30 | 31 | static divid partition(ARRAY &array, int left, int right) 32 | { 33 | section pivot = array[right]; 34 | divid ret = {left - 1, right + 1}; 35 | int index = left; 36 | while(index < ret.b) 37 | { 38 | if(array[index] < pivot) 39 | moveToLeft(array, index, ret); 40 | else if(array[index] > pivot) 41 | moveToRight(array, index, ret); 42 | else 43 | { 44 | pivot = getPublicSection(pivot, array[index]); 45 | index++; 46 | } 47 | } 48 | if(ret.a < left)ret.a = -1; 49 | if(ret.b > right)ret.b = -1; 50 | return ret; 51 | } 52 | 53 | void moveToLeft(ARRAY &array, int &index, divid &pivotIndex) 54 | { 55 | pivotIndex.a++; 56 | exchange(array[pivotIndex.a], array[index]); 57 | index++; 58 | } 59 | 60 | void moveToRight(ARRAY &array, int &index, divid &pivotIndex) 61 | { 62 | pivotIndex.b--; 63 | exchange(array[pivotIndex.b], array[index]); 64 | } 65 | 66 | section getPublicSection(const section &a, const section & b) 67 | { 68 | section ret; 69 | ret.end = min(a.end, b.end); 70 | ret.start = max(a.start, b.start); 71 | return ret; 72 | } 73 | 74 | static void exchange(section &a, section &b) 75 | { 76 | section temp; 77 | temp = a; 78 | a = b; 79 | b = temp; 80 | } 81 | 82 | -------------------------------------------------------------------------------- /src/chapter7/quickSort.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: quickSort.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Tue 20 Oct 2015 08:46:14 AM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | #include 12 | 13 | //输出过程 14 | void Print(int *A, int len) 15 | { 16 | for(int i = 0; i < len; i++) 17 | { 18 | if(i)cout<<' '; 19 | else cout<<"==> A = {"; 20 | cout< File Name: Exercise8_3_4.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Wed 21 Oct 2015 08:51:51 AM CST 6 | ************************************************************************/ 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | int n, radix, length_A, digit = 2; 12 | void Print(int *A, int start, int end) 13 | { 14 | int i; 15 | for(i = start; i <= end; i++) 16 | { 17 | if(i == start)cout<<'{'; 18 | else cout<<' '; 19 | cout<= 1; j--) 46 | { 47 | //如果<=D[j]的数字的个数是x,那么排序后A[j]应该出现在第x个位置,即B[x]=A[j] 48 | B[C[D[j]]] = A[j]; 49 | C[D[j]]--; 50 | } 51 | delete []C; 52 | delete []D; 53 | } 54 | //基数排序 55 | void Radix_Sort(int *A, int *B) 56 | { 57 | int i, j; 58 | //依次对每一位进行排序,从低位到高位 59 | for(i = 1; i <= digit; i++) 60 | { 61 | Stable_Sort(A, B, radix-1, i); 62 | //输入的是A,输出的是B,再次排序时要把输出数据放入输出数据中 63 | for(j = 1; j <= length_A; j++) 64 | A[j] = B[j]; 65 | } 66 | } 67 | 68 | int main() 69 | { 70 | cin>>n; 71 | length_A = n; 72 | int *A = new int[n+1]; 73 | int *B = new int[n+1]; 74 | bool flag[1000] = {0}; 75 | int i; 76 | //生产n个随机的数据范围在0到n^-1之间 77 | for(i = 1; i <= n; i++) 78 | { 79 | do 80 | { 81 | A[i] = rand() % (n*n); 82 | }while(flag[A[i]]); 83 | flag[A[i]] = 1; 84 | } 85 | Print(A, 1, n); 86 | radix = n; 87 | Radix_Sort(A, B); 88 | Print(A, 1, n); 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /src/chapter8/chapter8.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: Chapter8.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Wed 21 Oct 2015 08:48:49 AM CST 6 | ************************************************************************/ 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | #include "chapter8.h" 12 | 13 | /* 14 | int length_A, digit; 15 | 16 | void Print(int *A, int start, int end) 17 | { 18 | int i; 19 | for(i = start; i <= end; i++) 20 | { 21 | if(i == start)cout<<'{'; 22 | else cout<<' '; 23 | cout<= 1; j--) 46 | { 47 | //如果<=A[j]的数字的个数是x,那么排序后A[j]应该出现在第x个位置,即B[x]=A[j] 48 | B[C[A[j]]] = A[j]; 49 | C[A[j]]--; 50 | } 51 | delete C; 52 | } 53 | 54 | //基数排序调用的稳定排序 55 | void Stable_Sort_For_Radix(int *A, int *B, int length_A, int k, int d) 56 | { 57 | int i, j; 58 | //将C数组初始化为0,用于计数 59 | int *C = new int[k+1]; 60 | for(i = 0; i <= k; i++) 61 | C[i] = 0; 62 | int *D = new int[length_A+1]; 63 | for(j = 1; j <= length_A; j++) 64 | { 65 | //D[j]表示第[j]个元素的第i位数字 66 | D[j] = A[j] % (int)pow(10.0, d) / (int)pow(10.0, d-1); 67 | //C[j]表示数字D[j]在数组A中出现的次数 68 | C[D[j]]++; 69 | } 70 | //C[i]表示所以<=i的数字出现过的次数 71 | for(i = 1; i <= k; i++) 72 | C[i] = C[i] + C[i-1]; 73 | //初始化B为0,B用于输出排序结果 74 | for(i = 1; i <= length_A; i++) 75 | B[i] = 0; 76 | for(j = length_A; j >= 1; j--) 77 | { 78 | //如果<=D[j]的数字的个数是x,那么排序后A[j]应该出现在第x个位置,即B[x]=A[j] 79 | B[C[D[j]]] = A[j]; 80 | C[D[j]]--; 81 | } 82 | delete []C; 83 | delete []D; 84 | } 85 | //基数排序 86 | void Radix_Sort(int *A, int *B, int length_A, int digit) 87 | { 88 | int i, j; 89 | //依次对每一位进行排序,从低位到高位 90 | for(i = 1; i <= digit; i++) 91 | { 92 | Stable_Sort_For_Radix(A, B, length_A, 9, i); 93 | //输入的是A,输出的是B,再次排序时要把输出数据放入输出数据中 94 | for(j = 1; j <= length_A; j++) 95 | A[j] = B[j]; 96 | } 97 | } 98 | 99 | -------------------------------------------------------------------------------- /src/chapter8/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Chapter8.h" 5 | #include "sort.h" 6 | 7 | #define DATA_COUNT 10 8 | 9 | static void makeRadomData(); 10 | void Print(int *A, int start, int end); 11 | 12 | static int A[DATA_COUNT+1] = {0}; 13 | bool flag[1000] = {0}; 14 | 15 | void makeRadomData() 16 | { 17 | int i; 18 | bool flag[1000] = {0}; 19 | for(i = 0; i < DATA_COUNT; i++) 20 | { 21 | do 22 | { 23 | A[i] = rand() % (DATA_COUNT*DATA_COUNT); 24 | }while(flag[A[i]]); 25 | flag[A[i]] = 1; 26 | } 27 | } 28 | 29 | void Print(int *A, int start, int end) 30 | { 31 | int i; 32 | for(i = start; i <= end; i++) 33 | { 34 | if(i == start)cout<<'{'; 35 | else cout<<' '; 36 | cout< 2 | using namespace std; 3 | 4 | #include "Exercise9_1_1.h" 5 | 6 | int *nextTarget; 7 | int *nextSecond; 8 | int headTarget = 0; 9 | 10 | void prepare(int size) 11 | { 12 | headTarget = 0; 13 | nextTarget = new int[size]; 14 | for(int i = 0; i < size; i++) 15 | nextTarget[i] = i + 1; 16 | nextTarget[size-1] = -1; 17 | nextSecond = new int[size]; 18 | for(int i = 0; i < size; i++) 19 | nextSecond[i] = -1; 20 | } 21 | 22 | void release() 23 | { 24 | delete []nextTarget; 25 | delete []nextSecond; 26 | } 27 | 28 | int findSmallest(vector array); 29 | int findSecondSmaller(vector array, int smallestIndex); 30 | 31 | int solve9_1_1(vector array) 32 | { 33 | if(array.size() < 2) 34 | return 0; 35 | prepare(array.size()); 36 | //运行算法并输出结果 37 | int smallestIndex = findSmallest(array); 38 | int secondSmaller = findSecondSmaller(array, smallestIndex); 39 | release(); 40 | return secondSmaller; 41 | } 42 | 43 | void pushQueue(int bigIndex, int smallIndex) 44 | { 45 | nextSecond[bigIndex] = nextSecond[smallIndex]; 46 | nextSecond[smallIndex] = bigIndex; 47 | } 48 | int compare(vector array, int a, int b) 49 | { 50 | int smallIndex = array[a] < array[b] ? a : b; 51 | int bigIndex = array[a] > array[b] ? a : b; 52 | 53 | pushQueue(bigIndex, smallIndex); 54 | 55 | return smallIndex; 56 | } 57 | 58 | bool twoMoreElementsLeft(int head) 59 | { 60 | return nextTarget[head] != -1; 61 | } 62 | 63 | bool getTopTwoElements(int a, int &b) 64 | { 65 | b = nextTarget[a]; 66 | if(a == -1 || b == -1) 67 | return false; 68 | } 69 | 70 | void removeSmallerOne(int &head, int a, int pre, int b, int ret) 71 | { 72 | if(a == head) 73 | head = ret; 74 | else 75 | nextTarget[pre] = ret; 76 | nextTarget[ret] = nextTarget[b]; 77 | } 78 | 79 | int findSmallest(vector array) 80 | { 81 | int head = headTarget; 82 | while(twoMoreElementsLeft(head)) 83 | { 84 | int a = head, pre, b, ret; 85 | while(getTopTwoElements(a, b)) 86 | { 87 | ret = compare(array, a, b); 88 | removeSmallerOne(head, a, pre, b, ret); 89 | a = nextTarget[b]; 90 | pre = ret; 91 | } 92 | } 93 | return head; 94 | } 95 | 96 | int findSecondSmaller(vector array, int smallestIndex) 97 | { 98 | int head = smallestIndex; 99 | head = nextSecond[head]; 100 | int min = array[head]; 101 | while(nextSecond[head] != -1) 102 | { 103 | head = nextSecond[head]; 104 | if(array[head] < min) 105 | min = array[head]; 106 | } 107 | return min; 108 | } 109 | -------------------------------------------------------------------------------- /src/chapter9/Exercise9_3_6.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | #include "Chapter9.h" 6 | #include "array.h" 7 | 8 | CArrayFor_9_3_6::CArrayFor_9_3_6(int size):CArray(size) 9 | { 10 | 11 | } 12 | 13 | CArrayFor_9_3_6::CArrayFor_9_3_6(const int *initData, const int len) 14 | :CArray(initData, len) 15 | { 16 | } 17 | 18 | CArrayFor_9_3_6::CArrayFor_9_3_6(const CArrayFor_9_3_6 & origin) 19 | :CArray(origin.data, origin.remainDataCount()) 20 | { 21 | // start = origin.start; 22 | // end = origin.end; 23 | // memncpy(data, origin.data, sizeof(origin.data)); 24 | } 25 | 26 | CArrayFor_9_3_6 CArrayFor_9_3_6::getPart(int start, int end)const 27 | { 28 | return CArrayFor_9_3_6(data+start, end - start + 1); 29 | } 30 | 31 | #if 0 32 | int t, length_A; 33 | void Print(int *A, int len) 34 | { 35 | int i; 36 | for(i = 1; i <= len; i++) 37 | cout<= start; j--) 66 | { 67 | if(j == start) 68 | A[j] = t; 69 | else if(A[j-1] > t) 70 | A[j] = A[j-1]; 71 | else 72 | { 73 | A[j] = t; 74 | break; 75 | } 76 | } 77 | } 78 | return A[start+k-1]; 79 | } 80 | //???????,??????? 81 | int Find(int *A, int p, int r) 82 | { 83 | int i, j = 0; 84 | int start, end, len = r - p + 1; 85 | int *B = new int[len/5+1]; 86 | //?5?????,???start?end,??????????,????? 87 | for(i = 1; i <= len; i++) 88 | { 89 | if(i % 5 == 1) 90 | start = i+p-1; 91 | if(i % 5 == 0 || i == len) 92 | { 93 | j++; 94 | end = i+p-1; 95 | //?????start?end??????,?????,???????,??????????5 96 | int ret = Insert(A, start, end, (end-start)/2+1); 97 | //?????????????????? 98 | B[j] = ret; 99 | } 100 | } 101 | //??????????Select()??????? 102 | int ret = Select(B, 1, j, (j+1)/2); 103 | //delete []B; 104 | return ret; 105 | } 106 | #endif 107 | /* 108 | int Find(const ARRAY &array) 109 | { 110 | int i, j = 0; 111 | int start, end, len = array.size(); 112 | ARRAY B(array.size()/5+1); 113 | //?5?????,???start?end,??????????,????? 114 | for(i = 1; i <= len; i++) 115 | { 116 | if(i % 5 == 1) 117 | start = i-1; 118 | if(i % 5 == 0 || i == array.size()) 119 | { 120 | j++; 121 | end = i-1; 122 | //?????start?end??????,?????,???????,??????????5 123 | int ret = Insert(A, (end-start)/2+1); 124 | //?????????????????? 125 | B[j] = ret; 126 | } 127 | } 128 | //??????????Select()??????? 129 | int ret = Select(B, (j+1)/2); 130 | return ret; 131 | } 132 | */ 133 | #if 0 134 | //?f?????? 135 | int Partition2(int *A, int p, int r, int f) 136 | { 137 | int i; 138 | //??f???????A[r]?? 139 | for(i = p; i < r; i++) 140 | { 141 | if(A[i] == f) 142 | { 143 | swap(A[i], A[r]); 144 | break; 145 | } 146 | } 147 | return Partition(A, p, r); 148 | } 149 | //????A[p..r]???i????,i??1????,???p?? 150 | int Select(int *A, int p, int r, int i) 151 | { 152 | //???????????,????? 153 | if(p == r) 154 | return A[p]; 155 | //???????,??????? 156 | int f = Find(A, p, r); 157 | //???????????,?????????A[1..len]??? 158 | //?????????????,???????,A[p..q-1] <= f < A[q+1..r] 159 | int q = Partition2(A, p, r, f); 160 | //?????????A[p..r]???? 161 | int k = q - p + 1; 162 | //?????????? 163 | if(i == k) 164 | return A[q]; 165 | else if(i < k) 166 | return Select(A, p, q-1, i); 167 | else 168 | //?????????????,???????? 169 | return Select(A, q+1, r, i-k); 170 | //?????????????????,???????Select(A, q, r, i-k+1) 171 | } 172 | #endif 173 | 174 | int select(CArrayFor_9_3_6 & array, int i) 175 | { 176 | if( i > array.remainDataCount()) 177 | return 0x7fffffff; 178 | if(array.remainDataCount() == 1) 179 | return array.data[1]; 180 | return array.data[i]; 181 | /* 182 | //???????????,????? 183 | if(array.size() == 1) 184 | return array[0]; 185 | //???????,??????? 186 | int f = Find(A); 187 | //???????????,?????????A[1..len]??? 188 | //?????????????,???????,A[p..q-1] <= f < A[q+1..r] 189 | int q = Partition2(A, f); 190 | //?????????A[p..r]???? 191 | int k = q + 1; 192 | //?????????? 193 | if(i == k) 194 | return A[q]; 195 | else if(i < k) 196 | return Select(A, p, q-1, i); 197 | else 198 | //?????????????,???????? 199 | return Select(A, q+1, r, i-k); 200 | //?????????????????,???????Select(A, q, r, i-k+1)*/ 201 | } 202 | 203 | ARRAY K_Quantile(CArrayFor_9_3_6 & array, int k) 204 | { 205 | ARRAY ret; 206 | if(k == 1) 207 | return ret; 208 | int countPerK = array.remainDataCount() / k; 209 | int midK = (k + 1) / 2; 210 | int midKth = (midK) * countPerK; 211 | //cout<<"midKth = "< b ? a : b; 133 | } 134 | -------------------------------------------------------------------------------- /src/others/BigNumber.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "BigNumber.h" 3 | 4 | using namespace std; 5 | 6 | #define UP_LIMIT 1000000000000000000 7 | #define MAX_DIGIT_COUNT MAX_CELL_COUNT*DIGIT_PER_CELL 8 | 9 | CBigNumber::CBigNumber() 10 | { 11 | usedCells = 0; 12 | memset(cell, 0, sizeof(cell)); 13 | } 14 | 15 | CBigNumber::CBigNumber(const CBigNumber &B) 16 | { 17 | usedCells = B.usedCells; 18 | memset(cell, 0, sizeof(cell)); 19 | for(int i = 0; i < B.usedCells; i++) 20 | cell[i] = B.cell[i]; 21 | } 22 | 23 | CBigNumber::CBigNumber(long long normalData) 24 | { 25 | memset(cell, 0, sizeof(cell)); 26 | cell[0] = normalData; 27 | usedCells = 1; 28 | } 29 | 30 | CBigNumber::CBigNumber(string number) 31 | { 32 | int digit[MAX_DIGIT_COUNT] = {0}; 33 | int len = number.length(); 34 | for(int i = 0; i < len; i++) 35 | { 36 | digit[len -i - 1] = number[i] - '0'; 37 | } 38 | *this = digit2Number(digit, number.length()); 39 | } 40 | 41 | CBigNumber CBigNumber::operator+(const CBigNumber & number) 42 | { 43 | CBigNumber ret; 44 | for(int i = 0; i < usedCells; i++) 45 | { 46 | ret.cell[i] += cell[i] + number.cell[i]; 47 | if(ret.cell[i] > UP_LIMIT) 48 | { 49 | ret.cell[i] = ret.cell[i] - UP_LIMIT; 50 | ret.cell[i+1]++; 51 | } 52 | } 53 | ret.usedCells = usedCells; 54 | if(ret.cell[ret.usedCells] > 0) 55 | ret.usedCells++; 56 | return ret; 57 | } 58 | 59 | bool CBigNumber::operator<(const CBigNumber & number) const 60 | { 61 | if(usedCells != number.usedCells) 62 | return usedCells < number.usedCells; 63 | 64 | for(int i = usedCells - 1; i >= 0; i--) 65 | { 66 | if(cell[i] != number.cell[i]) 67 | return cell[i] < number.cell[i]; 68 | } 69 | return false; 70 | } 71 | 72 | long long CBigNumber::toLongLong() const 73 | { 74 | return cell[0]; 75 | } 76 | 77 | void CBigNumber::print() 78 | { 79 | for(int i = 0; i < usedCells; i++) 80 | cout<= MAX_CELL_COUNT) 102 | return true; 103 | return false; 104 | } 105 | bool CBigNumber::isPalindrome() 106 | { 107 | CBigNumber reverse = getReverseNumber(); 108 | if(reverse == *this) 109 | return true; 110 | else 111 | return false; 112 | } 113 | 114 | CBigNumber CBigNumber::getReverseNumber() 115 | { 116 | CBigNumber ret; 117 | 118 | int digit[MAX_DIGIT_COUNT] = {0}; 119 | int len = numberInCells2Digits(digit); 120 | reverseDigit(digit, len); 121 | ret = digit2Number(digit, len); 122 | 123 | return ret; 124 | } 125 | 126 | int CBigNumber::numberInCells2Digits(int *digit) 127 | { 128 | int start = 0; 129 | for(int i = 0; i < usedCells; i++) 130 | { 131 | start = i * DIGIT_PER_CELL; 132 | long long temp = cell[i]; 133 | while(temp) 134 | { 135 | digit[start++] = temp % 10; 136 | temp = temp / 10; 137 | } 138 | } 139 | return start; 140 | } 141 | 142 | void CBigNumber::reverseDigit(int *digit, int len) 143 | { 144 | int midIndex = (len - 1) / 2; 145 | for(int i = 0; i <= midIndex; i++) 146 | swap(digit[i], digit[len - 1 - i]); 147 | } 148 | 149 | CBigNumber CBigNumber::digit2Number(int *digit, int len) 150 | { 151 | CBigNumber ret; 152 | memset(ret.cell, 0, sizeof(ret.cell)); 153 | for(int i = 0; i < len; i+=DIGIT_PER_CELL) 154 | { 155 | for(int j = i + DIGIT_PER_CELL-1; j >= i; j--) 156 | { 157 | if(j >= len)continue; 158 | ret.cell[ret.usedCells] = ret.cell[ret.usedCells] * 10 + digit[j]; 159 | } 160 | ret.usedCells++; 161 | } 162 | return ret; 163 | } 164 | 165 | -------------------------------------------------------------------------------- /src/others/array.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | #include 6 | #include 7 | #include "array.h" 8 | 9 | CArray::CArray(int size) 10 | { 11 | start = 1; 12 | end = size; 13 | memset(data, 0, sizeof(data)); 14 | } 15 | 16 | CArray::CArray(const int *initData, const int len) 17 | { 18 | start = 1; 19 | end = len; 20 | for(int i = start; i <= end; i++) 21 | data[i] = initData[i-1]; 22 | } 23 | 24 | void CArray::insertArray(CArray B) 25 | { 26 | for(int i = 1; i <= B.end; i++) 27 | data[end+i] = B.data[i]; 28 | end += B.end; 29 | } 30 | 31 | void CArray::sortData() 32 | { 33 | sort(data+start, data+end); 34 | } 35 | 36 | void CArray::makeRadomData() 37 | { 38 | for(int i = start; i <= end; i++) 39 | { 40 | data[i] = rand() % 100; 41 | } 42 | sort(data+start, data+end+1); 43 | } 44 | 45 | void CArray::Print() 46 | { 47 | for(int i = start; i <= end; i++) 48 | cout<left); 11 | //?????? 12 | cout<key<right); 15 | } 16 | } 17 | /********12.2 ???????****************************************************************/ 18 | BST_Node *CBinarySearchTree::search(int k) 19 | { 20 | return search(root, k); 21 | } 22 | //?????????? 23 | BST_Node *CBinarySearchTree::search(BST_Node *x, int k) 24 | { 25 | //???????????,???????????? 26 | if(x == NULL || k == x->key) 27 | return x; 28 | //???????????????? 29 | if(k < x->key) 30 | return search(x->left, k); 31 | //???????????????? 32 | else 33 | return search(x->right, k); 34 | } 35 | BST_Node *CBinarySearchTree::iterativeSearch(int k) 36 | { 37 | return iterativeSearch(k); 38 | } 39 | //??????????? 40 | BST_Node *CBinarySearchTree::iterativeSearch(BST_Node *x, int k) 41 | { 42 | //??????????????? 43 | while(x != NULL && k != x->key) 44 | { 45 | //???????????????? 46 | if(k < x->key) 47 | x = x->left; 48 | //???????????????? 49 | else 50 | x = x->right; 51 | } 52 | return x; 53 | } 54 | //??????? 55 | BST_Node *CBinarySearchTree::iterativeMinimum(BST_Node *x) 56 | { 57 | //???????????? 58 | while(x->left != NULL) 59 | x = x->left; 60 | return x; 61 | } 62 | //??????? 63 | BST_Node *iterativeMaximum(BST_Node *x) 64 | { 65 | //???????????? 66 | while(x->right != NULL) 67 | x = x->right; 68 | return x; 69 | } 70 | //???????x?????,?????key[x]?????? 71 | BST_Node *CBinarySearchTree::successor(BST_Node *x) 72 | { 73 | //?????? 74 | if(x->right != NULL) 75 | //???????? 76 | return iterativeMinimum(x->right); 77 | //??x???????x???y,??y?x???????,?y?????? 78 | BST_Node *y = x->p; 79 | while(y != NULL && x == y->right) 80 | { 81 | x = y; 82 | y = y->p; 83 | } 84 | return y; 85 | } 86 | /*********12.3?????**********************************************************/ 87 | //????????,??? 88 | void CBinarySearchTree::iterativeInsert(BST_Node *z) 89 | { 90 | //???????? 91 | BST_Node *x = root, *y = NULL; 92 | //?x??,x???????,x???z->p 93 | while(x != NULL) 94 | { 95 | y = x; 96 | if(z->key == x->key) 97 | { 98 | cout<<"error:exist"<key < x->key) 102 | x = x->left; 103 | else 104 | x = x->right; 105 | } 106 | //????,???????? 107 | z->p = y; 108 | if(y == NULL) 109 | root = z; 110 | else if(z->key < y->key) 111 | y->left = z; 112 | else y->right = z; 113 | } 114 | //????????,?????????z,???z??? 115 | //???z???????????? 116 | BST_Node *CBinarySearchTree::remove(BST_Node *z) 117 | { 118 | BST_Node *x, *y; 119 | //?z????????,????????z 120 | if(z->left == NULL || z->right == NULL) 121 | y = z; 122 | //?z?????,????????z??? 123 | else 124 | y = successor(z); 125 | //?x??"????????"???(??????) 126 | if(y->left != NULL) 127 | x = y->left; 128 | else 129 | x = y->right; 130 | //????,????? 131 | if(x != NULL)//?"????????"???? 132 | x->p = y->p; 133 | if(y->p == NULL)//?"????????"???? 134 | root = x; 135 | else if(y == y->p->left) 136 | y->p->left = x; 137 | else y->p->right = x; 138 | //"?????????"??"??????",????? 139 | if(y != z) 140 | { 141 | z->key = y->key; 142 | z->data = y->data; 143 | } 144 | return y; 145 | } 146 | -------------------------------------------------------------------------------- /src/others/intervalTree.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windmissing/exerciseForAlgorithmSecond/c6ade0da2d7ca6be3415dece65e4f73ade5b4444/src/others/intervalTree.cpp -------------------------------------------------------------------------------- /src/others/queue.cpp: -------------------------------------------------------------------------------- 1 | //10.1???? 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | #include "queue.h" 8 | 9 | CQueue::CQueue(int size) 10 | :tail(1),head(1),length(size) 11 | { 12 | s = new int[size+1]; 13 | } 14 | 15 | CQueue::~CQueue() 16 | { 17 | delete s; 18 | } 19 | 20 | bool CQueue::isEmpty() 21 | { 22 | if(tail == head) 23 | return true; 24 | return false; 25 | } 26 | 27 | void CQueue::enqueue(int x) 28 | { 29 | s[tail] = x; 30 | if(tail == length) 31 | tail = 1; 32 | else tail++; 33 | } 34 | 35 | int CQueue::dequeue() 36 | { 37 | int x = s[head]; 38 | if(head == length) 39 | head = 1; 40 | else head++; 41 | return x; 42 | } 43 | 44 | //?????????? 45 | void Print(CQueue Q) 46 | { 47 | int i; 48 | if(Q.tail >= Q.head) 49 | { 50 | for(i = Q.head; i < Q.tail;i++) 51 | cout< 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | #include "stack.h" 8 | 9 | CStack::CStack(int size) 10 | :top(0) 11 | { 12 | s = new int[size+1]; 13 | } 14 | 15 | CStack::~CStack() 16 | { 17 | delete []s; 18 | } 19 | 20 | bool CStack::isEmpty() 21 | { 22 | return (top == 0); 23 | } 24 | 25 | void CStack::push(int x) 26 | { 27 | top++; 28 | s[top] = x; 29 | } 30 | 31 | int CStack::pop() 32 | { 33 | if(isEmpty()) 34 | { 35 | cout<<"underflow"< File Name: Main_TestAll.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Thu 15 Oct 2015 05:05:22 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | #include 12 | #include "gtest/gtest.h" 13 | 14 | int main(int argc, char **argv) { 15 | ::testing::InitGoogleTest(&argc, argv); 16 | return RUN_ALL_TESTS(); 17 | } 18 | -------------------------------------------------------------------------------- /tst/chapter10/Exercise10_1_2Test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: Exercise10_1_2.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Sat 24 Oct 2015 03:57:06 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | #include "gtest/gtest.h" 12 | #include "Exercise10_1_2.h" 13 | 14 | #define NUMOF(x) (sizeof(x)/sizeof(*(x))) 15 | 16 | TEST(no_operation, both_should_be_empty) 17 | { 18 | arrayWithTwoStack S(5); 19 | EXPECT_TRUE(S.isEmpty(0)); 20 | EXPECT_TRUE(S.isEmpty(1)); 21 | } 22 | 23 | TEST(push_one_data_one_stack, one_stack_not_empty) 24 | { 25 | arrayWithTwoStack S(5); 26 | S.push(1, 1); 27 | EXPECT_TRUE(S.isEmpty(0)); 28 | EXPECT_FALSE(S.isEmpty(1)); 29 | } 30 | 31 | TEST(pop_when_not_empty, should_get_latest_data) 32 | { 33 | arrayWithTwoStack S(5); 34 | S.push(0, 1); 35 | S.push(1, 2); 36 | EXPECT_EQ(1, S.pop(0)); 37 | EXPECT_EQ(2, S.pop(1)); 38 | } 39 | -------------------------------------------------------------------------------- /tst/chapter10/Exercise10_2_8Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "gtest/gtest.h" 5 | #include "gmock/gmock.h" 6 | 7 | #include "Chapter10.h" 8 | // Tests factorial of negative numbers. 9 | // 10 | using ::testing::_; 11 | using ::testing::SetArgPointee; 12 | using ::testing::DoAll; 13 | using ::testing::Return; 14 | using ::testing::Pointee; 15 | 16 | #define INSERT 0 17 | #define DELETE 1 18 | 19 | struct operation_t 20 | { 21 | int oper; 22 | int param; 23 | }; 24 | 25 | #define OPERATION_VEC vector 26 | #define RESULT_VEC vector 27 | 28 | typedef int OUTPUTTYPE; 29 | 30 | templatevector prepare(Type * data, int len) 31 | { 32 | vector ret; 33 | for(int i = 0; i < len; i++) 34 | ret.push_back(data[i]); 35 | return ret; 36 | } 37 | 38 | RESULT_VEC testStep(const OPERATION_VEC & inputDataVec) 39 | { 40 | RESULT_VEC outputVec; 41 | listOfOnePointerDoubleLink list; 42 | for(int i = 0; i < inputDataVec.size(); i++) 43 | { 44 | switch(inputDataVec[i].oper) 45 | { 46 | case INSERT: 47 | list.Insert(inputDataVec[i].param); 48 | break; 49 | case DELETE: 50 | list.Delete(inputDataVec[i].param); 51 | break; 52 | } 53 | } 54 | outputVec = list.Print(); 55 | return outputVec; 56 | } 57 | 58 | static bool compareVector(const RESULT_VEC & expect, const RESULT_VEC & result) 59 | { 60 | if(expect.size() != result.size()) 61 | return false; 62 | for(int i = 0; i < expect.size(); i++) 63 | { 64 | if(expect[i] != result[i]) 65 | return false; 66 | } 67 | return true; 68 | } 69 | 70 | static void printArray(vector array) 71 | { 72 | for(int i = 0; i < array.size(); i++) 73 | cout<(operation, 1); 88 | 89 | OUTPUTTYPE expect[1] = {1}; 90 | RESULT_VEC expectVec = prepare(expect, 1); 91 | 92 | RESULT_VEC output = testStep(operationVec); 93 | EXPECT_TRUE(compareVector(expectVec, output)); 94 | } 95 | 96 | TEST(OnlyInsert, Insert5NumberShouldGet5Data) 97 | { 98 | operation_t operation[5] = {{INSERT, 1}, 99 | {INSERT, 2}, 100 | {INSERT, 3}, 101 | {INSERT, 4}, 102 | {INSERT, 5}}; 103 | OPERATION_VEC operationVec = prepare(operation, 5); 104 | 105 | OUTPUTTYPE expect[5] = {5, 4, 3, 2, 1}; 106 | RESULT_VEC expectVec = prepare(expect, 5); 107 | 108 | RESULT_VEC output = testStep(operationVec); 109 | EXPECT_TRUE(compareVector(expectVec, output)); 110 | } 111 | 112 | TEST(Delete, deleteLastNodeWillSecuss) 113 | { 114 | operation_t operation[2] = {{INSERT, 1}, 115 | {DELETE, 1}}; 116 | OPERATION_VEC operationVec = prepare(operation, 2); 117 | 118 | RESULT_VEC expect; 119 | 120 | RESULT_VEC output = testStep(operationVec); 121 | EXPECT_TRUE(compareVector(expect, output)); 122 | } 123 | 124 | TEST(Delete, deleteFrontNodeWillSecuss) 125 | { 126 | operation_t operation[4] = {{INSERT, 1}, 127 | {INSERT, 2}, 128 | {INSERT, 3}, 129 | {DELETE, 3}}; 130 | OPERATION_VEC operationVec = prepare(operation, 4); 131 | 132 | OUTPUTTYPE expect[2] = {2, 1}; 133 | RESULT_VEC expectVec = prepare(expect, 2); 134 | 135 | RESULT_VEC output = testStep(operationVec); 136 | EXPECT_TRUE(compareVector(expectVec, output)); 137 | } 138 | 139 | TEST(Delete, deleteTailNodeWillSecuss) 140 | { 141 | operation_t operation[4] = {{INSERT, 1}, 142 | {INSERT, 2}, 143 | {INSERT, 3}, 144 | {DELETE, 1}}; 145 | OPERATION_VEC operationVec = prepare(operation, 4); 146 | 147 | OUTPUTTYPE expect[2] = {3, 2}; 148 | RESULT_VEC expectVec = prepare(expect, 2); 149 | 150 | RESULT_VEC output = testStep(operationVec); 151 | EXPECT_TRUE(compareVector(expectVec, output)); 152 | } 153 | 154 | TEST(Delete, deleteMidNodeWillSecuss) 155 | { 156 | operation_t operation[4] = {{INSERT, 1}, 157 | {INSERT, 2}, 158 | {INSERT, 3}, 159 | {DELETE, 2}}; 160 | OPERATION_VEC operationVec = prepare(operation, 4); 161 | 162 | OUTPUTTYPE expect[2] = {3, 1}; 163 | RESULT_VEC expectVec = prepare(expect, 2); 164 | 165 | RESULT_VEC output = testStep(operationVec); 166 | EXPECT_TRUE(compareVector(expectVec, output)); 167 | } 168 | -------------------------------------------------------------------------------- /tst/chapter13/redBlackTreeTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "gtest/gtest.h" 5 | #include "redBlackTree.h" 6 | 7 | TEST(initTree, rootShouldBeNull) 8 | { 9 | CRedBlackTree tree; 10 | EXPECT_TRUE(CRedBlackTree::isNodeNull(tree.root)); 11 | } 12 | 13 | TEST(initTree, shouldBeEmpty) 14 | { 15 | CRedBlackTree tree; 16 | EXPECT_TRUE(CRedBlackTree::isNodeNull(tree.search(5))); 17 | } 18 | 19 | TEST(insert, shouldBeFound) 20 | { 21 | CRedBlackTree tree; 22 | tree.insert(5); 23 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(5))); 24 | } 25 | 26 | TEST(insert, allShouldBeFound) 27 | { 28 | CRedBlackTree tree; 29 | tree.insert(5); 30 | tree.insert(6); 31 | tree.insert(4); 32 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(4))); 33 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(5))); 34 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(6))); 35 | } 36 | 37 | TEST(remove, removeRootShouldEmpty) 38 | { 39 | CRedBlackTree tree; 40 | tree.insert(5); 41 | tree.remove(tree.search(5)); 42 | EXPECT_TRUE(CRedBlackTree::isNodeNull(tree.root)); 43 | } 44 | 45 | TEST(remove, removeDataShouldNotFound) 46 | { 47 | CRedBlackTree tree; 48 | tree.insert(5); 49 | tree.remove(tree.search(5)); 50 | EXPECT_TRUE(CRedBlackTree::isNodeNull(tree.search(5))); 51 | } 52 | 53 | TEST(remove, unremoveDataShouldFound) 54 | { 55 | CRedBlackTree tree; 56 | tree.insert(5); 57 | tree.insert(4); 58 | tree.remove(tree.search(5)); 59 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(4))); 60 | } 61 | 62 | TEST(remove, allUnremoveDataShouldFound) 63 | { 64 | CRedBlackTree tree; 65 | tree.insert(5); 66 | tree.insert(4); 67 | tree.insert(6); 68 | tree.remove(tree.search(5)); 69 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(4))); 70 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(6))); 71 | } 72 | 73 | -------------------------------------------------------------------------------- /tst/chapter14/makefile.mk: -------------------------------------------------------------------------------- 1 | INCS += -I../include/chapter14 2 | 3 | SRC_DIR_14 = ../src/chapter14 4 | TST_DIR_14 = chapter14 5 | 6 | SRC_14 = $(SRC_DIR_14)/section14_1.o \ 7 | $(SRC_DIR_14)/exercise14_2.o 8 | 9 | TST_14 = $(TST_DIR_14)/section14_1Test.o 10 | 11 | CHAPTER14 = $(SRC_14) $(TST_14) 12 | 13 | -------------------------------------------------------------------------------- /tst/chapter14/section14_1Test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: section14_1.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Mon 23 Nov 2015 07:53:37 PM CST 6 | ************************************************************************/ 7 | #include "section14_1.h" 8 | 9 | /* 10 | int main() 11 | { 12 | //生成一棵动态顺序统计树 13 | Os_Tree *T = new Os_Tree; 14 | int m, n, i; 15 | while(cin>>n>>m) 16 | { 17 | //将1.,n依次插入到树中 18 | for(i = 1; i <= n; i++) 19 | { 20 | node *z = new node(T->nil, i); 21 | Os_Tree_Insert(T, z); 22 | } 23 | int t = n, start = 0; 24 | //还有剩余结点 25 | while(t) 26 | { 27 | //计算下一个要删除的结点在剩余结点中的位置 28 | start = (start + m - 1) % t; 29 | //找到这个结点 30 | node *ret = Os_Tree_Select(T->root, start+1); 31 | cout<key<<' '; 32 | //删除这个结点 33 | Os_Tree_Delete(T, ret); 34 | t--; 35 | } 36 | cout< File Name: ../../tst/chapter14/section14_3Test.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Tue 01 Dec 2015 07:36:15 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | #include 11 | #include "Interval_Tree.h" 12 | using namespace std; 13 | 14 | int main() 15 | { 16 | char ch; 17 | int x, y; 18 | //生成一棵顺序统计树 19 | Interval_Tree *T = new Interval_Tree; 20 | while(1) 21 | { 22 | cin>>ch; 23 | switch(ch) 24 | { 25 | //插入一个元素 26 | case 'I': 27 | { 28 | //cin>>x>>y; 29 | x = rand() % 100; 30 | y = rand() % 100; 31 | if(x > y)swap(x, y); 32 | node *z = new node(T->nil, x, y); 33 | T->Insert(z); 34 | break; 35 | } 36 | //删除一个元素 37 | case 'D': 38 | { 39 | cin>>x; 40 | node *z = T->Search(T->root, x); 41 | if(z == NULL) 42 | cout<<"not exist"<Delete(z); 45 | break; 46 | } 47 | //求第一个与[x,y]相交的区间 48 | case 'S': 49 | { 50 | cin>>x>>y; 51 | node *z = T->Interval_Search(interval(x, y)); 52 | if(z == NULL) 53 | cout<<"not exist"<inte.low<<' '<inte.high<Print(); 60 | break; 61 | default: 62 | break; 63 | } 64 | } 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /tst/chapter15/Exercise15_1Test.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | 3 | #include 4 | 5 | #include "Exercise15_1.h" 6 | /* 7 | 1 1 8 | 2 7 9 | 3 4 10 | 6 3 11 | 7 6 12 | 8 2 13 | 9 5 14 | */ 15 | 16 | #define NUMOF(x) (sizeof(x)/sizeof(*(x))) 17 | 18 | static vector data2vector(int* data, int size) 19 | { 20 | vector ret; 21 | for(int i = 0; i < size; i+=2) 22 | { 23 | coord pos = {data[i], data[i+1]}; 24 | ret.push_back(pos); 25 | } 26 | return ret; 27 | } 28 | TEST(double_adjustable_euclidean_traveling_salesman, no_data_should_get_0) 29 | { 30 | vector v; 31 | double ret = Double_adjustable_Euclidean_traveling_salesman(v); 32 | EXPECT_EQ(0, ret); 33 | } 34 | 35 | TEST(double_adjustable_euclidean_traveling_salesman, data_in_book_should_get_right_result) 36 | { 37 | int data[] = {1, 1, 38 | 2, 7, 39 | 3, 4, 40 | 6, 3, 41 | 7, 6, 42 | 8, 2, 43 | 9, 5}; 44 | vector v = data2vector(data, NUMOF(data)); 45 | double ret = Double_adjustable_Euclidean_traveling_salesman(v); 46 | // EXPECT_GE(0.001, fabs(ret - 25.584)); 47 | } 48 | -------------------------------------------------------------------------------- /tst/chapter15/Exercise15_3Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #include "assert.h" 4 | 5 | int DP(string x, string z); 6 | void Print(int lx, int lz); 7 | 8 | static void test1() 9 | { 10 | string src = "algorithm"; 11 | string dst = "altruistic"; 12 | assert( 10 == DP(src, dst)); 13 | } 14 | 15 | void Exercise15_3Test() 16 | { 17 | test1(); 18 | } -------------------------------------------------------------------------------- /tst/chapter15/makefile.mk: -------------------------------------------------------------------------------- 1 | INCS += -I../include/chapter15 2 | 3 | SRC_DIR_15 = ../src/chapter15 4 | TST_DIR_15 = chapter15 5 | 6 | SRC_15 = $(SRC_DIR_15)/Exercise15_1.o 7 | 8 | TST_15 = $(TST_DIR_15)/Exercise15_1Test.o 9 | 10 | CHAPTER15 = $(SRC_15) $(TST_15) 11 | 12 | -------------------------------------------------------------------------------- /tst/chapter16/Exercise16_2_6Test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: Exercise16_2_6.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Thu 22 Oct 2015 06:21:45 PM CST 6 | ************************************************************************/ 7 | #include "gtest/gtest.h" 8 | #include "Exercise16_2_6.h" 9 | 10 | #define NUMOF(x) (sizeof(x)/sizeof(*(x))) 11 | 12 | TEST(no_material, empty) 13 | { 14 | EXPECT_EQ(0, partialPackage(0, 0, NULL)); 15 | EXPECT_EQ(0, partialPackage(5, 0, NULL)); 16 | } 17 | 18 | TEST(very_small_package, empty) 19 | { 20 | node material[] = {{0, 0}, 21 | {3, 5}, 22 | {2, 4}, 23 | {1, 7}}; 24 | EXPECT_EQ(0, partialPackage(0, NUMOF(material), material)); 25 | } 26 | 27 | TEST(very_small_package, half_of_one) 28 | { 29 | node material[] = {{0, 0}, 30 | {3, 5}, 31 | {2, 4}, 32 | {2, 7}}; 33 | EXPECT_EQ(3.5, partialPackage(1, NUMOF(material), material)); 34 | } 35 | 36 | TEST(very_big_package, only_one_material) 37 | { 38 | node material[] = {{0, 0}, 39 | {1, 7}}; 40 | EXPECT_EQ(7, partialPackage(100, NUMOF(material), material)); 41 | } 42 | 43 | TEST(very_big_package, more_than_one_material) 44 | { 45 | node material[] = {{0, 0}, 46 | {3, 5}, 47 | {2, 4}, 48 | {1, 7}}; 49 | EXPECT_EQ(16, partialPackage(100, NUMOF(material), material)); 50 | } 51 | 52 | TEST(not_enough_package, one_and_half) 53 | { 54 | node material[] = {{0, 0}, 55 | {3, 5}, 56 | {2, 4}, 57 | {2, 7}}; 58 | EXPECT_EQ(9, partialPackage(3, NUMOF(material), material)); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /tst/chapter16/chapter16Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "gtest/gtest.h" 5 | #include "chapter16.h" 6 | 7 | #define NUMOF(x) (sizeof(x)/sizeof(*(x))) 8 | 9 | /* 10 | 0 0 //虚构活动a0 11 | 1 4 12 | 3 5 13 | 0 6 14 | 5 7 15 | 3 8 16 | 5 9 17 | 6 10 18 | 8 11 19 | 8 12 20 | 2 13 21 | 12 14 22 | */ 23 | 24 | static vector data2vector(int* data, int len) 25 | { 26 | vector ret; 27 | activity a = {0, 0, 0}; 28 | ret.push_back(a); 29 | for(int i = 0; i < len; i+=2) 30 | { 31 | a.id = (i/2) + 1; 32 | a.start = data[i]; 33 | a.finish = data[i+1]; 34 | ret.push_back(a); 35 | } 36 | return ret; 37 | } 38 | 39 | TEST(greedy_activity_selector, no_activity_should_return_nothing) 40 | { 41 | vector param; 42 | vector ret = Greedy_Activity_Selector(param); 43 | EXPECT_EQ(0, ret.size()); 44 | } 45 | 46 | TEST(greedy_activity_selector, test_in_book__should_result_right) 47 | { 48 | int data[] = {1, 4, 49 | 3, 5, 50 | 0, 6, 51 | 5, 7, 52 | 3, 8, 53 | 5, 9, 54 | 6, 10, 55 | 8, 11, 56 | 8, 12, 57 | 2, 13, 58 | 12, 14 59 | }; 60 | vector param = data2vector(data, NUMOF(data)); 61 | vector ret = Greedy_Activity_Selector(param); 62 | int exp[] = {1, 4, 8, 11}; 63 | EXPECT_EQ(4, ret.size()); 64 | for(int i = 0; i < 4; i++) 65 | { 66 | EXPECT_EQ(exp[i], ret[i]); 67 | } 68 | } 69 | 70 | TEST(reccursive_activity_selector, no_activity_should_return_nothing) 71 | { 72 | vector param; 73 | vector ret = Greedy_Activity_Selector(param); 74 | EXPECT_EQ(0, ret.size()); 75 | } 76 | 77 | TEST(reccursive_activity_selector, test_in_book__should_result_right) 78 | { 79 | int data[] = {1, 4, 80 | 3, 5, 81 | 0, 6, 82 | 5, 7, 83 | 3, 8, 84 | 5, 9, 85 | 6, 10, 86 | 8, 11, 87 | 8, 12, 88 | 2, 13, 89 | 12, 14 90 | }; 91 | vector param = data2vector(data, NUMOF(data)); 92 | vector ret = Reccursive_Activity_Selector(param); 93 | int exp[] = {1, 4, 8, 11}; 94 | EXPECT_EQ(4, ret.size()); 95 | for(int i = 0; i < 4; i++) 96 | { 97 | EXPECT_EQ(exp[i], ret[i]); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /tst/chapter16/makefile.mk: -------------------------------------------------------------------------------- 1 | SRC_DIR_16 = ../src/chapter16 2 | TST_DIR_16 = chapter16 3 | 4 | SRC_16 = $(SRC_DIR_16)/Exercise16_2_6.o \ 5 | $(SRC_DIR_16)/chapter16.o 6 | 7 | TST_16 = $(TST_DIR_16)/Exercise16_2_6Test.o \ 8 | $(TST_DIR_16)/chapter16Test.o 9 | 10 | CHAPTER16 = $(SRC_16) $(TST_16) 11 | 12 | -------------------------------------------------------------------------------- /tst/chapter20/FibHeapTest.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: chapter20/fibHeapTest.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Sun 25 Oct 2015 10:32:19 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | #include "gtest/gtest.h" 12 | #include "FibHeap.h" 13 | 14 | TEST(initFibHeap, currentSizeShouldBe0) 15 | { 16 | CFibHeap H; 17 | EXPECT_EQ(0, H.getDataCount()); 18 | } 19 | 20 | TEST(getTopData, oneDataShouldGetTheData) 21 | { 22 | CFibHeap H; 23 | node *pN = new node(3); 24 | EXPECT_EQ(SUCCESS, H.insert(pN)); 25 | node *pTop = H.extract(); 26 | EXPECT_EQ(3, pTop->key); 27 | delete pTop; 28 | } 29 | 30 | TEST(merge, merge) 31 | { 32 | CFibHeap H1; 33 | node *pN1 = new node(5); 34 | H1.insert(pN1); 35 | 36 | CFibHeap H2; 37 | node *pN2 = new node(3); 38 | H2.insert(pN2); 39 | 40 | EXPECT_EQ(SUCCESS, H1.merge(&H2)); 41 | 42 | node *pTop = H1.extract(); 43 | EXPECT_EQ(3, pTop->key); 44 | delete pTop; 45 | 46 | pTop = H1.extract(); 47 | EXPECT_EQ(5, pTop->key); 48 | delete pTop; 49 | } 50 | -------------------------------------------------------------------------------- /tst/chapter22/Exercise22_3_6Test.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | 3 | using namespace std; 4 | #include 5 | 6 | #include "Exercise22_3_6.h" 7 | 8 | #define NUMOF(x) (sizeof(x)/sizeof(*(x))) 9 | 10 | class G_for_test : public Graph 11 | { 12 | public: 13 | void inputTestData(vector v); 14 | void testVisitTime(int vId, int start, int end); 15 | void testEdgeType(int *type, int len); 16 | }; 17 | 18 | vector data2Vector(char *data, int len) 19 | { 20 | vector ret; 21 | for(int i = 0; i < len; i++) 22 | ret.push_back(data[i] - 'p'); 23 | return ret; 24 | } 25 | 26 | void G_for_test::inputTestData(vector v) 27 | { 28 | for(int i = 0; i < v.size(); i+=2) 29 | { 30 | Edge *E = new Edge(v[i], v[i+1]); 31 | InsertEdge(this, E); 32 | //无向图,要加两条边 33 | // E = new Edge(end, start); 34 | // InsertEdge(this, E); 35 | } 36 | } 37 | 38 | void G_for_test::testVisitTime(int vId, int start, int end) 39 | { 40 | EXPECT_EQ(start, V[vId]->d); 41 | EXPECT_EQ(end, V[vId]->f); 42 | } 43 | 44 | /* 45 | * 1:"树边" 2:"反向边" 3:"正向边" 4:"交叉边" 46 | * */ 47 | void G_for_test::testEdgeType(int *type, int len) 48 | { 49 | int cnt = 0; 50 | for(int i = 1; i <= N; i++) 51 | { 52 | Edge *e = V[i]->head; 53 | while(e) 54 | { 55 | EXPECT_EQ(type[cnt], e->type) << e->start << ' '<< e->end <<' '<type; 56 | cnt++; 57 | if(cnt >= len)break; 58 | e = e->next; 59 | } 60 | if(cnt >= len)break; 61 | } 62 | } 63 | TEST(data_in_book, data_in_book) 64 | { 65 | char data[] = 66 | { 67 | 'q', 's', 68 | 's', 'v', 69 | 'v', 'w', 70 | 'w', 's', 71 | 'q', 'w', 72 | 'q', 't', 73 | 't', 'y', 74 | 'y', 'q', 75 | 't', 'x', 76 | 'x', 'z', 77 | 'z', 'x', 78 | 'u', 'y', 79 | 'r', 'y', 80 | 'r', 'u' 81 | }; 82 | vector v = data2Vector(data, NUMOF(data)); 83 | G_for_test *G = new G_for_test(); 84 | G->inputTestData(v); 85 | DFS(G); 86 | G->testVisitTime(1, 1, 16); 87 | G->testVisitTime(2, 17, 20); 88 | G->testVisitTime(3, 2, 7); 89 | G->testVisitTime(4, 8, 15); 90 | G->testVisitTime(5, 18, 19); 91 | G->testVisitTime(6, 3, 6); 92 | G->testVisitTime(7, 4, 5); 93 | G->testVisitTime(8, 9, 12); 94 | G->testVisitTime(9, 13, 14); 95 | G->testVisitTime(10, 10, 11); 96 | 97 | int edgeType[] = {1, 1, 3, 1, 4, 1, 1, 1, 4, 1, 2, 1, 2, 2}; 98 | G->testEdgeType(edgeType, NUMOF(edgeType)); 99 | delete G; 100 | } 101 | -------------------------------------------------------------------------------- /tst/chapter22/Exercise22_4_2Test.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | 3 | using namespace std; 4 | #include 5 | #include "Exercise22_4_2.h" 6 | 7 | #define NUMOF(x) (sizeof(x)/sizeof(*(x))) 8 | 9 | using namespace exercise22_4_2; 10 | class G_test_22_4_2 : public Graph 11 | { 12 | public: 13 | G_test_22_4_2(int n):Graph(n){} 14 | void inputTestData(vector v); 15 | }; 16 | 17 | static vector data2Vector(char *data, int len) 18 | { 19 | vector ret; 20 | for(int i = 0; i < len; i++) 21 | ret.push_back(data[i] - 'l'); 22 | return ret; 23 | } 24 | 25 | void G_test_22_4_2::inputTestData(vector v) 26 | { 27 | for(int i = 0; i < v.size(); i+=2) 28 | { 29 | Edge *E = new Edge(v[i], v[i+1]); 30 | InsertEdge(E); 31 | } 32 | } 33 | 34 | TEST(empty_graph, result_should_be_0) 35 | { 36 | G_test_22_4_2 *G = new G_test_22_4_2(0); 37 | EXPECT_EQ(0, G->countWays(0, 0)); 38 | delete G; 39 | } 40 | 41 | TEST(data_in_book, result_should_be_4) 42 | { 43 | char data[] = 44 | { 45 | 'm', 'q', 46 | 'm', 'r', 47 | 'm', 'x', 48 | 'n', 'q', 49 | 'n', 'u', 50 | 'n', 'o', 51 | 'o', 'r', 52 | 'o', 's', 53 | 'o', 'v', 54 | 'p', 'o', 55 | 'p', 'z', 56 | 'q', 't', 57 | 'r', 'y', 58 | 'r', 'u', 59 | 's', 'r', 60 | 'v', 'x', 61 | 'v', 'w', 62 | 'w', 'z', 63 | 'y', 'v' 64 | }; 65 | vector v = data2Vector(data, NUMOF(data)); 66 | G_test_22_4_2 *G = new G_test_22_4_2(14); 67 | G->inputTestData(v); 68 | EXPECT_EQ(3, G->countWays(4, 10)); 69 | delete G; 70 | } 71 | -------------------------------------------------------------------------------- /tst/chapter22/makefile.mk: -------------------------------------------------------------------------------- 1 | INCS += -I../include/chapter22 2 | 3 | SRC_DIR_22 = ../src/chapter22 4 | TST_DIR_22 = chapter22 5 | 6 | SRC_22 = $(SRC_DIR_22)/Exercise22_3_6.o \ 7 | $(SRC_DIR_22)/Exercise22_4_2.o 8 | 9 | 10 | TST_22 = $(TST_DIR_22)/Exercise22_3_6Test.o \ 11 | $(TST_DIR_22)/Exercise22_4_2Test.o 12 | 13 | CHAPTER22 = $(SRC_22) $(TST_22) 14 | 15 | -------------------------------------------------------------------------------- /tst/chapter22/section22_3Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "Link_Graph.h" 5 | 6 | int main() 7 | { 8 | int n, m, i; 9 | char start, end; 10 | //输入点的个数和边的个数 11 | cin>>n>>m; 12 | //构造一个空的图 13 | Link_Graph *G = new Link_Graph(n); 14 | //输入边 15 | for(i = 1; i <= m; i++) 16 | { 17 | cin>>start>>end; 18 | G->AddSingleEdge(start-'p', end-'p'); 19 | } 20 | //深度优先搜索 21 | G->DFS(); 22 | //输出每个顶点的第一次访问时间和访问结束的时间 23 | G->Print_Vertex_Time(); 24 | //输出每条边的类型 25 | G->Print_Edge_Type(); 26 | delete G; 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /tst/chapter26/MaxFlowTest.cpp: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include 3 | using namespace std; 4 | 5 | #include "MaxFlow.h" 6 | #define NUMOF(x) (sizeof(x)/sizeof(*(x))) 7 | /* 8 | 5 10 9 | 0 1 16 10 | 0 2 13 11 | 1 3 12 12 | 1 2 10 13 | 2 1 4 14 | 3 2 9 15 | 2 4 14 16 | 3 5 20 17 | 4 3 7 18 | 4 5 4 19 | */ 20 | struct testNode 21 | { 22 | int start, end, value; 23 | }; 24 | vector v; 25 | 26 | vector data2Vector(testNode *data, int len) 27 | { 28 | vector ret; 29 | for(int i = 0; i < len; i++) 30 | { 31 | ret.push_back(data[i]); 32 | } 33 | return ret; 34 | } 35 | 36 | class flowForTest : public Mat_Flow 37 | { 38 | public: 39 | flowForTest(int n):Mat_Flow(n){} 40 | void MakeGraph(vector v) 41 | { 42 | int start, end, value; 43 | for(int i = 0; i < v.size(); i++) 44 | { 45 | testNode temp = v[i]; 46 | AddSingleEdge(temp.start, temp.end, temp.value); 47 | } 48 | } 49 | }; 50 | 51 | TEST(case_in_book, case_in_book) 52 | { 53 | testNode data[] = {{0,1,16}, 54 | 0,2,13, 55 | 1,3,12, 56 | 1,2,10, 57 | 2,1,4, 58 | 3,2,9, 59 | 2,4,14, 60 | 3,5,20, 61 | 4,3,7, 62 | 4,5,4 63 | }; 64 | flowForTest *F = new flowForTest(5); 65 | vector v = data2Vector(data, NUMOF(data)); 66 | F->MakeGraph(v); 67 | 68 | EXPECT_EQ(23, F->max_flow()); 69 | delete F; 70 | } 71 | -------------------------------------------------------------------------------- /tst/chapter6/Exercise6_5_8Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "Exercise6_5_8.h" 5 | 6 | #include "gtest/gtest.h" 7 | 8 | /* 9 | #include "gmock/gmock.h" 10 | // Tests factorial of negative numbers. 11 | // 12 | using ::testing::_; 13 | using ::testing::SetArgPointee; 14 | using ::testing::DoAll; 15 | using ::testing::Return; 16 | using ::testing::Pointee; 17 | */ 18 | 19 | ARRAY setArray(int *initArray, int len, int list) 20 | { 21 | ARRAY ret; 22 | for(int i = 0; i < len; i++) 23 | { 24 | node newNode; 25 | newNode.value = initArray[i]; 26 | newNode.list = list; 27 | ret.push_back(newNode); 28 | } 29 | return ret; 30 | } 31 | 32 | bool compare(ARRAY A, ARRAY B) 33 | { 34 | if(A.size() != B.size()) 35 | return false; 36 | for(int i = 0; i < A.size(); i++) 37 | if(A[i].value != B[i].value) 38 | return false; 39 | return true; 40 | } 41 | 42 | TEST(only_one_array, only_one_data_in_array) 43 | { 44 | int initArray[1] = {5}; 45 | ARRAY array = setArray(initArray, 1, 0); 46 | vector inputParam; 47 | inputParam.push_back(array); 48 | 49 | ARRAY result = solve_6_5_8(inputParam); 50 | EXPECT_TRUE(compare(array, result)); 51 | } 52 | 53 | void printArray(ARRAY array) 54 | { 55 | for(int i = 0; i < array.size(); i++) 56 | cout< inputParam; 67 | inputParam.push_back(array1); 68 | inputParam.push_back(array2); 69 | 70 | ARRAY result = solve_6_5_8(inputParam); 71 | 72 | int expectArray[2] = {5, 4}; 73 | ARRAY expect = setArray(expectArray, 2, 0); 74 | EXPECT_TRUE(compare(expect, result)); 75 | } 76 | 77 | TEST(two_array, negitave_data_in_array) 78 | { 79 | int initArray1[5] = {13, 10, 7, -1, -4}; 80 | ARRAY array1 = setArray(initArray1, 5, 0); 81 | int initArray2[10] = {15, 14, 12, 11, 9, 8, 6, 0, -2, -3}; 82 | ARRAY array2 = setArray(initArray2, 10, 1); 83 | vector inputParam; 84 | inputParam.push_back(array1); 85 | inputParam.push_back(array2); 86 | 87 | ARRAY result = solve_6_5_8(inputParam); 88 | 89 | int expectArray[15] = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 0, -1, -2, -3, -4}; 90 | ARRAY expect = setArray(expectArray, 15, 0); 91 | EXPECT_TRUE(compare(expect, result)); 92 | } 93 | 94 | TEST(three_array, different_data_count_in_array) 95 | { 96 | int initArray1[6] = {10, 9, 8, 4, 3, 2}; 97 | ARRAY array1 = setArray(initArray1, 6, 0); 98 | int initArray2[2] = {7, 1}; 99 | ARRAY array2 = setArray(initArray2, 2, 1); 100 | int initArray3[4] = {6, 5, 0, -1}; 101 | ARRAY array3 = setArray(initArray3, 4, 2); 102 | vector inputParam; 103 | inputParam.push_back(array1); 104 | inputParam.push_back(array2); 105 | inputParam.push_back(array3); 106 | 107 | ARRAY result = solve_6_5_8(inputParam); 108 | 109 | int expectArray[15] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1}; 110 | ARRAY expect = setArray(expectArray, 12, 0); 111 | EXPECT_TRUE(compare(expect, result)); 112 | } 113 | -------------------------------------------------------------------------------- /tst/chapter6/HeapTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "gtest/gtest.h" 5 | //#include "gmock/gmock.h" 6 | 7 | #include "Heap.h" 8 | // Tests factorial of negative numbers. 9 | // 10 | /* 11 | using ::testing::_; 12 | using ::testing::SetArgPointee; 13 | using ::testing::DoAll; 14 | using ::testing::Return; 15 | using ::testing::Pointee; 16 | */ 17 | TEST(initHeap, currentSizeShouldBe0) 18 | { 19 | CMaxHeap H; 20 | EXPECT_EQ(0, H.currentSize); 21 | } 22 | 23 | TEST(initHeapWithSize, currentSizeShouldBe0) 24 | { 25 | CMaxHeap H(5, 0x7FFFFFFF); 26 | EXPECT_EQ(0, H.currentSize); 27 | EXPECT_EQ(5, H.maxSize); 28 | } 29 | 30 | TEST(initHeapWithMaxNode, allDataSetToMaxNode) 31 | { 32 | CMaxHeap H(5, 0x7FFFFFFF); 33 | for(int i = 0; i < H.maxSize; i++) 34 | EXPECT_EQ(0x7FFFFFFF, H.A[i]); 35 | } 36 | 37 | TEST(getMaxData, noDataShouldTheMaxNode) 38 | { 39 | CMaxHeap H(5, 0x7FFFFFFF); 40 | EXPECT_EQ(0x7FFFFFFF, H.Heap_Maximum()); 41 | } 42 | 43 | TEST(getMaxData, oneDataShouldGetTheData) 44 | { 45 | CMaxHeap H(5, 0x7FFFFFFF); 46 | H.insert(3); 47 | EXPECT_EQ(3, H.Heap_Maximum()); 48 | } 49 | -------------------------------------------------------------------------------- /tst/chapter7/Exercise7_1_2Test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: Exercise7_1_2Test.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Sun 29 Nov 2015 11:25:50 AM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | #include "gtest/gtest.h" 12 | #include "Exercise7_1_2.h" 13 | 14 | TEST(quick_sort_7_1_2, one_data_should_not_error) 15 | { 16 | int data[] = {1}; 17 | QuickSort7_1_2(data, 0, 0); 18 | EXPECT_EQ(1, data[0]); 19 | } 20 | 21 | TEST(quick_sort_7_1_2, two_data_should_sort) 22 | { 23 | int data[] = {2, 1}; 24 | QuickSort7_1_2(data, 0, 1); 25 | EXPECT_EQ(1, data[0]); 26 | EXPECT_EQ(2, data[1]); 27 | } 28 | -------------------------------------------------------------------------------- /tst/chapter7/Exercise7_6Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "gtest/gtest.h" 5 | 6 | #include "Exercise7_6.h" 7 | 8 | bool meet(const ARRAY & array) 9 | { 10 | for(int i = 1; i < array.size(); i++) 11 | { 12 | if(array[0] > array[1]) 13 | { 14 | return false; 15 | } 16 | } 17 | return true; 18 | } 19 | 20 | ARRAY setArray(int *start, int *end, int size) 21 | { 22 | ARRAY ret; 23 | for(int i = 0; i < size; i++) 24 | { 25 | section s; 26 | s.start = start[i]; 27 | s.end = end[i]; 28 | ret.push_back(s); 29 | } 30 | return ret; 31 | } 32 | TEST(noData, shoudNotChange) 33 | { 34 | ARRAY array; 35 | Exercise7_6(array); 36 | EXPECT_TRUE(meet(array)); 37 | } 38 | 39 | TEST(oneData, shouldNotChange) 40 | { 41 | int start[1] = {3}; 42 | int end[1] = {4}; 43 | ARRAY array = setArray(start, end, 1); 44 | Exercise7_6(array); 45 | EXPECT_TRUE(meet(array)); 46 | } 47 | 48 | TEST(twoData, dataNotEqualShouldSort) 49 | { 50 | int start[2] = {3, 1}; 51 | int end[2] = {4, 2}; 52 | ARRAY array = setArray(start, end, 2); 53 | Exercise7_6(array); 54 | EXPECT_TRUE(meet(array)); 55 | } 56 | 57 | TEST(twoData, equal) 58 | { 59 | int start[2] = {1, 2}; 60 | int end[2] = {4, 3}; 61 | ARRAY array = setArray(start, end, 2); 62 | Exercise7_6(array); 63 | EXPECT_TRUE(meet(array)); 64 | } 65 | 66 | TEST(moreData, a) 67 | { 68 | int start[3] = {2, 7, 1}; 69 | int end[3] = {2, 7, 8}; 70 | ARRAY array = setArray(start, end, 3); 71 | Exercise7_6(array); 72 | EXPECT_TRUE(meet(array)); 73 | } 74 | 75 | TEST(moreData, b) 76 | { 77 | int start[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; 78 | int end[10] = {14, 13, 12, 11, 10, 9, 8, 7, 6, 5}; 79 | ARRAY array = setArray(start, end, 10); 80 | Exercise7_6(array); 81 | EXPECT_TRUE(meet(array)); 82 | } 83 | -------------------------------------------------------------------------------- /tst/chapter7/makefile.mk: -------------------------------------------------------------------------------- 1 | INCS += -I../include/chapter7 2 | 3 | SRC_DIR_7 = ../src/chapter7 4 | TST_DIR_7 = chapter7 5 | 6 | SRC_7 = $(SRC_DIR_7)/quickSort.o \ 7 | $(SRC_DIR_7)/Exercise7_1_2.o \ 8 | $(SRC_DIR_7)/Exercise7_6.o 9 | 10 | 11 | TST_7 = $(TST_DIR_7)/quickSortTest.o \ 12 | $(TST_DIR_7)/Exercise7_1_2Test.o \ 13 | $(TST_DIR_7)/Exercise7_6Test.o 14 | 15 | CHAPTER7 = $(SRC_7) $(TST_7) 16 | 17 | -------------------------------------------------------------------------------- /tst/chapter7/quickSortTest.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: chapter7/quickSortTest.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Sat 24 Oct 2015 12:12:04 PM CST 6 | ************************************************************************/ 7 | #include "gtest/gtest.h" 8 | #include "quickSort.h" 9 | 10 | #define NUMOF(x) (sizeof(x)/sizeof(*(x))) 11 | 12 | bool check_equal(int *src, int *dst, int len) 13 | { 14 | for(int i = 0; i < len; i++) 15 | if(src[i] != dst[i]) 16 | return false; 17 | return true; 18 | } 19 | 20 | TEST(no_data_to_sort, no_error) 21 | { 22 | int src[] = {}; 23 | QuickSort(src, 1, NUMOF(src) - 1); 24 | Randomized_QuickSort(src, 1, NUMOF(src) - 1); 25 | } 26 | 27 | TEST(one_data_to_sort, data_not_change) 28 | { 29 | int src[] = {0, 1}; 30 | int dst[] = {0, 1}; 31 | QuickSort(src, 1, NUMOF(src) -1); 32 | EXPECT_TRUE(check_equal(src, dst, NUMOF(src))); 33 | 34 | int src2[] = {0, 1}; 35 | Randomized_QuickSort(src2, 1, NUMOF(src) - 1); 36 | EXPECT_TRUE(check_equal(src2, dst, NUMOF(src))); 37 | } 38 | 39 | TEST(more_than_one_data_to_sort, data_sorted) 40 | { 41 | int src[] = {0, 1, 4, 7, 6, 2}; 42 | int dst[] = {0, 1, 2, 4, 6, 7}; 43 | QuickSort(src, 1, NUMOF(src) -1); 44 | EXPECT_TRUE(check_equal(src, dst, NUMOF(src))); 45 | 46 | int src2[] = {0, 1, 4, 7, 6, 2}; 47 | Randomized_QuickSort(src2, 1, NUMOF(src) - 1); 48 | EXPECT_TRUE(check_equal(src2, dst, NUMOF(src))); 49 | } 50 | 51 | TEST(more_than_one_data_to_sort, with_same_data) 52 | { 53 | int src[] = {0, 1, 4, 6, 6, 2}; 54 | int dst[] = {0, 1, 2, 4, 6, 6}; 55 | QuickSort(src, 1, NUMOF(src) -1); 56 | EXPECT_TRUE(check_equal(src, dst, NUMOF(src))); 57 | 58 | int src2[] = {0, 1, 4, 6, 6, 2}; 59 | Randomized_QuickSort(src2, 1, NUMOF(src) - 1); 60 | EXPECT_TRUE(check_equal(src2, dst, NUMOF(src))); 61 | } 62 | 63 | //void QuickSort(int *A, int p, int r) 64 | -------------------------------------------------------------------------------- /tst/chapter8/Exercise8_3Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "Chapter8.h" 5 | 6 | #include "gtest/gtest.h" 7 | #include "gmock/gmock.h" 8 | // Tests factorial of negative numbers. 9 | // 10 | using ::testing::_; 11 | using ::testing::SetArgPointee; 12 | using ::testing::DoAll; 13 | using ::testing::Return; 14 | using ::testing::Pointee; 15 | 16 | #define ARRAY vector 17 | 18 | static void printArray(const ARRAY& array) 19 | { 20 | for(int i = 0; i < array.size(); i++) 21 | cout<< array[i]<<' '; 22 | cout< inputParam = setArray(initArray, 1); 47 | 48 | ARRAY result = solve8_3(inputParam); 49 | EXPECT_TRUE(compare(result, inputParam)); 50 | printArray(result); 51 | } 52 | 53 | TEST(dataWithDifferentDigit, sortByDigitCount) 54 | { 55 | int initArray[2] = {11, 1}; 56 | vector inputParam = setArray(initArray, 2); 57 | int expectArray[2] = {1, 11}; 58 | ARRAY expect = setArray(expectArray, 2); 59 | 60 | ARRAY result = solve8_3(inputParam); 61 | EXPECT_TRUE(compare(expect, result)); 62 | } 63 | 64 | TEST(moreDataWithDifferentDigit, dataShouldSort) 65 | { 66 | int initArray[4] = {1234, 5, 678, 90}; 67 | vector inputParam = setArray(initArray, 4); 68 | int expectArray[4] = {5, 90, 678, 1234}; 69 | ARRAY expect = setArray(expectArray, 4); 70 | 71 | ARRAY result = solve8_3(inputParam); 72 | EXPECT_TRUE(compare(expect, result)); 73 | } 74 | 75 | TEST(allDataInOneDigit, dataShouldSort) 76 | { 77 | int initArray[4] = {3, 2, 1, 0}; 78 | vector inputParam = setArray(initArray, 4); 79 | int expectArray[4] = {0, 1, 2, 3}; 80 | ARRAY expect = setArray(expectArray, 4); 81 | 82 | ARRAY result = solve8_3(inputParam); 83 | EXPECT_TRUE(compare(expect, result)); 84 | } 85 | -------------------------------------------------------------------------------- /tst/chapter8/chapter8Test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/windmissing/exerciseForAlgorithmSecond/c6ade0da2d7ca6be3415dece65e4f73ade5b4444/tst/chapter8/chapter8Test -------------------------------------------------------------------------------- /tst/chapter8/chapter8Test.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: chapter8/chapter8Test.cpp 3 | > Author: yinahe 4 | > Mail: yina.he@nokia.com 5 | > Created Time: Sun 29 Nov 2015 12:07:19 PM CST 6 | ************************************************************************/ 7 | 8 | #include 9 | using namespace std; 10 | 11 | #include "gtest/gtest.h" 12 | 13 | #include "chapter8.h" 14 | /* 15 | int main() 16 | { 17 | cin>>length_A>>digit; 18 | int *A = new int[length_A+1]; 19 | int *B = new int[length_A+1]; 20 | int i; 21 | //随机产生length_A个digit位的数据 22 | for(i = 1; i <= length_A; i++) 23 | { 24 | A[i] = 0; 25 | while(A[i] < (int)pow(10.0, digit-1)) 26 | A[i] = rand() % (int)pow(10.0, digit); 27 | } 28 | Print(A, 1, length_A); 29 | // Counting_Sort(A, B, 9); 30 | Radix_Sort(A, B); 31 | Print(A, 1, length_A); 32 | delete []A; 33 | delete []B; 34 | return 0; 35 | }*/ 36 | 37 | TEST(counting_sort, sort) 38 | { 39 | int A[] = {0, 5, 4, 3, 2, 1}; 40 | int B[6] = {}; 41 | int C[] = {0, 1, 2, 3, 4, 5}; 42 | Counting_Sort(A, B, 5, 10); 43 | for(int i = 1; i <= 5; i++) 44 | EXPECT_EQ(C[i], B[i]); 45 | } 46 | 47 | TEST(radix_sort, sort) 48 | { 49 | int A[] = {0, 5, 44, 3, 2222, 1}; 50 | int B[6] = {}; 51 | int C[] = {0, 1, 3, 5, 44, 2222}; 52 | Radix_Sort(A, B, 5, 4); 53 | for(int i = 1; i <= 5; i++) 54 | EXPECT_EQ(C[i], B[i]); 55 | } 56 | -------------------------------------------------------------------------------- /tst/chapter8/makefile.mk: -------------------------------------------------------------------------------- 1 | INCS += -I../include/chapter8 2 | 3 | SRC_DIR_8 = ../src/chapter8 4 | TST_DIR_8 = chapter8 5 | 6 | SRC_8 = $(SRC_DIR_8)/chapter8.o \ 7 | 8 | TST_8 = $(TST_DIR_8)/chapter8Test.o 9 | 10 | CHAPTER8 = $(SRC_8) $(TST_8) 11 | 12 | -------------------------------------------------------------------------------- /tst/chapter9/Exercise9_1_1Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "gtest/gtest.h" 5 | #include "Exercise9_1_1.h" 6 | 7 | #define NUMOF(x) (sizeof(x)/sizeof(*(x))) 8 | 9 | vector initArray(int *data, int len) 10 | { 11 | vector ret; 12 | for(int i = 0; i < len; i++) 13 | ret.push_back(data[i]); 14 | return ret; 15 | } 16 | 17 | TEST(noInput, shouleReturn0) 18 | { 19 | vector array; 20 | EXPECT_EQ(0, solve9_1_1(array)); 21 | } 22 | 23 | TEST(oneData, shouleReturn0) 24 | { 25 | int data[1] = {1}; 26 | vector array = initArray(data, 1); 27 | EXPECT_EQ(0, solve9_1_1(array)); 28 | } 29 | 30 | TEST(twoData, shouldGetTheFirstOne) 31 | { 32 | int data[2] = {2, 1}; 33 | vector array = initArray(data, NUMOF(data)); 34 | EXPECT_EQ(2, solve9_1_1(array)); 35 | } 36 | 37 | TEST(twoData, shouldGetTheSecondOne) 38 | { 39 | int data[2] = {1, 2}; 40 | vector array = initArray(data, NUMOF(data)); 41 | EXPECT_EQ(2, solve9_1_1(array)); 42 | } 43 | 44 | TEST(evenDataCount, secondDataInFirst) 45 | { 46 | int data[4] = {2, 1, 3, 4}; 47 | vector array = initArray(data, 4); 48 | EXPECT_EQ(2, solve9_1_1(array)); 49 | } 50 | 51 | TEST(evenDataCount, secondDataInLast) 52 | { 53 | int data[4] = {1, 3, 4, 2}; 54 | vector array = initArray(data, 4); 55 | EXPECT_EQ(2, solve9_1_1(array)); 56 | } 57 | 58 | TEST(evenDataCount, secondDataInSecond) 59 | { 60 | int data[4] = {1, 2, 4, 3}; 61 | vector array = initArray(data, 4); 62 | EXPECT_EQ(2, solve9_1_1(array)); 63 | } 64 | 65 | TEST(evenDataCount, secondDataInSecondLast) 66 | { 67 | int data[4] = {1, 4, 2, 3}; 68 | vector array = initArray(data, 4); 69 | EXPECT_EQ(2, solve9_1_1(array)); 70 | } 71 | 72 | TEST(oddDataCount, secondDataInFirst) 73 | { 74 | int data[5] = {2, 1, 4, 5, 3}; 75 | vector array = initArray(data, 5); 76 | EXPECT_EQ(2, solve9_1_1(array)); 77 | } 78 | 79 | TEST(oddDataCount, secondDataInLast) 80 | { 81 | int data[5] = {3, 1, 4, 5, 2}; 82 | vector array = initArray(data, 5); 83 | EXPECT_EQ(2, solve9_1_1(array)); 84 | } 85 | 86 | -------------------------------------------------------------------------------- /tst/chapter9/Exercise9_3_6Test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "Chapter9.h" 5 | 6 | #include "gtest/gtest.h" 7 | #include "gmock/gmock.h" 8 | // Tests factorial of negative numbers. 9 | // 10 | using ::testing::_; 11 | using ::testing::SetArgPointee; 12 | using ::testing::DoAll; 13 | using ::testing::Return; 14 | using ::testing::Pointee; 15 | 16 | static bool compareArray(const ARRAY & a, const ARRAY & b) 17 | { 18 | if(a.size() != b.size()) 19 | return false; 20 | for(int i = 0; i < a.size(); i++) 21 | if(a[i] != b[i]) 22 | return false; 23 | return true; 24 | } 25 | 26 | static ARRAY setArray(int *initData, int len) 27 | { 28 | ARRAY ret; 29 | for(int i = 0; i < len; i++) 30 | ret.push_back(initData[i]); 31 | return ret; 32 | } 33 | 34 | static void printArray(const ARRAY & array) 35 | { 36 | for(int i = 0; i < array.size(); i++) 37 | cout< 2 | using namespace std; 3 | 4 | #include "Chapter9.h" 5 | 6 | #include "gtest/gtest.h" 7 | #include "gmock/gmock.h" 8 | // Tests factorial of negative numbers. 9 | // 10 | using ::testing::_; 11 | using ::testing::SetArgPointee; 12 | using ::testing::DoAll; 13 | using ::testing::Return; 14 | using ::testing::Pointee; 15 | 16 | TEST(one_data_each_array, get_the_bigger_one) 17 | { 18 | int a[1] = {3}; 19 | int b[1] = {5}; 20 | CArrayFor_9_3_8 A(a, 1), B(b, 1); 21 | 22 | EXPECT_EQ(5, solve_9_3_8(A, B)); 23 | EXPECT_EQ(5, solve_9_3_8(B, A)); 24 | } 25 | 26 | TEST(two_data_each_array, get_the_less_bigger_one_1) 27 | { 28 | int a[2] = {1, 2}; 29 | int b[2] = {3, 4}; 30 | CArrayFor_9_3_8 A(a, 2), B(b, 2); 31 | 32 | EXPECT_EQ(3, solve_9_3_8(A, B)); 33 | } 34 | 35 | TEST(two_data_each_array, get_the_less_bigger_one_2) 36 | { 37 | int a[2] = {1, 3}; 38 | int b[2] = {2, 4}; 39 | CArrayFor_9_3_8 A(a, 2), B(b, 2); 40 | 41 | EXPECT_EQ(3, solve_9_3_8(A, B)); 42 | } 43 | 44 | TEST(three_data_each_array, get_the_third_bigger_one_1) 45 | { 46 | int a[3] = {1, 3, 5}; 47 | int b[3] = {2, 4, 6}; 48 | CArrayFor_9_3_8 A(a, 3), B(b, 3); 49 | 50 | EXPECT_EQ(4, solve_9_3_8(A, B)); 51 | } 52 | 53 | TEST(three_data_each_array, get_the_third_bigger_one_2) 54 | { 55 | int a[3] = {1, 2, 3}; 56 | int b[3] = {4, 5, 6}; 57 | CArrayFor_9_3_8 A(a, 3), B(b, 3); 58 | 59 | EXPECT_EQ(4, solve_9_3_8(A, B)); 60 | } 61 | 62 | int regularMethod(CArrayFor_9_3_8 A, CArrayFor_9_3_8 B) 63 | { 64 | CArrayFor_9_3_8 C = A; 65 | C.insertArray(B); 66 | C.sortData(); 67 | return C.getDownMiddle(); 68 | } 69 | 70 | TEST(radom_data_each_array, test) 71 | { 72 | CArrayFor_9_3_8 A(5), B(5); 73 | A.makeRadomData(); 74 | B.makeRadomData(); 75 | int expectResult = regularMethod(A, B); 76 | 77 | EXPECT_EQ(expectResult, solve_9_3_8(A, B)); 78 | } 79 | 80 | -------------------------------------------------------------------------------- /tst/chapter9/makefile.mk: -------------------------------------------------------------------------------- 1 | SRC_DIR_9 = ../src/chapter9 2 | TST_DIR_9 = chapter9 3 | 4 | SRC_9 = $(SRC_DIR_9)/Exercise9_1_1.o 5 | 6 | 7 | TST_9 = $(TST_DIR_9)/Exercise9_1_1Test.o 8 | 9 | CHAPTER9 = $(SRC_9) $(TST_9) 10 | 11 | -------------------------------------------------------------------------------- /tst/coverage.sh: -------------------------------------------------------------------------------- 1 | ######################################################################### 2 | # File Name: coverage.sh 3 | # Author: yinahe 4 | # mail: yina.he@nokia.com 5 | # Created Time: Thu 29 Oct 2015 07:57:13 PM CST 6 | ######################################################################### 7 | #!/bin/bash 8 | 9 | cd result 10 | 11 | rm -rf result 12 | 13 | cp ../*.gcda ./ 14 | cp ../*.gcno ./ 15 | cp ../*/*.gcda ./ 16 | cp ../*/*.gcno ./ 17 | cp ../../src/*/*.gcda ./ 18 | cp ../../src/*/*.gcno ./ 19 | gcov ../*.cpp ../*/*.cpp ../../src/*/*.cpp 20 | 21 | lcov -c -o log.info -d . 22 | genhtml log.info -o result 23 | firefox result/index.html 24 | -------------------------------------------------------------------------------- /tst/makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | CXXFLAGS = -g -L/opt/gtest/lib -lgtest -lgtest_main -lpthread -D__UT__ -fprofile-arcs -ftest-coverage 3 | INCS = -I./ \ 4 | -I/opt/gtest/include \ 5 | -I../include/chapter6 \ 6 | -I../src/chapter6 \ 7 | -I../include/chapter9 \ 8 | -I../include/chapter10 \ 9 | -I../include/chapter13 \ 10 | -I../include/chapter16 \ 11 | -I../include/chapter20 \ 12 | -I../include/chapter26 13 | 14 | SRC_6 = ../src/chapter6/Exercise6_5_8.o 15 | TST_6 = chapter6/Exercise6_5_8Test.o \ 16 | chapter6/HeapTest.o 17 | 18 | CHAPTER6 = $(SRC_6) $(TST_6) 19 | 20 | include chapter7/makefile.mk 21 | include chapter8/makefile.mk 22 | include chapter9/makefile.mk 23 | 24 | SRC_10 = ../src/chapter10/Exercise10_1_2.o 25 | TST_10 = chapter10/Exercise10_1_2Test.o 26 | 27 | CHAPTER10 = $(SRC_10) $(TST_10) 28 | 29 | SRC_13 = ../src/chapter13/redBlackTree.o 30 | TST_13 = chapter13/redBlackTreeTest.o 31 | 32 | CHAPTER13 = $(SRC_13) $(TST_13) 33 | 34 | include chapter14/makefile.mk 35 | include chapter15/makefile.mk 36 | include chapter16/makefile.mk 37 | 38 | SRC_20 = ../src/chapter20/FibHeap.o 39 | TST_20 = chapter20/FibHeapTest.o 40 | 41 | CHAPTER20 = $(SRC_20) $(TST_20) 42 | 43 | include chapter22/makefile.mk 44 | 45 | SRC_26 = ../src/chapter26/MaxFlow.o 46 | TST_26 = chapter26/MaxFlowTest.o 47 | 48 | CHAPTER26 = $(SRC_26) $(TST_26) 49 | 50 | OBJS = $(CHAPTER6) $(CHAPTER7) $(CHAPTER8) $(CHAPTER9) $(CHAPTER10) $(CHAPTER13) $(CHAPTER14) $(CHAPTER15) $(CHAPTER16) $(CHAPTER20) $(CHAPTER22) $(CHAPTER26) 51 | 52 | testAll: $(OBJS) 53 | $(CXX) $(CXXFLAGS) -o testAll Main_TestAll.cpp $(OBJS) $(INCS) 54 | # ./testAll 55 | 56 | .cpp.o: 57 | $(CXX) $(CXXFLAGS) -c $< -o $@ $(INCS) 58 | 59 | 60 | clean: 61 | rm -r testAll */*.o testAll.xml *.gcov ../src/*/*.o */*.gcno */*.gcda ../src/*/*.gcno ../src/*/*.gcda 62 | -------------------------------------------------------------------------------- /tst/others/BigNumberTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "BigNumber.h" 5 | 6 | #include "gtest/gtest.h" 7 | #include "gmock/gmock.h" 8 | // Tests factorial of negative numbers. 9 | // 10 | using ::testing::_; 11 | using ::testing::SetArgPointee; 12 | using ::testing::DoAll; 13 | using ::testing::Return; 14 | using ::testing::Pointee; 15 | 16 | #include "BigNumber.h" 17 | #define MAX_SIZE 200 18 | 19 | bool checkAllMemberZero(const CBigNumber & number) 20 | { 21 | if(number.usedCells != 0) 22 | return false; 23 | for(int i = 0; i < MAX_SIZE; i++) 24 | if(number.cell[i] != 0) 25 | return false; 26 | return true; 27 | } 28 | 29 | bool isNumberEqual(const CBigNumber & number1, CBigNumber & number2) 30 | { 31 | if(number1.usedCells != number2.usedCells) 32 | return false; 33 | for(int i = 0; i < number1.usedCells; i++) 34 | if(number1.cell[i] != number2.cell[i]) 35 | return false; 36 | return true; 37 | } 38 | 39 | CBigNumber generateRadomNumber() 40 | { 41 | CBigNumber radom; 42 | radom.usedCells = rand() % MAX_SIZE; 43 | for(int i = 0; i < radom.usedCells; i++) 44 | radom.cell[i] = rand(); 45 | return radom; 46 | } 47 | 48 | TEST(initNumberWithNoParam, allMemberIsZero) 49 | { 50 | CBigNumber number; 51 | EXPECT_TRUE(checkAllMemberZero(number)); 52 | } 53 | 54 | TEST(initWithLongLong, initCellIsStoredInOneCell) 55 | { 56 | long long initNumber = 1234567890123; 57 | CBigNumber number(initNumber); 58 | EXPECT_EQ(1, number.usedCells); 59 | EXPECT_EQ(initNumber, number.cell[0]); 60 | } 61 | 62 | TEST(initWithBigNumber, newNumberAndOriginNumberAreEqual) 63 | { 64 | CBigNumber origin = generateRadomNumber(); 65 | CBigNumber number(origin); 66 | EXPECT_TRUE(isNumberEqual(origin, number)); 67 | } 68 | 69 | TEST(initWithString, numberLessThan18DigitIsStoredInOneCell) 70 | { 71 | CBigNumber number("123456789"); 72 | EXPECT_EQ(1, number.usedCells); 73 | EXPECT_EQ(123456789, number.cell[0]); 74 | } 75 | 76 | TEST(initWithString, numberMoreThan18DigitIsStoredInMoreCells) 77 | { 78 | CBigNumber number("123456789""123456789123456789"); 79 | EXPECT_EQ(2, number.usedCells); 80 | EXPECT_EQ(123456789123456789, number.cell[0]); 81 | EXPECT_EQ(123456789, number.cell[1]); 82 | } 83 | 84 | TEST(isUpOverflow, usedCellsMoreThanMaxCellCounts) 85 | { 86 | CBigNumber number; 87 | number.usedCells = MAX_SIZE + 10; 88 | 89 | EXPECT_TRUE(number.isUpOverflow()); 90 | } 91 | 92 | TEST(isNotUpOverflow, usedCellslessThanMaxCellCounts) 93 | { 94 | CBigNumber number; 95 | number.usedCells = MAX_SIZE - 10; 96 | 97 | EXPECT_FALSE(number.isUpOverflow()); 98 | } 99 | 100 | TEST(isPalindrome, usedOneCell) 101 | { 102 | CBigNumber number(12345678987654321); 103 | EXPECT_TRUE(number.isPalindrome()); 104 | } 105 | 106 | TEST(isPalindrome, usedMoreThanOneCells) 107 | { 108 | CBigNumber number("111112222233333444445555544444333332222211111"); 109 | EXPECT_TRUE(number.isPalindrome()); 110 | } 111 | 112 | TEST(operatorAsign, everyMemberWillCopy) 113 | { 114 | CBigNumber origin = generateRadomNumber(); 115 | CBigNumber number = origin; 116 | 117 | EXPECT_TRUE(isNumberEqual(origin, number)); 118 | } 119 | 120 | TEST(numberNotEqual, usedCellsNotEqual) 121 | { 122 | CBigNumber number1, number2; 123 | number1.usedCells = 5; 124 | number2.usedCells = 10; 125 | 126 | EXPECT_FALSE(number1 == number2); 127 | } 128 | 129 | TEST(numberNotEqual, cellNotEqual) 130 | { 131 | CBigNumber number1(12345), number2(54321); 132 | EXPECT_FALSE(number1 == number2); 133 | } 134 | 135 | TEST(getReverseNumber, usedOneCells) 136 | { 137 | CBigNumber number(123456789); 138 | CBigNumber expectNumber(987654321); 139 | 140 | EXPECT_TRUE(expectNumber == number.getReverseNumber()); 141 | } 142 | 143 | 144 | TEST(getReverseNumber, usedMoreThanOneCells) 145 | { 146 | CBigNumber number("1234567890""1234567890""1234567890""123456"); 147 | CBigNumber expectNumber("654321""0987654321""0987654321""0987654321"); 148 | 149 | EXPECT_TRUE(expectNumber == number.getReverseNumber()); 150 | } 151 | 152 | TEST(operatorAdd, usedCellsIs1WillWork) 153 | { 154 | CBigNumber number1(123), number2(456), sum(123+456); 155 | EXPECT_TRUE(sum == number1 + number2); 156 | } 157 | 158 | TEST(operatorAdd, usedCellsMoreThan1WillWork) 159 | { 160 | CBigNumber number1("11111111111111111111"); 161 | CBigNumber number2("22222222222222222222"); 162 | CBigNumber sum("33333333333333333333"); 163 | 164 | EXPECT_TRUE(sum == number1 + number2); 165 | } 166 | 167 | TEST(toLongLong, usedCellsIs1WillGetAll) 168 | { 169 | CBigNumber number(123456789); 170 | 171 | EXPECT_EQ(123456789, number.toLongLong()); 172 | } 173 | 174 | TEST(toLongLong, usedCellsMoreThan1WillGetLast18Digits) 175 | { 176 | CBigNumber number("1234123456789987654321"); 177 | 178 | EXPECT_EQ(123456789987654321, number.toLongLong()); 179 | } 180 | 181 | TEST(operatorLess, usedMoreCellsIsBigger) 182 | { 183 | CBigNumber number1, number2; 184 | number1.usedCells = 5; 185 | number2.usedCells = 10; 186 | 187 | EXPECT_TRUE(number1 < number2); 188 | } 189 | 190 | TEST(operatorLess, usediSameCellsWillDecideByCell) 191 | { 192 | CBigNumber number1(123), number2(456); 193 | EXPECT_TRUE(number1 < number2); 194 | } 195 | -------------------------------------------------------------------------------- /tst/others/binarySearchTreeTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "gtest/gtest.h" 5 | #include "gmock/gmock.h" 6 | 7 | #include "binarySearchTree.h" 8 | // Tests factorial of negative numbers. 9 | // 10 | using ::testing::_; 11 | using ::testing::SetArgPointee; 12 | using ::testing::DoAll; 13 | using ::testing::Return; 14 | using ::testing::Pointee; 15 | 16 | TEST(initBST, rootShouldBeNull) 17 | { 18 | CBinarySearchTree tree; 19 | EXPECT_EQ(NULL, tree.root); 20 | } 21 | 22 | #if 0 23 | TEST(initTree, shouldBeEmpty) 24 | { 25 | CRedBlackTree tree; 26 | EXPECT_TRUE(CRedBlackTree::isNodeNull(tree.search(5))); 27 | } 28 | 29 | TEST(insert, shouldBeFound) 30 | { 31 | CRedBlackTree tree; 32 | tree.insert(5); 33 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(5))); 34 | } 35 | 36 | TEST(insert, allShouldBeFound) 37 | { 38 | CRedBlackTree tree; 39 | tree.insert(5); 40 | tree.insert(6); 41 | tree.insert(4); 42 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(4))); 43 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(5))); 44 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(6))); 45 | } 46 | 47 | TEST(remove, removeRootShouldEmpty) 48 | { 49 | CRedBlackTree tree; 50 | tree.insert(5); 51 | tree.remove(tree.search(5)); 52 | EXPECT_TRUE(CRedBlackTree::isNodeNull(tree.root)); 53 | } 54 | 55 | TEST(remove, removeDataShouldNotFound) 56 | { 57 | CRedBlackTree tree; 58 | tree.insert(5); 59 | tree.remove(tree.search(5)); 60 | EXPECT_TRUE(CRedBlackTree::isNodeNull(tree.search(5))); 61 | } 62 | 63 | TEST(remove, unremoveDataShouldFound) 64 | { 65 | CRedBlackTree tree; 66 | tree.insert(5); 67 | tree.insert(4); 68 | tree.remove(tree.search(5)); 69 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(4))); 70 | } 71 | 72 | TEST(remove, allUnremoveDataShouldFound) 73 | { 74 | CRedBlackTree tree; 75 | tree.insert(5); 76 | tree.insert(4); 77 | tree.insert(6); 78 | tree.remove(tree.search(5)); 79 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(4))); 80 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(6))); 81 | } 82 | #endif 83 | -------------------------------------------------------------------------------- /tst/others/intervalTreeTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | #include "gtest/gtest.h" 5 | #include "gmock/gmock.h" 6 | 7 | #include "intervalTree.h" 8 | // Tests factorial of negative numbers. 9 | // 10 | using ::testing::_; 11 | using ::testing::SetArgPointee; 12 | using ::testing::DoAll; 13 | using ::testing::Return; 14 | using ::testing::Pointee; 15 | 16 | #if 0 17 | #include 18 | #include "Interval_Tree.h" 19 | using namespace std; 20 | 21 | int main() 22 | { 23 | char ch; 24 | int x, y; 25 | //生成一棵顺序统计树 26 | Interval_Tree *T = new Interval_Tree; 27 | while(1) 28 | { 29 | cin>>ch; 30 | switch(ch) 31 | { 32 | //插入一个元素 33 | case 'I': 34 | { 35 | //cin>>x>>y; 36 | x = rand() % 100; 37 | y = rand() % 100; 38 | if(x > y)swap(x, y); 39 | node *z = new node(T->nil, x, y); 40 | T->Insert(z); 41 | break; 42 | } 43 | //删除一个元素 44 | case 'D': 45 | { 46 | cin>>x; 47 | node *z = T->Search(T->root, x); 48 | if(z == NULL) 49 | cout<<"not exist"<Delete(z); 52 | break; 53 | } 54 | //求第一个与[x,y]相交的区间 55 | case 'S': 56 | { 57 | cin>>x>>y; 58 | node *z = T->Interval_Search(interval(x, y)); 59 | if(z == NULL) 60 | cout<<"not exist"<inte.low<<' '<inte.high<Print(); 67 | break; 68 | default: 69 | break; 70 | } 71 | } 72 | return 0; 73 | } 74 | #endif 75 | #if 0 76 | /* 77 | static bool nodeCanBeFound(const CRedBlackTree & tree, int key) 78 | { 79 | node * ret = tree.search(key); 80 | return CRedBlackTree::isNodeNull(ret); 81 | } 82 | */ 83 | TEST(initTree, rootShouldBeNull) 84 | { 85 | CRedBlackTree tree; 86 | EXPECT_TRUE(CRedBlackTree::isNodeNull(tree.root)); 87 | } 88 | 89 | TEST(initTree, shouldBeEmpty) 90 | { 91 | CRedBlackTree tree; 92 | EXPECT_TRUE(CRedBlackTree::isNodeNull(tree.search(5))); 93 | } 94 | 95 | TEST(insert, shouldBeFound) 96 | { 97 | CRedBlackTree tree; 98 | tree.insert(5); 99 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(5))); 100 | } 101 | 102 | TEST(insert, allShouldBeFound) 103 | { 104 | CRedBlackTree tree; 105 | tree.insert(5); 106 | tree.insert(6); 107 | tree.insert(4); 108 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(4))); 109 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(5))); 110 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(6))); 111 | } 112 | 113 | TEST(remove, removeRootShouldEmpty) 114 | { 115 | CRedBlackTree tree; 116 | tree.insert(5); 117 | tree.remove(tree.search(5)); 118 | EXPECT_TRUE(CRedBlackTree::isNodeNull(tree.root)); 119 | } 120 | 121 | TEST(remove, removeDataShouldNotFound) 122 | { 123 | CRedBlackTree tree; 124 | tree.insert(5); 125 | tree.remove(tree.search(5)); 126 | EXPECT_TRUE(CRedBlackTree::isNodeNull(tree.search(5))); 127 | } 128 | 129 | TEST(remove, unremoveDataShouldFound) 130 | { 131 | CRedBlackTree tree; 132 | tree.insert(5); 133 | tree.insert(4); 134 | tree.remove(tree.search(5)); 135 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(4))); 136 | } 137 | 138 | TEST(remove, allUnremoveDataShouldFound) 139 | { 140 | CRedBlackTree tree; 141 | tree.insert(5); 142 | tree.insert(4); 143 | tree.insert(6); 144 | tree.remove(tree.search(5)); 145 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(4))); 146 | EXPECT_FALSE(CRedBlackTree::isNodeNull(tree.search(6))); 147 | } 148 | #endif 149 | -------------------------------------------------------------------------------- /tst/others/sortTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | 5 | #include "gtest/gtest.h" 6 | #include "gmock/gmock.h" 7 | // Tests factorial of negative numbers. 8 | // 9 | using ::testing::_; 10 | using ::testing::SetArgPointee; 11 | using ::testing::DoAll; 12 | using ::testing::Return; 13 | using ::testing::Pointee; 14 | 15 | #include "sort.h" 16 | 17 | static ARRAY setArray(int *initArray, int len) 18 | { 19 | ARRAY ret; 20 | for(int i = 0; i < len; i++) 21 | { 22 | ret.push_back(initArray[i]); 23 | } 24 | return ret; 25 | } 26 | 27 | static bool compare(ARRAY A, ARRAY B) 28 | { 29 | if(A.size() != B.size()) 30 | return false; 31 | for(int i = 0; i < A.size(); i++) 32 | if(A[i] != B[i]) 33 | return false; 34 | return true; 35 | } 36 | 37 | void printArray(ARRAY array) 38 | { 39 | for(int i = 0; i < array.size(); i++) 40 | cout<