├── 01-复杂度1 最大子列和问题 (20分) ├── 01-复杂度2 Maximum Subsequence Sum (25分) ├── 02-线性结构1 两个有序链表序列的合并 (15分) ├── 02-线性结构2 一元多项式的乘法与加法运算 ├── 02-线性结构3 Reversing Linked List (25分) ├── 02-线性结构4 Pop Sequence (25分) ├── 03-树1 树的同构 (25分).cpp ├── 03-树2 List Leaves.cpp ├── 03-树3 Tree Traversals Again.cpp ├── 04-树4 是否同一棵二叉搜索树.cpp ├── 04-树5 Root of AVL Tree.cpp ├── 04-树6 Complete Binary Search Tree.cpp ├── 04-树7 二叉搜索树的操作集.cpp ├── 05-树10 Huffman Codes.cpp ├── 05-树8 堆中的路径.cpp ├── 05-树9 File Transfer.cpp ├── 06-图1 列出连通集.cpp ├── 06-图2 Saving James Bond - Easy Version.cpp ├── 06-图3 六度空间.cpp ├── 07-图4 哈利·波特的考试.cpp ├── 07-图5 Saving James Bond - Hard Version ├── 07-图6 旅游规划.cpp ├── 08-图7 公路村村通.cpp ├── 08-图8 How Long Does It Take.cpp ├── 08-图9 关键活动.cpp ├── 09-排序1 排序.cpp ├── 09-排序2 Insert or Merge.cpp ├── 09-排序3 Insertion or Heap Sort.cpp ├── 10-排序4 统计工龄.cpp ├── 10-排序5 PAT Judge.cpp ├── 10-排序6 Sort with Swap(0, i).cpp ├── 11-散列1 电话聊天狂人.cpp ├── 11-散列2 Hashing.cpp ├── 11-散列3 QQ帐户的申请与登陆.cpp ├── 11-散列4 Hashing - Hard Version.cpp └── README.md /01-复杂度1 最大子列和问题 (20分): -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //KEY: use algorithm--Divide and Conquer; 4 | 5 | using namespace std; 6 | int *Init_array(int n); 7 | int max(int a, int b, int c); 8 | int divideseq(int *p, int left, int right); 9 | int MaxSub(int *p, int n); 10 | 11 | int main() 12 | { 13 | int n, i = 0; 14 | cin >> n; 15 | int *p = Init_array(n); 16 | 17 | cout << MaxSub(p, n) << endl; 18 | delete[] p; 19 | 20 | return 0; 21 | } 22 | 23 | int* Init_array(int n) //initialize array; 24 | { 25 | int *pArray = new int[n]; 26 | int i = 0; 27 | while (i < n) 28 | cin >> pArray[i++]; 29 | 30 | return pArray; 31 | } 32 | 33 | int max(int a, int b, int c) 34 | { 35 | return (a>b ? (a > c ? a : c) : (b < c ? c : b)); 36 | } 37 | 38 | int divideseq(int *p, int left, int right) 39 | { 40 | int i, maxboaderleft, maxboaderright; 41 | int leftboader = 0, rightboader = 0; 42 | 43 | if (left == right) //it means only one data, the ending condition; 44 | { 45 | if (p[left] > 0) 46 | return p[left]; 47 | else 48 | return 0; 49 | } 50 | 51 | int center = (left + right) / 2; 52 | int maxleft = divideseq(p, left, center); // use 'recursion' to get the max left value; 53 | int maxright = divideseq(p, center + 1, right); 54 | 55 | maxboaderleft = 0; 56 | for (i = center; i >= left; i--) // get left boader max value, and right value, sum them. 57 | { 58 | leftboader += p[i]; 59 | if (leftboader > maxboaderleft) //so we get the value including the left and the right; 60 | maxboaderleft = leftboader; 61 | } 62 | 63 | maxboaderright = 0; 64 | for (i = center + 1; i <= right; i++) 65 | { 66 | rightboader += p[i]; 67 | if (rightboader > maxboaderright) 68 | maxboaderright = rightboader; 69 | } 70 | 71 | return max(maxleft, maxright, maxboaderleft + maxboaderright); 72 | } 73 | 74 | int MaxSub(int *p, int n) 75 | { 76 | return divideseq(p, 0, n - 1); 77 | } 78 | -------------------------------------------------------------------------------- /01-复杂度2 Maximum Subsequence Sum (25分): -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //key: Algorithm-- start from the first one, sum every one; if the sum is negative, it means the sequence is not it. 4 | // record the sequence from next. 5 | 6 | using namespace std; 7 | int *Init_Array(int n); 8 | void MaxSeq(int *p, int n); 9 | 10 | int main() 11 | { 12 | int n; 13 | cin >> n; 14 | int *p = Init_Array(n); //initialize the array; 15 | MaxSeq(p, n); 16 | 17 | return 0; 18 | } 19 | 20 | int *Init_Array(int n) 21 | { 22 | int *pArray = new int[n]; 23 | int i = 0; 24 | while (i < n) 25 | cin >> pArray[i++]; 26 | 27 | return pArray; 28 | } 29 | 30 | void MaxSeq(int *p, int n) 31 | { 32 | int maxsum, thisum, tempfirst, i, firstone, endone; 33 | 34 | tempfirst = firstone = 0; 35 | endone = n - 1; 36 | thisum = i = 0; 37 | maxsum = -1; 38 | while (i < n) 39 | { 40 | thisum += p[i]; //record the sum, if thisum is greater than maxsum, 41 | if (thisum > maxsum) //let thisum be maxsum; 42 | { 43 | maxsum = thisum; 44 | endone = i; 45 | firstone = tempfirst; 46 | } 47 | else if (thisum < 0) //record a new startpoint; thisum can't equal '0' either because 0 belongs to the sequense; 48 | { 49 | thisum = 0; 50 | tempfirst = i + 1; 51 | } 52 | i++; 53 | } 54 | 55 | if (maxsum == -1) 56 | cout << "0 " << p[0] << ' ' << p[n - 1] << endl; 57 | else 58 | { 59 | cout << maxsum << ' ' << p[firstone] << ' ' << p[endone] << endl; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /02-线性结构1 两个有序链表序列的合并 (15分): -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | typedef int ElementType; 5 | typedef struct Node *PtrToNode; 6 | struct Node 7 | { 8 | ElementType Data; 9 | PtrToNode Next; 10 | }; 11 | typedef PtrToNode List; 12 | 13 | List Read(); 14 | void Print(List L); 15 | List Merge(List L1, List L2); 16 | 17 | int main() 18 | { 19 | List L1, L2, L; 20 | L1 = Read(); 21 | L2 = Read(); 22 | L = Merge(L1, L2); 23 | 24 | Print(L); 25 | Print(L1); 26 | Print(L2); 27 | 28 | return 0; 29 | } 30 | 31 | List Read() 32 | { 33 | List pHead = new Node; 34 | pHead->Next = NULL; 35 | List p = pHead; 36 | int n, t, i = 0; 37 | cin >> n; 38 | 39 | while (i < n) 40 | { 41 | cin >> t; 42 | List pNew = new Node; 43 | pNew->Data = t; 44 | pNew->Next = NULL; 45 | p->Next = pNew; 46 | p = pNew; 47 | i++; 48 | } 49 | return pHead; 50 | } 51 | 52 | void Print(List L) 53 | { 54 | List p = L->Next; 55 | int flag = 1; 56 | if (p == NULL) 57 | cout << "NULL"; 58 | else 59 | { 60 | while (p) 61 | { 62 | if (flag) 63 | { 64 | cout << p->Data; 65 | flag = 0; 66 | } 67 | else 68 | cout << ' ' << p->Data; 69 | 70 | p = p->Next; 71 | } 72 | } 73 | 74 | cout << endl; 75 | } 76 | 77 | List Merge(List L1, List L2) 78 | { 79 | List pHead = new Node; //create L3's head node; 80 | pHead->Next = NULL; 81 | List p1 = L1->Next; 82 | List p2 = L2->Next; 83 | List p3 = pHead; 84 | 85 | while (p1 && p2) 86 | { 87 | if (p1->Data < p2->Data) 88 | { 89 | p3->Next = p1; 90 | p3 = p1; 91 | p1 = p1->Next; 92 | } 93 | else 94 | { 95 | p3->Next = p2; 96 | p3 = p2; 97 | p2 = p2->Next; 98 | } 99 | 100 | } 101 | 102 | if (p1) //connect the rest to L3; 103 | p3->Next = p1; 104 | if (p2) 105 | p3->Next = p2; 106 | 107 | L1->Next = NULL; 108 | L2->Next = NULL; 109 | 110 | return pHead; 111 | } 112 | -------------------------------------------------------------------------------- /02-线性结构2 一元多项式的乘法与加法运算: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef int element; 4 | typedef struct Node 5 | { 6 | element coef; 7 | element exp; 8 | struct Node * Next; 9 | }node; 10 | using namespace std; 11 | 12 | node * Read(); 13 | node * Add(node *L1, node *L2); 14 | node * Mult(node *L1, node *L2); 15 | void Print(node *L); 16 | node * Insert(node *p, element c, element e); 17 | 18 | int main() 19 | { 20 | node *L1, *L2, *L3, *L4; 21 | L1 = Read(); 22 | L2 = Read(); 23 | L4 = Mult(L1, L2); 24 | L3 = Add(L1, L2); 25 | 26 | Print(L4); 27 | Print(L3); 28 | 29 | return 0; 30 | } 31 | 32 | node * Read() 33 | { 34 | node *p; 35 | node * phead = new node; 36 | phead->Next = NULL; 37 | p = phead; 38 | int n, i = 0; 39 | cin >> n; 40 | 41 | while (i < n) 42 | { 43 | node *pNew = new node; 44 | cin >> pNew->coef >> pNew->exp; 45 | pNew->Next = NULL; 46 | p->Next = pNew; 47 | p = pNew; 48 | i++; 49 | } 50 | return phead; 51 | } 52 | 53 | node * Add(node *L1, node *L2) 54 | { 55 | node *phead = new node; 56 | node *p1 = L1->Next; 57 | node *p2 = L2->Next; 58 | node *p3 = phead; 59 | phead->Next = NULL; 60 | 61 | while (p1 && p2) 62 | { 63 | node *t1, *t2; 64 | if (p1->exp == p2->exp) 65 | { 66 | t1 = p1; 67 | t2 = p2; 68 | t1->coef = p1->coef + p2->coef; // list L1 as the new list L3's template; 69 | if (t1->coef != 0) 70 | { 71 | p3->Next = t1; 72 | p3 = t1; 73 | p1 = p1->Next; 74 | p2 = p2->Next; 75 | p3->Next = NULL; 76 | delete t2; 77 | } 78 | else 79 | { 80 | p1 = p1->Next; 81 | p2 = p2->Next; 82 | delete t1; 83 | delete t2; 84 | } 85 | } 86 | else if (p1->exp > p2->exp) 87 | { 88 | p3->Next = p1; 89 | p3 = p1; 90 | p1 = p1->Next; 91 | p3->Next = NULL; 92 | } 93 | else 94 | { 95 | p3->Next = p2; 96 | p3 = p2; 97 | p2 = p2->Next; 98 | p3->Next = NULL; 99 | } 100 | 101 | } 102 | 103 | if (p1) 104 | p3->Next = p1; 105 | if (p2) 106 | p3->Next = p2; 107 | 108 | L1->Next = NULL; 109 | L2->Next = NULL; 110 | 111 | return phead; 112 | } 113 | 114 | void Print(node *L) 115 | { 116 | node *p = L->Next; 117 | if (!p) 118 | cout << "0 0" << endl; 119 | while (p) 120 | { 121 | if (p->Next != NULL) 122 | cout << p->coef << ' ' << p->exp << ' '; 123 | else 124 | cout << p->coef << ' ' << p->exp << endl; 125 | p = p->Next; 126 | } 127 | return; 128 | } 129 | 130 | node * Mult(node *L1, node *L2) //key: insert list p3 by every node; 131 | { 132 | element c, e; 133 | node *phead = new node; 134 | phead->Next = NULL; 135 | node *p1 = L1->Next; 136 | node *p2 = L2->Next; 137 | node *p3 = phead; 138 | 139 | if (!p1 || !p2) 140 | return phead; //not 'NULL'; 141 | 142 | while (p2) 143 | { 144 | node *pNew = new node; 145 | p3 = Insert(p3, p1->coef * p2->coef, p1->exp + p2->exp); 146 | p2 = p2->Next; 147 | } 148 | 149 | p1 = p1->Next; 150 | node *t; 151 | while (p1) 152 | { 153 | p2 = L2->Next; 154 | p3 = phead->Next; 155 | while (p2) 156 | { 157 | c = p1->coef * p2->coef; 158 | e = p1->exp + p2->exp; 159 | while (p3->Next && p3->Next->exp > e) 160 | p3 = p3->Next; 161 | 162 | if (p3->Next && p3->Next->exp == e) 163 | { 164 | if (p3->Next->coef + c != 0) 165 | p3->Next->coef += c; 166 | else 167 | { 168 | t = p3->Next; 169 | p3->Next = t->Next; 170 | delete t; 171 | } 172 | } 173 | else 174 | { 175 | p3 = Insert(p3, c, e); 176 | } 177 | 178 | p2 = p2->Next; 179 | } 180 | 181 | p1 = p1->Next; 182 | } 183 | 184 | return phead; 185 | } 186 | 187 | node * Insert(node *p, element c, element e) 188 | { 189 | node *t = new node; 190 | t->coef = c; 191 | t->exp = e; 192 | t->Next = p->Next; 193 | p->Next = t; 194 | 195 | return t; 196 | } 197 | -------------------------------------------------------------------------------- /02-线性结构3 Reversing Linked List (25分): -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //key: use the array's labelcase as every data's local address; 5 | 6 | #define N 100001 7 | using namespace std; 8 | 9 | int main() 10 | { 11 | int data[N], next[N]; 12 | int temp, n, k, st, i; 13 | cin >> st >> n >> k; 14 | 15 | i = 0; 16 | while (i < n) 17 | { 18 | cin >> temp; 19 | cin >> data[temp] >> next[temp]; 20 | i++; 21 | } 22 | 23 | int adr[N], re[N]; 24 | int cnt = 0; 25 | temp = st; 26 | while (temp != -1) // find the address linklist; 27 | { 28 | adr[cnt++] = temp; 29 | temp = next[temp]; 30 | } 31 | 32 | for (i = 0; i < cnt; i++) //copy it to re[]; 33 | re[i] = adr[i]; 34 | 35 | i = 0; 36 | while (k != 1 && i < cnt - cnt%k) 37 | { 38 | re[i] = adr[k - i%k - 1 + i / k * k]; // reverse the linklist; 39 | i++; 40 | } 41 | 42 | for (i = 0; i < cnt - 1; i++) //output result; 43 | printf("%05d %d %05d\n", re[i], data[re[i]], re[i + 1]); 44 | printf("%05d %d -1\n", re[i], data[re[i]]); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /02-线性结构4 Pop Sequence (25分): -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | //key: use 'STL'-template-'stack'; 7 | //imitate the operation of stack; 8 | int main() 9 | { 10 | int n, k; 11 | unsigned int m; 12 | stack st; 13 | cin >> m >> n >> k; 14 | int *flag = new int[n]; 15 | 16 | int i, j, t, num; 17 | for (i = 0; i < k; i++) 18 | { 19 | t = flag[i] = 1; 20 | for (j = 0; j < n; j++) 21 | { 22 | cin >> num; 23 | if (flag[i]) 24 | { 25 | while (st.empty() || st.top() != num) // if unequal, push the number; 26 | { 27 | st.push(t); 28 | t++; 29 | 30 | if (st.size() > m) 31 | { 32 | flag[i] = 0; 33 | break; 34 | } 35 | 36 | } 37 | } 38 | if (flag[i] && !st.empty() && st.top() == num) 39 | st.pop(); 40 | } 41 | while (!st.empty()) // clear the stack; 42 | st.pop(); 43 | 44 | } 45 | 46 | for (i = 0; i < k; i++) 47 | { 48 | if (flag[i]) 49 | printf("YES\n"); 50 | else 51 | printf("NO\n"); 52 | 53 | } 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /03-树1 树的同构 (25分).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | typedef struct tnode 5 | { 6 | char ch; 7 | int left; 8 | int right; 9 | }tNode; 10 | tNode * tBuild(int &m); 11 | int isOmorphic(tNode *t1, int h1, tNode *t2, int h2); 12 | 13 | //key: use recursion method; 14 | //data structure use static link to imitate the bi-tree; 15 | int main() 16 | { 17 | int h1, h2; 18 | 19 | tNode *tr1 = tBuild(h1); 20 | tNode *tr2 = tBuild(h2); 21 | 22 | if (isOmorphic(tr1, h1, tr2, h2)) 23 | cout << "Yes" << endl; 24 | else 25 | cout << "No" << endl; 26 | 27 | delete[] tr1; 28 | delete[] tr2; 29 | 30 | return 0; 31 | } 32 | 33 | tNode * tBuild(int &m) 34 | { 35 | int i, n; 36 | cin >> n; 37 | tNode *tr = new tNode[n]; 38 | 39 | if (n) 40 | { 41 | int * check = new int[n]; 42 | for (i = 0; i < n; i++) 43 | check[i] = 0; 44 | 45 | char t1, t2; 46 | for (i = 0; i < n; i++) 47 | { 48 | cin >> tr[i].ch >> t1 >> t2; 49 | if (t1 == '-') 50 | tr[i].left = -1; // '-1' means it's a leaf node; 51 | else 52 | { 53 | tr[i].left = t1 - '0'; 54 | check[tr[i].left] = 1; 55 | } 56 | if (t2 == '-') 57 | tr[i].right = -1; 58 | else 59 | { 60 | tr[i].right = t2 - '0'; 61 | check[tr[i].right] = 1; 62 | } 63 | } 64 | 65 | for (i = 0; i < n; i++) 66 | { 67 | if (!check[i]) 68 | break; 69 | } 70 | m = i; //find the head node; 71 | return tr; 72 | } 73 | else 74 | { 75 | m = -1; 76 | return NULL; 77 | } 78 | } 79 | 80 | int isOmorphic(tNode *t1, int h1, tNode *t2, int h2) // recursion; 81 | { 82 | if (h1 == -1 && h2 == -1) 83 | return 1; 84 | if ((h1 == -1 && h2 != -1) || (h1 != -1 && h2 == -1)) 85 | return 0; 86 | if (t1[h1].ch != t2[h2].ch) 87 | return 0; 88 | 89 | return((isOmorphic(t1, t1[h1].left, t2, t2[h2].left) && isOmorphic(t1, t1[h1].right, t2, t2[h2].right)) || 90 | (isOmorphic(t1, t1[h1].right, t2, t2[h2].left) && isOmorphic(t1, t1[h1].left, t2, t2[h2].right))); 91 | 92 | } 93 | -------------------------------------------------------------------------------- /03-树2 List Leaves.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | typedef struct node 5 | { 6 | int left; 7 | int right; 8 | }Node; 9 | 10 | Node *tBuild(int &h); //call by reference; 11 | void LevelOrder(Node *tr, int h); 12 | 13 | //idea: build the tree use static link firstly; 14 | // then traverse the tree by imitating level-order travese; 15 | int main() 16 | { 17 | int hd; 18 | Node *tr = tBuild(hd); 19 | LevelOrder(tr, hd); 20 | 21 | return 0; 22 | } 23 | 24 | Node *tBuild(int &h) 25 | { 26 | int n, i; 27 | char tleft, tright; 28 | cin >> n; 29 | Node *tr = new Node[n]; 30 | int *check = new int[n]; 31 | for (i = 0; i < n; i++) 32 | check[i] = 0; 33 | 34 | for (i = 0; i < n; i++) 35 | { 36 | cin >> tleft >> tright; 37 | if (tleft == '-') 38 | tr[i].left = -1; 39 | else 40 | { 41 | tr[i].left = tleft - '0'; 42 | check[tr[i].left] = 1; 43 | } 44 | 45 | if (tright == '-') 46 | tr[i].right = -1; 47 | else 48 | { 49 | tr[i].right = tright - '0'; 50 | check[tr[i].right] = 1; 51 | } 52 | } 53 | 54 | for (i = 0; i < n; i++) 55 | { 56 | if (!check[i]) 57 | break; 58 | } 59 | h = i; 60 | return tr; 61 | } 62 | 63 | void LevelOrder(Node *tr, int h) 64 | { 65 | int t, flag = 1; 66 | queue q; 67 | q.push(h); 68 | while (!q.empty()) 69 | { 70 | t = q.front(); 71 | q.pop(); 72 | if (tr[t].left == -1 && tr[t].right == -1) 73 | { 74 | if (flag) 75 | { 76 | cout << t; 77 | flag = 0; 78 | } 79 | else 80 | cout << ' ' << t; 81 | } 82 | else 83 | { 84 | if (tr[t].left != -1) 85 | q.push(tr[t].left); 86 | if (tr[t].right != -1) 87 | q.push(tr[t].right); 88 | } 89 | } 90 | cout << endl; 91 | } 92 | -------------------------------------------------------------------------------- /03-树3 Tree Traversals Again.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | int find_pos(vector &v, int data); 8 | void post_traverse(vector &pre, vector &ino, int left, int right, int head); 9 | 10 | //idea: the order of push is the Pre_order bi_tree, one of pop is the In_order bi_tree; 11 | // so by recursion, we can get the post-order using the pre-order and in-order sequences; 12 | int main() 13 | { 14 | int n, i, node; 15 | string str; 16 | stack sta; 17 | vector pre, ino; 18 | cin >> n; 19 | for (i = 0; i < 2*n; i++) 20 | { 21 | cin >> str; 22 | if (str == "Push") // get the pre-order sequence; 23 | { 24 | cin >> node; 25 | pre.push_back(node); 26 | sta.push(node); 27 | } 28 | else 29 | { 30 | ino.push_back(sta.top()); // get the in-order sequence; 31 | sta.pop(); 32 | } 33 | } 34 | 35 | post_traverse(pre, ino, 0, n - 1, 0); 36 | 37 | return 0; 38 | } 39 | 40 | int find_pos(vector &v, int data) 41 | { 42 | unsigned int i; 43 | for (i = 0; i < v.size(); i++) 44 | { 45 | if (v[i] == data) 46 | break; 47 | } 48 | return i; 49 | } 50 | 51 | void post_traverse(vector &pre, vector &ino, int left, int right, int head) 52 | { 53 | int pa_pos = find_pos(ino, pre[head]); 54 | int left_size = pa_pos - left + 1; 55 | if (head < (int)pre.size()) 56 | { 57 | if (pa_pos > left) //recurse left part; 58 | post_traverse(pre, ino, left, pa_pos - 1, head + 1); 59 | if (pa_pos < right) 60 | post_traverse(pre, ino, pa_pos + 1, right, head + left_size); //recurse right part; 61 | if (head == 0) 62 | cout << pre[head] << endl; // output the parent node; 63 | else 64 | cout << pre[head] << ' '; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /04-树4 是否同一棵二叉搜索树.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | typedef struct Node 4 | { 5 | int data, flag; 6 | struct Node * left; 7 | struct Node *right; 8 | }node; 9 | 10 | node *nwNode(int d); 11 | void nodeInsert(node *&head, int d); 12 | node *tBuild(int n); 13 | int tJudge(node *head, int n); 14 | void flagReset(node *head); 15 | void tDelete(node *head); 16 | 17 | /* 18 | 19 | 思路:先建立模板树,然后依次将待测试树和其比较。 20 | 比较过的结点的标志设为1,若该结点未比较过且其数据不等,则两树不同。 21 | */ 22 | int main() 23 | { 24 | int n, line, i; 25 | cin >> n; 26 | while (n) 27 | { 28 | cin >> line; 29 | node *head = tBuild(n); 30 | for (i = 0; i < line; i++) 31 | { 32 | if (tJudge(head, n)) 33 | cout << "Yes" << endl; 34 | else 35 | cout << "No" << endl; 36 | 37 | flagReset(head); 38 | } 39 | tDelete(head); 40 | 41 | cin >> n; 42 | } 43 | 44 | return 0; 45 | } 46 | 47 | node *nwNode(int d) 48 | { 49 | node *p = new node; 50 | p->data = d; 51 | p->flag = 0; 52 | p->left = p->right = NULL; 53 | return p; 54 | } 55 | void nodeInsert(node *&head, int d) 56 | { 57 | 58 | if (!head) 59 | head = nwNode(d); 60 | else 61 | { 62 | if (d > head->data) 63 | nodeInsert(head->right, d); 64 | else 65 | nodeInsert(head->left, d); 66 | } 67 | } 68 | node *tBuild(int n) 69 | { 70 | int i, d; 71 | cin >> d; 72 | node *head = nwNode(d); 73 | for (i = 1; i < n; i++) 74 | { 75 | cin >> d; 76 | nodeInsert(head, d); 77 | } 78 | return head; 79 | } 80 | int tJudge(node *head, int n) 81 | { 82 | node *T; 83 | int i, t, fflag = 1; 84 | for (i = 0; i < n; i++) 85 | { 86 | T = head; 87 | cin >> t; 88 | while (T && fflag) 89 | { 90 | if (T->flag == 1) 91 | { 92 | if (t > T->data) 93 | T = T->right; 94 | else 95 | T = T->left; 96 | } 97 | else if (T->flag == 0 && T->data == t) 98 | { 99 | T->flag = 1; 100 | break; 101 | } 102 | else 103 | { 104 | fflag = 0; 105 | break; 106 | } 107 | } 108 | } 109 | if (fflag == 0 || T == NULL) 110 | return 0; 111 | else 112 | return 1; 113 | } 114 | void flagReset(node *head) //需要恢复结点的标志。 115 | { 116 | if (head->left) 117 | flagReset(head->left); 118 | if (head->right) 119 | flagReset(head->right); 120 | head->flag = 0; 121 | } 122 | void tDelete(node *head) 123 | { 124 | if (head->left) 125 | tDelete(head->left); 126 | if (head->right) 127 | tDelete(head->right); 128 | delete head; 129 | } 130 | -------------------------------------------------------------------------------- /04-树5 Root of AVL Tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | typedef struct Node 5 | { 6 | int data; 7 | struct Node *left; 8 | struct Node *right; 9 | }node; 10 | 11 | int GetH(node *T); 12 | node *SingleLL(node *T); 13 | node *SingleRR(node *T); 14 | node *DoubleLR(node *T); 15 | node *DoubleRL(node *T); 16 | node *nInsert(node *T, int d); 17 | 18 | //经典的AVL旋转问题。 19 | int main() 20 | { 21 | node *T = NULL; 22 | int N, i, t; 23 | cin >> N; 24 | for (i = 0; i < N; i++) 25 | { 26 | cin >> t; 27 | T = nInsert(T, t); 28 | } 29 | cout << T->data << endl; 30 | 31 | return 0; 32 | } 33 | 34 | int GetH(node *T) 35 | { 36 | if (!T) 37 | return 0; 38 | 39 | return(max(GetH(T->left), GetH(T->right)) + 1); 40 | } //取得树的高度, 空树高度为0。 41 | 42 | node *SingleLL(node *T) //左单旋; 43 | { 44 | node *B = T->left; 45 | T->left = B->right; 46 | B->right = T; 47 | 48 | return B; 49 | } 50 | 51 | node *SingleRR(node *T) //右单旋; 52 | { 53 | node *B = T->right; 54 | T->right = B->left; 55 | B->left = T; 56 | 57 | return B; 58 | } 59 | 60 | node *DoubleLR(node *T) //左右双旋; 61 | { 62 | T->left = SingleRR(T->left); 63 | T = SingleLL(T); 64 | 65 | return T; 66 | } 67 | 68 | node *DoubleRL(node *T) //右左双旋; 69 | { 70 | T->right = SingleLL(T->right); 71 | T = SingleRR(T); 72 | 73 | return T; 74 | } 75 | 76 | node *nInsert(node *T, int d) //建立AVL树; 77 | { 78 | if (!T) 79 | { 80 | T = new node; 81 | T->data = d; 82 | T->left = NULL; 83 | T->right = NULL; 84 | } 85 | else if (d < T->data) 86 | { 87 | T->left = nInsert(T->left, d); //递归左插入; 88 | if (GetH(T->left) - GetH(T->right) == 2) //平衡处理; 89 | { 90 | if (d < T->left->data) 91 | T = SingleLL(T); 92 | else 93 | T = DoubleLR(T); 94 | } 95 | } 96 | else if (d > T->data) 97 | { 98 | T->right = nInsert(T->right, d); //递归右插; 99 | if (GetH(T->left) - GetH(T->right) == -2) //平衡处理; 100 | { 101 | if (d > T->right->data) 102 | T = SingleRR(T); 103 | else 104 | T = DoubleRL(T); 105 | } 106 | } 107 | 108 | return T; 109 | } 110 | -------------------------------------------------------------------------------- /04-树6 Complete Binary Search Tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int incCmp(const void *a, const void *b); //快排比较函数; 5 | void tBuild(int *T, int root, int *ino, int &pos, int n); //模拟建造完全二叉树; 6 | void Print(int *T, int n); //打印输出; 7 | 8 | /* 9 | 思路:刚开始打算仿照AVL想法建树,后面发现无法根据左右旋转来平衡。 10 | 后面看了下大牛的思路。 11 | 题意其实是构造一个完全二叉排序树,所以我们要分析完全二叉树的性质, 即结点下标i, 12 | 左子结点2i, 右子结点2i+1, 这是完全二叉树特有的性质。所以结构上我们可以用数组来表示。 13 | 然后如何保证有序呢?不要忘了,二叉排序树中序遍历是有序的。 14 | 于是问题就成了,通过完全二叉树的中序遍历输出层序遍历。 15 | */ 16 | int main() 17 | { 18 | int N, i; 19 | int pos = 0; 20 | cin >> N; 21 | int *T = new int[N+1]; 22 | int *ino = new int[N]; 23 | for (i = 0; i < N; i++) 24 | cin >> ino[i]; 25 | qsort(ino, N, sizeof(ino[0]), incCmp); //数组排序形成中序遍历; 26 | tBuild(T, 1, ino, pos, N); //模拟建造完全二叉树; 27 | Print(T, N + 1); 28 | 29 | return 0; 30 | } 31 | 32 | int incCmp(const void *a, const void *b) //快排比较函数; 33 | { 34 | return (*(int*)a - *(int*)b); 35 | } 36 | 37 | void tBuild(int *T, int root, int *ino, int &pos, int n) //模拟建造完全二叉树; 38 | { 39 | if (root > n) //递归终止条件; 40 | return; 41 | int left, right; 42 | left = root << 1; //左子结点下标; 43 | right = (root << 1) + 1; //右子结点下标; 44 | tBuild(T, left, ino, pos, n); //左递归; 45 | T[root] = ino[pos++]; 46 | tBuild(T, right, ino, pos, n); //右递归; 47 | } 48 | 49 | void Print(int *T, int n) //打印输出; 50 | { 51 | int i, flag = 1; 52 | for (i = 1; i < n; i++) 53 | { 54 | if (flag) 55 | { 56 | cout << T[i]; 57 | flag = 0; 58 | } 59 | else 60 | cout << ' ' << T[i]; 61 | } 62 | cout << endl; 63 | 64 | return; 65 | } 66 | -------------------------------------------------------------------------------- /04-树7 二叉搜索树的操作集.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef int ElementType; 5 | typedef struct TNode *Position; 6 | typedef Position BinTree; 7 | struct TNode{ 8 | ElementType Data; 9 | BinTree Left; 10 | BinTree Right; 11 | }; 12 | 13 | BinTree Insert(BinTree BST, ElementType X); 14 | BinTree Delete(BinTree BST, ElementType X); 15 | Position Find(BinTree BST, ElementType X); 16 | Position FindMin(BinTree BST); 17 | Position FindMax(BinTree BST); 18 | 19 | int main() 20 | { 21 | BinTree BST, MinP, MaxP, Tmp; 22 | ElementType X; 23 | int N, i; 24 | 25 | BST = NULL; 26 | scanf("%d", &N); 27 | for (i = 0; iData); 41 | if (Tmp == MinP) printf("%d is the smallest key\n", Tmp->Data); 42 | if (Tmp == MaxP) printf("%d is the largest key\n", Tmp->Data); 43 | } 44 | } 45 | scanf("%d", &N); 46 | for (i = 0; iData = X; 60 | BST->Left = BST->Right = NULL; 61 | } 62 | else if (X < BST->Data) 63 | BST->Left = Insert(BST->Left, X); 64 | else if (X > BST->Data) 65 | BST->Right = Insert(BST->Right, X); 66 | 67 | return BST; 68 | } 69 | 70 | BinTree Delete(BinTree BST, ElementType X) 71 | { 72 | BinTree Temp; 73 | if (!BST) 74 | printf("Not Found\n"); 75 | else if (X < BST->Data) 76 | BST->Left = Delete(BST->Left, X); 77 | else if (X > BST->Data) 78 | BST->Right = Delete(BST->Right, X); 79 | else 80 | { 81 | if (BST->Left && BST->Right) //有两个子结点,用右子节点最大代替。 82 | { 83 | Temp = FindMin(BST->Right); 84 | BST->Data = Temp->Data; 85 | BST->Right = Delete(BST->Right, Temp->Data); 86 | } 87 | else //有一个子结点或没有。 88 | { 89 | Temp = BST; 90 | if (BST->Left) //只有左子结点; 91 | BST = BST->Left; 92 | else //只有右子结点; 93 | BST = BST->Right; 94 | free(Temp); 95 | } 96 | } 97 | 98 | return BST; 99 | } 100 | 101 | Position Find(BinTree BST, ElementType X) 102 | { 103 | if (!BST) 104 | return NULL; 105 | 106 | if (X < BST->Data) 107 | return(Find(BST->Left, X)); 108 | else if (X > BST->Data) 109 | return(Find(BST->Right, X)); 110 | else 111 | return BST; 112 | } 113 | 114 | Position FindMin(BinTree BST) 115 | { 116 | if (!BST) 117 | return NULL; 118 | if (!BST->Left) 119 | return BST; 120 | else 121 | return FindMin(BST->Left); 122 | } 123 | 124 | Position FindMax(BinTree BST) 125 | { 126 | if (!BST) 127 | return NULL; 128 | if (!BST->Right) 129 | return BST; 130 | else 131 | return FindMax(BST->Right); 132 | } 133 | -------------------------------------------------------------------------------- /05-树10 Huffman Codes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | struct Heap 5 | { 6 | int *data; 7 | int size = 0; 8 | }; 9 | struct cnode 10 | { 11 | int tag = 0; 12 | cnode *left = nullptr; 13 | cnode *right = nullptr; 14 | }; 15 | 16 | Heap *Init_Heap(int n); //初始化小根堆(利用静态链表的逻辑结构); 17 | void Insert_Heap(Heap *H, int x); //把元素依次插入小根堆; 18 | int Delmin_Heap(Heap *H); //删除小根堆中的最小元素; 19 | int Cal_Wpl(Heap *H); //计算huffman编码的wpl; 20 | int wpl_prefix(int *sample, int n, int &re); //计算待测编码的wpl及判断是否为前缀编码; 21 | 22 | /*思路:要判断是否,需要解决两个问题: 1)编码wpl等于huffman编码的wpl; 23 | 2)待测编码是前缀编码。 24 | 问题1: 首先要求出标准wpl。观察huffman树,我们发现其wpl是非叶子结点权值和。 25 | 于是,我们无需构造出huffman树来求权值(麻烦点),通过模拟树的构造过程, 26 | 理由小根堆的特点求出wpl; 27 | 28 | 而待测编码的wpl就是利用每个编码的字符串长度,乘以每个字符的权值得到; 29 | 问题2: 30 | 思路是构造一个二叉树出来,模拟huffman树。 31 | 1.让每个编码遍历树,结束时在当前结点设置标记为1; 32 | 2.如果遍历时,未结束时碰到了标记为1的结点,则不是前缀编码; 33 | 3.结束时,未碰到标记点(包括最后一个),是前缀编码。 34 | */ 35 | int main() 36 | { 37 | int n, i, val; 38 | char ch; 39 | cin >> n; 40 | int *sample = new int[n]; //每个字符权值存储在这里; 41 | Heap *H = Init_Heap(n); //初始化小根堆(利用静态链表的逻辑结构); 42 | for (i = 0; i < n; i++) 43 | { 44 | cin >> ch >> val; 45 | sample[i] = val; 46 | Insert_Heap(H, val); //把元素依次插入小根堆; 47 | } 48 | int best_wpl = Cal_Wpl(H); //计算huffman编码的wpl; 49 | 50 | int m, wpl, re; //re是用来判断是否前缀编码,是为1,否为0; 51 | cin >> m; 52 | for (i = 0; i < m; i++) 53 | { 54 | wpl = wpl_prefix(sample, n, re); //计算待测编码的wpl及判断是否为前缀编码; 55 | if (wpl == best_wpl && re == 1) 56 | cout << "Yes" << endl; 57 | else 58 | cout << "No" << endl; 59 | } 60 | delete sample; 61 | 62 | return 0; 63 | } 64 | 65 | Heap *Init_Heap(int n) 66 | { 67 | Heap *H = new Heap; 68 | H->data = new int[n + 1]; //堆的下标从1开始(为了操作方便); 69 | H->data[0] = -1; //小根堆赋值最小值; 70 | 71 | return H; 72 | } 73 | 74 | void Insert_Heap(Heap *H, int x) //把元素依次插入小根堆; 75 | { 76 | int i = ++(H->size); 77 | for (; H->data[i / 2] > x; i /= 2) //从下往上过滤; 78 | H->data[i] = H->data[i / 2]; 79 | H->data[i] = x; 80 | 81 | return; 82 | } 83 | 84 | int Delmin_Heap(Heap *H) //删除小根堆中的最小元素; 85 | { 86 | int t = H->data[H->size--]; 87 | int min = H->data[1]; 88 | int pa, chi; 89 | for (pa = 1; pa * 2 <= H->size; pa = chi) //从上往下过滤最小元素; 90 | { 91 | chi = pa * 2; 92 | if (chi != H->size && H->data[chi + 1] < H->data[chi]) //找到子结点的最小下标; 93 | chi++; 94 | if (t < H->data[chi]) 95 | break; 96 | else 97 | H->data[pa] = H->data[chi]; 98 | } 99 | H->data[pa] = t; //赋值最小元素 100 | 101 | return min; 102 | } 103 | 104 | int Cal_Wpl(Heap *H) //计算huffman编码的wpl; 105 | { 106 | int sum = 0; 107 | if (H->size > 1) 108 | { 109 | int i, t1, t2, t; 110 | int m = H->size; 111 | for (i = 1; i < m; i++) 112 | { 113 | t1 = Delmin_Heap(H); //模拟构造huffman树的过程,先取出两个最小值,相加,把和插入堆中; 114 | t2 = Delmin_Heap(H); 115 | t = t1 + t2; 116 | Insert_Heap(H, t); 117 | sum += t; 118 | } 119 | } 120 | else 121 | sum = H->data[0]; 122 | 123 | return sum; 124 | } 125 | 126 | int wpl_prefix(int *sample, int n, int &re) //计算待测编码的wpl及判断是否为前缀编码; 127 | { 128 | int i, j, len, wpl = 0; 129 | char ch; 130 | string st; 131 | cnode *phead = new cnode; 132 | cnode *p = phead; 133 | re = 1; 134 | for (i = 0; i < n; i++) 135 | { 136 | cin >> ch >> st; //此处计算wpl; 137 | len = st.length(); 138 | wpl += len*sample[i]; 139 | 140 | if (re != 0) //此处判断是否前缀编码; 141 | { 142 | for (j = 0; j < len; j++) 143 | { 144 | if (st[j] == '0') //0的话判断左边; 145 | { 146 | if (p->left == nullptr) //左边空,新建结点; 147 | { 148 | cnode *q = new cnode; 149 | p->left = q; 150 | } 151 | else 152 | { 153 | if (p->tag == 1) 154 | { 155 | re = 0; 156 | break; 157 | } 158 | } 159 | p = p->left; 160 | } 161 | else if (st[j] == '1') //判断右边; 162 | { 163 | if (p->right == nullptr) 164 | { 165 | cnode *q = new cnode; 166 | p->right = q; 167 | } 168 | else 169 | { 170 | if (p->tag == 1) 171 | { 172 | re = 0; 173 | break; 174 | } 175 | } 176 | p = p->right; 177 | } 178 | } 179 | 180 | if (p->left == nullptr && p->right == nullptr) 181 | re = 1; 182 | else 183 | re = 0; 184 | if (p->tag == 0) //注意此处需要判断,最后结点标记不为1才能赋值(待测编码有可能有相同的); 185 | p->tag = 1; 186 | else 187 | re = 0; 188 | 189 | p = phead; 190 | } 191 | } 192 | 193 | return wpl; 194 | } 195 | -------------------------------------------------------------------------------- /05-树8 堆中的路径.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define Min -10001; 4 | struct Heap 5 | { 6 | int *data; 7 | int size; 8 | }; 9 | 10 | Heap *Create(int N); //建小顶堆; 11 | void Insert(Heap *H, int t); //插入元素; 12 | void Print(Heap *H, int d); //打印路径; 13 | 14 | int main() 15 | { 16 | int N, M, i, t; 17 | cin >> N >> M; 18 | Heap *H = Create(N); 19 | for (i = 0; i < N; i++) 20 | { 21 | cin >> t; 22 | Insert(H, t); 23 | } 24 | for (i = 0; i < M; i++) 25 | { 26 | cin >> t; 27 | Print(H, t); 28 | } 29 | 30 | return 0; 31 | } 32 | 33 | Heap *Create(int N) 34 | { 35 | Heap *H = new Heap; 36 | H->data = new int[N + 1]; //堆都是从下标1的位置开始存储; 37 | H->size = 0; 38 | H->data[0] = Min; 39 | 40 | return H; 41 | } 42 | 43 | void Insert(Heap *H, int t) 44 | { 45 | int i = ++H->size; //先插入最后一个位置, 然后依次往上过滤; 46 | for (i = H->size; t < H->data[i / 2]; i /= 2) 47 | H->data[i] = H->data[i / 2]; 48 | H->data[i] = t; 49 | } 50 | 51 | void Print(Heap *H, int d) 52 | { 53 | int i; 54 | cout << H->data[d]; 55 | for (i = d / 2; i > 0; i /= 2) 56 | cout << ' ' << H->data[i]; 57 | cout << endl; 58 | 59 | return; 60 | } 61 | -------------------------------------------------------------------------------- /05-树9 File Transfer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int *Create(int n); //创建静态链表; 5 | int FindRoot(int *co, int d); //查找根结点; 6 | void Union(int *co, int root1, int root2); //合并 7 | void CheckCon(int *co); //检查是否连通; 8 | void Insert(int *co); //将两个连通; 9 | void CheckNet(int *co, int n); //检查整个连通网; 10 | 11 | //思路:考察并查集操作; 12 | int main() 13 | { 14 | int n; 15 | char ch; 16 | cin >> n; 17 | int *co = Create(n); 18 | do 19 | { 20 | cin >> ch; 21 | switch(ch) 22 | { 23 | case 'C':CheckCon(co); break; 24 | case 'I':Insert(co); break; 25 | case 'S':CheckNet(co, n); break; 26 | } 27 | } while (ch != 'S'); 28 | 29 | return 0; 30 | } 31 | 32 | int *Create(int n) 33 | { 34 | int i; 35 | int *co = new int[n+1]; //下标表示编号, 值表示父结点; 36 | for (i = 0; i <= n; i++) //每个结点根结点值为-1,表示各结点独立; 37 | co[i] = -1; 38 | 39 | return co; 40 | } 41 | 42 | int FindRoot(int *co, int d) //找到根结点; 43 | { 44 | if (co[d] < 0) 45 | return d; 46 | else 47 | return co[d] = FindRoot(co, co[d]); //表示将所有子结点均指向一个总根,用到了路径压缩思想;以缩减查找规模; 48 | } 49 | 50 | void CheckCon(int *co) //检查连通性; 51 | { 52 | int t1, t2; 53 | cin >> t1 >> t2; 54 | int root1 = FindRoot(co, t1); 55 | int root2 = FindRoot(co, t2); 56 | 57 | if (root1 == root2) 58 | cout << "yes" << endl; 59 | else 60 | cout << "no" << endl; 61 | 62 | return; 63 | } 64 | 65 | void Union(int *co, int root1, int root2) //合并; 66 | { 67 | if (co[root1] < co[root2]) // 用到了按秩归并, 把小树并到大树上; 68 | { 69 | co[root1] += co[root2]; 70 | co[root2] = root1; 71 | } 72 | else 73 | { 74 | co[root2] += co[root1]; 75 | co[root1] = root2; 76 | } 77 | 78 | return; 79 | } 80 | 81 | void Insert(int *co) 82 | { 83 | int t1, t2; 84 | cin >> t1 >> t2; 85 | int root1 = FindRoot(co, t1); 86 | int root2 = FindRoot(co, t2); 87 | if (root1 != root2) 88 | Union(co, root1, root2); 89 | 90 | return; 91 | } 92 | 93 | void CheckNet(int *co, int n) 94 | { 95 | int i, cnt = 0; 96 | for (i = 1; i <= n; i++) 97 | { 98 | if (co[i] < 0) 99 | cnt++; 100 | } 101 | 102 | if (cnt == 1) 103 | cout << "The network is connected." << endl; 104 | else 105 | printf("There are %d components.\n", cnt); 106 | 107 | return; 108 | } 109 | -------------------------------------------------------------------------------- /06-图1 列出连通集.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | #define MaxV 11 5 | int G[MaxV][MaxV] = { 0 }; //全局变量; 6 | int visited[MaxV] = { 0 }; //存储结点是否访问过; 7 | 8 | void BuildG(int e); //建立图; 9 | void ListDfs(int v); //DFS遍历输出; 10 | void Dfs(int n, int v); //DFS遍历结点值; 11 | void InitVisited(int v); //初始化为0; 12 | void ListBfs(int v); //BFS遍历输出; 13 | void Bfs(int n, int v); //BFS遍历结点值; 14 | 15 | /* 16 | 思路:考虑到要按照从小到大的顺序遍历输出,结构用邻接矩阵(邻接表不方便,要用小根堆才能实现)。 17 | 1.建立图(用二维数组表示), 依次读入各边; 18 | 2.DFS遍历输出; 19 | 3.BFS遍历输出; 20 | */ 21 | int main() 22 | { 23 | int v, e; 24 | cin >> v >> e; 25 | BuildG(e); 26 | ListDfs(v); 27 | InitVisited(v); 28 | ListBfs(v); 29 | 30 | return 0; 31 | } 32 | 33 | void BuildG(int e) 34 | { 35 | int i, v1, v2; 36 | for (i = 0; i < e; i++) 37 | { 38 | cin >> v1 >> v2; 39 | G[v1][v2] = G[v2][v1] = 1; 40 | } 41 | 42 | return; 43 | } 44 | 45 | void ListDfs(int v) 46 | { 47 | int i; 48 | for (i = 0; i < v; i++) 49 | { 50 | if (!visited[i]) 51 | { 52 | cout << "{ "; 53 | Dfs(i, v); 54 | cout << '}' << endl; 55 | } 56 | } 57 | 58 | return; 59 | } 60 | 61 | void Dfs(int n, int v) 62 | { 63 | int i; 64 | visited[n] = 1; 65 | cout << n << ' '; 66 | for (i = 0; i < v; i++) //递归实现; 67 | { 68 | if (!visited[i] && G[n][i]) 69 | Dfs(i, v); 70 | } 71 | 72 | return; 73 | } 74 | 75 | void InitVisited(int v) 76 | { 77 | for (int i = 0; i < v; i++) 78 | visited[i] = 0; 79 | 80 | return; 81 | } 82 | 83 | void ListBfs(int v) 84 | { 85 | for (int i = 0; i < v; i++) 86 | { 87 | if (!visited[i]) 88 | { 89 | cout << "{ "; 90 | Bfs(i, v); 91 | cout << '}' << endl; 92 | } 93 | } 94 | 95 | return; 96 | } 97 | 98 | void Bfs(int n, int v) 99 | { 100 | int tv; 101 | queue Q; 102 | cout << n << ' '; 103 | visited[n] = 1; 104 | Q.push(n); 105 | while (!Q.empty()) //队列实现; 106 | { 107 | tv = Q.front(); 108 | Q.pop(); 109 | for (int i = 0; i < v; i++) 110 | { 111 | if (!visited[i] && G[tv][i]) 112 | { 113 | cout << i << ' '; 114 | visited[i] = 1; 115 | Q.push(i); 116 | } 117 | } 118 | } 119 | 120 | return; 121 | } 122 | -------------------------------------------------------------------------------- /06-图2 Saving James Bond - Easy Version.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include //使用平方和开方函数; 3 | #include 4 | using namespace std; 5 | #define MinD 42.5 6 | 7 | struct Point //存储点坐标; 8 | { 9 | int x, y; 10 | int visited = 0; 11 | }; 12 | 13 | double Distance(const Point a, const Point b); //计算两点距离; 14 | void Build_array(vector &pv, int n); //保存每个点的数组; 15 | void Create_first(vector &pv, vector &f, int n, int D); //处理第一次; 16 | void Search_dfs(vector &pv, int i, int D, int N); //dfs递归; 17 | 18 | /* 19 | 把每个点存入一维数组,递归两点距离是否满足即可; 20 | */ 21 | int main() 22 | { 23 | vector pv; 24 | vector Firstp; 25 | int N, D; 26 | cin >> N >> D; 27 | Build_array(pv, N); 28 | 29 | if (D >= MinD) 30 | { 31 | cout << "Yes" << endl; 32 | return 0; 33 | } 34 | Create_first(pv, Firstp, N, D); 35 | if (Firstp.empty()) 36 | { 37 | cout << "No" << endl; 38 | return 0; 39 | } 40 | 41 | for (int i = 0; i < (int)Firstp.size(); i++) 42 | Search_dfs(pv, Firstp[i], D, N); 43 | cout << "No" << endl; 44 | 45 | return 0; 46 | } 47 | 48 | double Distance(const Point a, const Point b) 49 | { 50 | return(sqrt(pow((a.x - b.x), 2) + pow((a.y - b.y), 2))); 51 | } 52 | 53 | void Build_array(vector &pv, int n) 54 | { 55 | Point t; 56 | for (int i = 0; i < n; i++) 57 | { 58 | cin >> t.x >> t.y; 59 | pv.push_back(t); 60 | } 61 | 62 | return; 63 | } 64 | 65 | void Create_first(vector &pv, vector &f, int n, int D) 66 | { 67 | Point O; 68 | O.x = O.y = 0; 69 | for (int i = 0; i < n; i++) 70 | { 71 | if (Distance(pv[i], O) <= (D + 7.5)) 72 | f.push_back(i); 73 | } 74 | 75 | return; 76 | } 77 | 78 | void Search_dfs(vector &pv, int i, int D, int N) 79 | { 80 | pv[i].visited = 1; 81 | if ((50 - abs(pv[i].x) <= D) || (50 - abs(pv[i].y) <= D)) 82 | { 83 | cout << "Yes" << endl; 84 | exit(0); 85 | } 86 | for (int j = 0; j < N; j++) 87 | { 88 | if (!pv[j].visited && Distance(pv[i], pv[j]) <= D) 89 | Search_dfs(pv, j, D, N); 90 | } 91 | 92 | return; 93 | } 94 | -------------------------------------------------------------------------------- /06-图3 六度空间.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include //用做队列容器; 3 | #define MaxN 10001 4 | using namespace std; 5 | 6 | struct Enode //定义边; 7 | { 8 | int v1, v2; 9 | }; 10 | struct Avnode //定义邻接表的邻接点; 11 | { 12 | int data; 13 | Avnode * next; 14 | }; 15 | struct Ahead //定义邻接表的头结点;也可以不定义结构,这里是为了方便封装; 16 | { 17 | Avnode *phead = nullptr; 18 | }; 19 | struct Graph //定义图的结构; 20 | { 21 | int nv; 22 | int ne; 23 | Ahead ah[MaxN]; 24 | }; 25 | int visited[MaxN] = { 0 }; //存储结点是否访问; 26 | 27 | Graph *Init_Graph(int vnum); //初始化图; 28 | void Insert_E(Graph *G, Enode *E); //把边的关系插入图中; 29 | Graph *Build_G(); //建立图; 30 | void OutputE(Graph *G); //输出边; 31 | int BFS(Graph *G, int v); //广度遍历; 32 | 33 | int main() 34 | { 35 | Graph * G = Build_G(); //建立图; 36 | OutputE(G); //输出边; 37 | 38 | 39 | return 0; 40 | } 41 | 42 | Graph *Init_Graph(int vnum) //初始化的图只有顶点,没有边; 43 | { 44 | Graph *G = new Graph; 45 | G->nv = vnum; 46 | G->ne = 0; 47 | 48 | return G; 49 | } 50 | 51 | void Insert_E(Graph *G, Enode *E) 52 | { 53 | Avnode *nAv = new Avnode; 54 | nAv->data = E->v2; 55 | nAv->next = G->ah[E->v1].phead; //注意指针; 56 | G->ah[E->v1].phead = nAv; 57 | 58 | Avnode *nAv2 = new Avnode; //无向图两边都要插入; 59 | nAv2->data = E->v1; 60 | nAv2->next = G->ah[E->v2].phead; 61 | G->ah[E->v2].phead = nAv2; 62 | 63 | return; 64 | } 65 | 66 | Graph *Build_G() //建立图; 67 | { 68 | int tnv; 69 | Enode *E = new Enode; 70 | cin >> tnv; 71 | Graph *G = Init_Graph(tnv); 72 | cin >> G->ne; 73 | for (int i = 0; i < G->ne; i++) 74 | { 75 | cin >> E->v1 >> E->v2; 76 | Insert_E(G, E); 77 | } 78 | 79 | return G; 80 | } 81 | 82 | void OutputE(Graph *G) 83 | { 84 | int cnt; 85 | for (int i = 1; i <= G->nv; i++) 86 | { 87 | cnt = BFS(G, i); 88 | 89 | for (int j = 1; j <= G->nv; j++) //这里需要初始化; 90 | visited[j] = 0; 91 | 92 | printf("%d: %.2f%%\n", i, (float)cnt * 100 / G->nv); 93 | } 94 | 95 | return; 96 | } 97 | 98 | int BFS(Graph *G, int v) //广度遍历; 99 | { 100 | visited[v] = 1; 101 | int cnt = 1; 102 | queue Q; 103 | int last = v; 104 | Q.push(v); 105 | 106 | int tail, level = 0; //tail是每一层最后一个压入的点; 107 | Avnode *w; 108 | while (!Q.empty()) 109 | { 110 | v = Q.front(); 111 | Q.pop(); 112 | for (w = G->ah[v].phead; w; w = w->next) 113 | { 114 | if (!visited[w->data]) 115 | { 116 | visited[w->data] = 1; 117 | cnt++; 118 | tail = w->data; 119 | Q.push(w->data); 120 | } 121 | } 122 | if (v == last) //当弹出的结点和最后压入的点相同时,代表该层遍历完毕,切入下一层; 123 | { 124 | level++; 125 | last = tail; 126 | } 127 | if (level == 6) 128 | break; 129 | } 130 | 131 | return cnt; 132 | } 133 | -------------------------------------------------------------------------------- /07-图4 哈利·波特的考试.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | #define Inf 65535 5 | #define Mlen 101 6 | int G[Mlen][Mlen]; 7 | 8 | /* 9 | 思路:这是最短路径问题。 10 | 稠密图,数据结构采用邻接矩阵。 11 | 用Floyd算法求出任两点间的最短路径; 12 | 然后找出一点到其余点的路径最大值; 13 | 再找出这些最大值的最小值; 14 | */ 15 | void Init_G(int G[][Mlen], int N, int M); //初始化图; 16 | void Floyd(int G[][Mlen], int N); //floyd算法; 17 | int Find_Max(int G[][Mlen], int row, int N); //找出一点到其余点的路径最大值; 18 | 19 | int main() 20 | { 21 | int N, M; 22 | cin >> N >> M; 23 | Init_G(G, N, M); 24 | Floyd(G, N); 25 | 26 | int num, t, min_len = Mlen; 27 | for (int i = 1; i <= N; i++) //找出路径最大值的最小值; 28 | { 29 | t = Find_Max(G, i, N); 30 | if (t == Inf) 31 | { 32 | cout << 0 << endl; 33 | return 0; 34 | } 35 | if (t < min_len) 36 | { 37 | num = i; 38 | min_len = t; 39 | } 40 | } 41 | cout << num << ' ' << min_len << endl; 42 | 43 | return 0; 44 | } 45 | 46 | void Init_G(int G[][Mlen], int N, int M) 47 | { 48 | for (int i = 1; i <= N; i++) 49 | { 50 | for (int j = 1; j <= N; j++) 51 | { 52 | if (i == j) 53 | G[i][j] = 0; //0表示无边; 54 | else 55 | G[i][j] = Inf; //最大值表示两点不可达; 56 | } 57 | } 58 | 59 | int a, b, v; 60 | for (int i = 0; i < M; i++) //读入数据,赋值; 61 | { 62 | cin >> a >> b >> v; 63 | G[a][b] = G[b][a] = v; 64 | } 65 | 66 | return; 67 | } 68 | 69 | void Floyd(int G[][Mlen], int N) //floyd算法; 70 | { 71 | for (int k = 1; k <= N; k++) 72 | { 73 | for (int i = 1; i <= N; i++) 74 | { 75 | for (int j = 1; j <= N; j++) 76 | { 77 | if (G[i][k] + G[k][j] < G[i][j]) 78 | G[i][j] = G[i][k] + G[k][j]; 79 | } 80 | } 81 | } 82 | 83 | return; 84 | } 85 | 86 | int Find_Max(int G[][Mlen], int row, int N) //找出一点到其余点的路径最大值; 87 | { 88 | int max = 0; 89 | for (int i = 1; i <= N; i++) 90 | { 91 | max = max < G[row][i] ? G[row][i] : max; 92 | } 93 | 94 | return max; 95 | } 96 | -------------------------------------------------------------------------------- /07-图5 Saving James Bond - Hard Version: -------------------------------------------------------------------------------- 1 | #include 2 | #include //使用sort()函数; 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | struct Node 8 | { 9 | int x, y; //点坐标; 10 | double distance; //存储每点到原点的距离; 11 | }; 12 | 13 | /* 14 | 思路:问题核心是无向图单源最短路径问题,所以算法采用BFS了; 15 | 需解决: 16 | 1. 单独处理第一跳。题目要求存在多个最短时,输出第一跳的距离最小,所以我们可以把所有点距原点距离从小到大排序, 17 | 然后再对各点进行BFS。 18 | 2.路径输出的话,只有采用栈了。 19 | */ 20 | double Distance(Node a, Node b); //求两点距离; 21 | void Init_data(vector &np, int N); //读入数据 22 | void Fir_Step(vector &fp, vector &np, int N, int ra); //处理第一跳; 23 | bool inc_cmp(const Node &ta, const Node &tb); //sort()函数的compare函数; 24 | void bfs(int v, vector &np, int N, int ra); //BFS; 25 | int IsBorder(vector &np, int v, int ra); //判断从该点能否跳到岸上; 26 | void Print(int *path, int x, vector &np); //递归输出; 27 | 28 | int main() 29 | { 30 | vector np; 31 | vector fp; //用来存储第一跳符合要求的点的编号; 32 | int ra, N, tN; 33 | cin >> tN >> ra; 34 | Init_data(np, tN); 35 | N = np.size(); 36 | Fir_Step(fp, np, N, ra);//处理第一跳; 37 | 38 | if (ra > 42) 39 | cout << 1 << endl; // 此处是直接跳到岸上,输出1,不用输出点坐标(没有踩,输出啥); 40 | else 41 | { 42 | for (int i = 0; i < (int)fp.size(); i++) //第一跳的每点bfs; 43 | bfs(i, np, N, ra); 44 | cout << 0 << endl; 45 | } 46 | 47 | return 0; 48 | } 49 | 50 | double Distance(Node a, Node b) //求两点距离; 51 | { 52 | return(sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2))); 53 | } 54 | 55 | void Init_data(vector &np, int N) //读入数据; 56 | { 57 | Node tem; 58 | int t1, t2; 59 | double d; 60 | for (int i = 0; i < N; i++) 61 | { 62 | cin >> t1 >> t2; 63 | d = sqrt(t1*t1 + t2*t2); 64 | if (max(abs(t1), abs(t2)) >= 50 || max(abs(t1), abs(t2)) < 8) //此处是为了淘汰掉那些不在水中的点; 65 | continue; 66 | tem.x = t1; 67 | tem.y = t2; 68 | tem.distance = d; 69 | np.push_back(tem); 70 | } 71 | 72 | return; 73 | } 74 | 75 | void Fir_Step(vector &fp, vector &np, int N, int ra)//处理第一跳; 76 | { 77 | sort(np.begin(), np.end(), inc_cmp); //对距离进行升序排序; 78 | 79 | for (int i = 0; i < N; i++) 80 | { 81 | if (np[i].distance <= (ra + 7.5)) //fp里存储符合要求的第一跳的点编号; 82 | fp.push_back(i); 83 | else 84 | break; 85 | } 86 | 87 | return; 88 | } 89 | 90 | bool inc_cmp(const Node &ta, const Node &tb) 91 | { 92 | return(ta.distance < tb.distance); 93 | } 94 | 95 | void bfs(int v, vector &np, int N, int ra) 96 | { 97 | int *path = new int[N]; //存储路径,表示从起点v到i的上一个结点; 98 | for (int i = 0; i < N; i++) 99 | path[i] = -1; //初始为-1,表示无父结点; 100 | int *dist = new int[N]; //存储路径长度; 101 | for (int i = 0; i < N; i++) 102 | { 103 | if (i == v) 104 | dist[i] = 1; //相等,表示路径为1(因为我们是从小岛上跳过来的) 105 | else 106 | dist[i] = 0; 107 | } 108 | queue Q; 109 | 110 | int x, flag = 0; 111 | Q.push(v); 112 | while (!Q.empty()) 113 | { 114 | x = Q.front(); 115 | Q.pop(); 116 | if (IsBorder(np, x, ra)) //判断从该点能否跳到岸上; 117 | { 118 | flag = 1; 119 | break; 120 | } 121 | else 122 | { 123 | for (int i = 0; i < N; i++) 124 | { 125 | if (dist[i] == 0 && Distance(np[x], np[i]) <= ra) 126 | { 127 | path[i] = x; 128 | dist[i] = dist[x] + 1; 129 | Q.push(i); 130 | } 131 | } 132 | } 133 | } 134 | 135 | if (flag) 136 | { 137 | cout << dist[x] + 1<< endl; 138 | Print(path, x, np); 139 | exit(0); 140 | } 141 | 142 | return; 143 | } 144 | 145 | int IsBorder(vector &np, int v, int ra) //判断从该点能否跳到岸上; 146 | { 147 | if (50 - abs(np[v].x) <= ra || 50 - abs(np[v].y) <= ra) 148 | return 1; 149 | else 150 | return 0; 151 | } 152 | 153 | void Print(int *path, int x, vector &np) 154 | { 155 | if (path[x] != -1) 156 | Print(path, path[x], np); 157 | cout << np[x].x << ' ' << np[x].y << endl; 158 | 159 | return; 160 | } 161 | -------------------------------------------------------------------------------- /07-图6 旅游规划.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include //用到min(); 3 | using namespace std; 4 | #define MaxN 501 5 | struct Node //结点定义; 6 | { 7 | int di; 8 | int fee; 9 | }; 10 | struct Graph 11 | { 12 | Node Ma[MaxN][MaxN]; 13 | int Nv; 14 | int Ne; 15 | }; 16 | 17 | /* 18 | 思路:dijikstra算法求无向图的单源最短路径; 19 | 数据结构用邻接矩阵; 20 | */ 21 | void Init_G(Graph *G, int &c1, int &c2); //初始化图; 22 | void Dijkstra(Graph *G, int &c1, int &c2, int *dist, int *cost, int *col); 23 | int FindMin(Graph *G, int *dist, int *col); //找到剩余点中的最小路径; 24 | 25 | int main() 26 | { 27 | Graph *G = new Graph; 28 | int c1, c2; 29 | Init_G(G, c1, c2); //初始化图; 30 | int *dist = new int[G->Nv]; //存储路径长度; 31 | int *cost = new int[G->Nv]; //存储路径费用; 32 | int *col = new int[G->Nv]; //记录最短路径的点; 33 | Dijkstra(G, c1, c2, dist, cost, col); 34 | 35 | delete[] dist; 36 | delete[] cost; 37 | delete[] col; 38 | delete G; 39 | return 0; 40 | } 41 | 42 | void Init_G(Graph *G, int &c1, int &c2) 43 | { 44 | int n, m, i, j; 45 | cin >> n >> m >> c1 >> c2; 46 | G->Nv = n; 47 | G->Ne = m; 48 | int t1, t2, d1, co1; 49 | 50 | for (i = 0; i < n; i++) 51 | { 52 | for (j = 0; j < n; j++) //矩阵初始化为最大值; 53 | { 54 | G->Ma[i][j].di = G->Ma[j][i].di = MaxN; 55 | G->Ma[i][j].fee = G->Ma[j][i].fee = MaxN; 56 | } 57 | } 58 | for (i = 0; i < m; i++) //注意题目中的是无向图; 59 | { 60 | cin >> t1 >> t2 >> d1 >> co1; 61 | G->Ma[t1][t2].di = G->Ma[t2][t1].di = d1; 62 | G->Ma[t1][t2].fee = G->Ma[t2][t1].fee = co1; 63 | } 64 | 65 | return; 66 | } 67 | 68 | void Dijkstra(Graph *G, int &c1, int &c2, int *dist, int *cost, int *col) 69 | { 70 | int i; 71 | for (i = 0; i < G->Nv; i++) 72 | { 73 | dist[i] = G->Ma[c1][i].di; 74 | cost[i] = G->Ma[c1][i].fee; 75 | col[i] = 0; 76 | } 77 | dist[c1] = 0; 78 | col[c1] = 1; //先收录起点; 79 | int minv; 80 | while (1) 81 | { 82 | minv = FindMin(G, dist, col); 83 | if (minv == -1) 84 | break; 85 | col[minv] = 1; 86 | for (i = 0; i < G->Nv; i++) 87 | { 88 | if (col[i] == 0) 89 | { 90 | if (dist[minv] + G->Ma[minv][i].di < dist[i]) 91 | { 92 | dist[i] = dist[minv] + G->Ma[minv][i].di; 93 | cost[i] = cost[minv] + G->Ma[minv][i].fee; 94 | } 95 | else if (dist[minv] + G->Ma[minv][i].di == dist[i]) //长度相等,判断费用大小; 96 | cost[i] = min(cost[minv] + G->Ma[minv][i].fee, cost[i]); 97 | } 98 | } 99 | } 100 | 101 | cout << dist[c2] << ' ' << cost[c2] << endl; 102 | 103 | return; 104 | } 105 | 106 | int FindMin(Graph *G, int *dist, int *col) 107 | { 108 | int mindi = MaxN; 109 | int i, minv; 110 | for (i = 0; i < G->Nv; i++) 111 | { 112 | if (col[i] == 0 && dist[i] < mindi) 113 | { 114 | mindi = dist[i]; 115 | minv = i; 116 | } 117 | } 118 | if (mindi < MaxN) 119 | return minv; 120 | else 121 | return -1; //不存在返回-1; 122 | } 123 | -------------------------------------------------------------------------------- /08-图7 公路村村通.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #define MaxN 1002 4 | #define inf 65535 //不可达的最大值。 5 | int G[MaxN][MaxN]; //冒充下邻接矩阵; 6 | int dist[MaxN]; //未收录的点到已生成的生成树中的点的最短路长度; 7 | 8 | /* 9 | 思路:Prim算法。结构是邻接矩阵。 10 | 但要比真正的Prim算法简略,因为题目只要输出总权值,所以我们就不用 11 | 同时建立最小生成树,只需要累加边权值。 12 | */ 13 | void Init_G(int N, int M); //初始化并读入数据,构造邻接矩阵; 14 | int Prim(int N); 15 | int FindMin(int N); //找到未收录点到生成树的最小边权值; 16 | 17 | int main() 18 | { 19 | int N, M, wt; 20 | cin >> N >> M; 21 | Init_G(N, M); 22 | wt = Prim(N); 23 | cout << wt << endl; 24 | 25 | return 0; 26 | } 27 | 28 | void Init_G(int N, int M) //初始化并读入数据,构造邻接矩阵; 29 | { 30 | int i, j; 31 | for (i = 1; i <= N; i++) //初始化矩阵; 32 | { 33 | for (j = 1; j <= N; j++) 34 | { 35 | if (i == j) 36 | G[i][j] = 0; 37 | else 38 | G[i][j] = G[j][i] = inf; 39 | } 40 | } 41 | 42 | int s, d, wt; 43 | for (i = 0; i < M; i++) 44 | { 45 | cin >> s >> d >> wt; 46 | G[s][d] = G[d][s] = wt; 47 | } 48 | 49 | return; 50 | } 51 | 52 | int Prim(int N) 53 | { 54 | int i, v, sumw, vcnt; 55 | sumw = 0; 56 | vcnt = 1; 57 | for (i = 1; i <= N; i++) //点1作为起点; 58 | dist[i] = G[1][i]; //初始化为到点1的长度; 59 | 60 | while (1) 61 | { 62 | v = FindMin(N); 63 | if (v == -1) 64 | break; 65 | sumw += dist[v]; 66 | dist[v] = 0; //收录进生成树,不为0表示不是生成树的点; 67 | vcnt++; 68 | for (i = 1; i <= N; i++) 69 | { 70 | if (dist[i] && G[v][i] < inf) //更新因收录v而使得其他未收录点到生成树的最短长度; 71 | { 72 | if (G[v][i] < dist[i]) 73 | dist[i] = G[v][i]; 74 | } 75 | } 76 | } 77 | 78 | if (vcnt < N) 79 | return -1; 80 | else 81 | return sumw; 82 | } 83 | 84 | int FindMin(int N) 85 | { 86 | int min, minv, i; 87 | min = inf; 88 | for (i = 1; i <= N; i++) 89 | { 90 | if (dist[i] && dist[i] < min) 91 | { 92 | min = dist[i]; 93 | minv = i; 94 | } 95 | } 96 | if (min == inf) //顶点不存在; 97 | return -1; 98 | else 99 | return minv; 100 | } 101 | -------------------------------------------------------------------------------- /08-图8 How Long Does It Take.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | #define MaxN 100 5 | /* 6 | 思路:关键路径的变形,即找出最长路径长度。 7 | 算法:拓扑排序; 8 | 数据结构:邻接表; 9 | */ 10 | 11 | struct Edge //邻接表的边定义; 12 | { 13 | int v1, v2; 14 | int wt; 15 | }; 16 | struct Ajnode //邻接点; 17 | { 18 | int ajn; //结点值; 19 | int wt; //权值; 20 | Ajnode *next = nullptr; 21 | }; 22 | struct Ahead //边表头结点; 23 | { 24 | Ajnode *first = nullptr; 25 | }; 26 | struct Graph 27 | { 28 | int nv, ne; 29 | Ahead ah[MaxN]; 30 | }; 31 | 32 | Graph *Init_G(int N); //初始化构造邻接表; 33 | void Insert_G(Graph *G, Edge e); //插入邻接表边; 34 | Graph *Build_G(); //建图; 35 | void Topsort(Graph *G); //拓扑排序; 36 | 37 | int main() 38 | { 39 | Graph *G = Build_G(); //建图; 40 | Topsort(G); //拓扑排序; 41 | 42 | return 0; 43 | } 44 | 45 | Graph *Init_G(int N) 46 | { 47 | Graph *G = new Graph; //初始化顶点数; 48 | G->nv = N; 49 | 50 | return G; 51 | } 52 | 53 | void Insert_G(Graph *G, Edge e) //插入邻接表边; 54 | { 55 | Ajnode *aj = new Ajnode; 56 | aj->wt = e.wt; 57 | aj->ajn = e.v2; 58 | aj->next = G->ah[e.v1].first; 59 | G->ah[e.v1].first = aj; 60 | 61 | return; 62 | } 63 | 64 | Graph *Build_G() //建图; 65 | { 66 | int N, i; 67 | cin >> N; 68 | Graph *G = Init_G(N); 69 | Edge te; 70 | cin >> G->ne; 71 | 72 | for (i = 0; i < G->ne; i++) 73 | { 74 | cin >> te.v1 >> te.v2 >> te.wt; 75 | Insert_G(G, te); 76 | } 77 | 78 | return G; 79 | } 80 | 81 | void Topsort(Graph *G) //拓扑排序; 82 | { 83 | int N = G->nv; 84 | int i; 85 | Ajnode *w; 86 | int Indegree[MaxN] = { 0 }; //存储顶点的入度,初始化0; 87 | for (i = 0; i < N; i++) 88 | { 89 | for (w = G->ah[i].first; w; w = w->next) 90 | Indegree[w->ajn]++; //统计入度; 91 | } 92 | 93 | queue Q; 94 | for (i = 0; i < N; i++) //将入度0的点压入队列; 95 | { 96 | if (Indegree[i] == 0) 97 | Q.push(i); 98 | } 99 | 100 | int tn, cnt, cptime[MaxN] = { 0 }; //cptime[]统计顶点代表事件完成的时间最大值; 101 | cnt = 0; //统计弹出的顶点数,小于总数,表示图不连通; 102 | while (!Q.empty()) 103 | { 104 | tn = Q.front(); 105 | Q.pop(); 106 | cnt++; 107 | 108 | for (w = G->ah[tn].first; w; w = w->next) //处理每个顶点的邻接点; 109 | { 110 | if (cptime[tn] + w->wt > cptime[w->ajn]) //更新时间最大值; 111 | cptime[w->ajn] = cptime[tn] + w->wt; 112 | if(--Indegree[w->ajn] == 0) //入度为0,压入; 113 | Q.push(w->ajn); 114 | } 115 | } 116 | 117 | if (cnt != N) 118 | cout << "Impossible" << endl; 119 | else 120 | { 121 | int t = -1; 122 | for (i = 0; i < N; i++) 123 | { 124 | if (cptime[i] > t) 125 | t = cptime[i]; 126 | } 127 | cout << t << endl; 128 | } 129 | 130 | return; 131 | } 132 | -------------------------------------------------------------------------------- /08-图9 关键活动.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include //使用max(), min(); 4 | using namespace std; 5 | #define MaxN 101 6 | #define inf 65535 7 | /* 8 | 思路: 核心是关键路径, 算法--拓扑排序, 结构--邻接矩阵; 9 | 1.正向拓扑一次,得出最早完成时间; 10 | 2.逆向拓扑一次,得出最晚完成时间; 11 | 3.两者之差等于两点的权值,即为关键边; 12 | */ 13 | 14 | struct Graph //定义邻接矩阵; 15 | { 16 | int nv, ne; 17 | int G[MaxN][MaxN]; 18 | }; 19 | int early[MaxN] = { 0 }; 20 | int latest[MaxN]; 21 | int indeg[MaxN] = { 0 }; //入度值; 22 | int outdeg[MaxN] = { 0 }; //出度值; 23 | 24 | void Init_G(Graph *Mg); //初始化矩阵; 25 | int Topsort(Graph *Mg); //正向拓扑; 26 | void Back_Tops(Graph *Mg, int m_wt); //逆向拓扑 27 | 28 | int main() 29 | { 30 | Graph *Mg = new Graph; 31 | Init_G(Mg); 32 | int m_wt = Topsort(Mg); //关键路径长度; 33 | 34 | int i, j; 35 | if (m_wt == -1) //有环跳出; 36 | cout << 0 << endl; 37 | else 38 | { 39 | cout << m_wt << endl; 40 | Back_Tops(Mg, m_wt); 41 | for (i = 1; i <= Mg->nv; i++) //逆序输出; 42 | { 43 | for (j = Mg->nv; j > 0; j--) 44 | { 45 | if (Mg->G[i][j] && Mg->G[i][j] < inf) 46 | { 47 | if (early[i] == latest[j] - Mg->G[i][j]) //两者之差等于两点的权值,即为关键边; 48 | cout << i << "->" << j << endl; 49 | } 50 | } 51 | } 52 | } 53 | 54 | delete[] Mg; 55 | return 0; 56 | } 57 | 58 | void Init_G(Graph *Mg) //初始化矩阵; 59 | { 60 | cin >> Mg->nv >> Mg->ne; 61 | int i, j; 62 | for (i = 1; i <= Mg->nv; i++) 63 | { 64 | for (j = 1; j <= Mg->nv; j++) //开始赋值为无穷; 65 | { 66 | if (i == j) 67 | Mg->G[i][j] = 0; 68 | else 69 | Mg->G[i][j] = Mg->G[j][i] = inf; 70 | } 71 | latest[i] = inf; 72 | } 73 | 74 | int s, d, wt; 75 | for (i = 0; i < Mg->ne; i++) //读入数据; 76 | { 77 | cin >> s >> d >> wt; 78 | Mg->G[s][d] = wt; 79 | indeg[d]++; 80 | outdeg[s]++; 81 | } 82 | 83 | return; 84 | } 85 | 86 | int Topsort(Graph *Mg) //正向拓扑; 87 | { 88 | int i; 89 | queue Q; 90 | 91 | for (i = 1; i <= Mg->nv; i++) 92 | { 93 | if (indeg[i] == 0) //将入度0的点压入队列; 94 | Q.push(i); 95 | } 96 | 97 | int v, cnt = 0; 98 | while (!Q.empty()) 99 | { 100 | v = Q.front(); 101 | Q.pop(); 102 | cnt++; 103 | 104 | for (i = 1; i <= Mg->nv; i++) 105 | { 106 | if (Mg->G[v][i] && Mg->G[v][i] < inf) //边存在; 107 | { 108 | early[i] = max(early[i], early[v] + Mg->G[v][i]); 109 | if (--indeg[i] == 0) 110 | Q.push(i); 111 | } 112 | } 113 | } 114 | 115 | if (cnt < Mg->nv) //表示有环; 116 | return -1; 117 | else 118 | { 119 | int t = 0; 120 | for (i = 1; i <= Mg->nv; i++) 121 | t = max(t, early[i]); 122 | return t; 123 | } 124 | } 125 | 126 | void Back_Tops(Graph *Mg, int m_wt) //逆向拓扑 127 | { 128 | int i; 129 | queue Q; 130 | 131 | for (i = 1; i <= Mg->nv; i++) 132 | { 133 | if (outdeg[i] == 0) 134 | { 135 | Q.push(i); 136 | latest[i] = m_wt; 137 | } 138 | } 139 | 140 | int v; 141 | while (!Q.empty()) 142 | { 143 | v = Q.front(); 144 | Q.pop(); 145 | for (i = 1; i <= Mg->nv; i++) 146 | { 147 | if (Mg->G[i][v] && Mg->G[i][v] < inf) 148 | { 149 | latest[i] = min(latest[i], latest[v] - Mg->G[i][v]); 150 | if (--outdeg[i] == 0) 151 | Q.push(i); 152 | } 153 | } 154 | } 155 | 156 | return; 157 | } 158 | -------------------------------------------------------------------------------- /09-排序1 排序.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | void shell(int *A, int n);//希尔排序; 5 | 6 | int main() 7 | { 8 | int i, n; 9 | cin >> n; 10 | int *list = new int[n+1]; 11 | for (i = 1; i <= n; i++) 12 | cin >> list[i]; 13 | shell(list, n); 14 | for (i = 1; i <= n; i++) 15 | { 16 | if (i == n) 17 | cout << list[i] << endl; 18 | else 19 | cout << list[i] << ' '; 20 | } 21 | return 0; 22 | } 23 | 24 | void shell(int *A, int n) 25 | { 26 | int i, j, d; 27 | for (d = n / 2; d > 0; d /= 2) 28 | { 29 | for (i = d+1; i <= n; i ++) 30 | { 31 | if (A[i] < A[i - d]) 32 | { 33 | A[0] = A[i]; 34 | for (j = i - d; j>0 && A[0] 2 | #include 3 | using namespace std; 4 | 5 | void Print(int a[], int n); 6 | int Is_Insert(int a[], int b[], int n); 7 | void Merge(int *b, int n); 8 | int Get_L(int *b, int n); //求出归并段长度; 9 | 10 | /* 11 | 思路:先判断是否插入,若不是执行归并。 12 | 归并的话先求出归并段长度。 13 | 本代码最后两个测试点未通过,冏~ 14 | */ 15 | int main() 16 | { 17 | int n, i; 18 | cin >> n; 19 | int *A = new int[n]; 20 | int *B = new int[n]; 21 | for (i = 0; i < n; i++) 22 | cin >> A[i]; 23 | for (i = 0; i < n; i++) 24 | cin >> B[i]; 25 | int d = Is_Insert(A, B, n); 26 | if (d) 27 | Merge(B, n); 28 | 29 | delete[] A, B; 30 | 31 | return 0; 32 | } 33 | 34 | void Print(int a[], int n) 35 | { 36 | for (int i = 0; i < n; i++) 37 | { 38 | if (i != n - 1) 39 | cout << a[i] << ' '; 40 | else 41 | cout << a[i] << endl; 42 | } 43 | } 44 | 45 | int Is_Insert(int a[], int b[], int n) 46 | { 47 | int i, t, m; 48 | int flag = 1; 49 | for (i = 1; i < n - 1; i++) 50 | { 51 | if (flag && b[i] > b[i + 1]) 52 | { 53 | flag = 0; 54 | t = i; 55 | } 56 | if (!flag && b[i + 1] != a[i + 1]) 57 | return 1; 58 | } 59 | 60 | cout << "Insertion Sort" << endl; 61 | m = b[t + 1]; 62 | for (i = t; i >= 0 && b[i] > m; i--) 63 | b[i + 1] = b[i]; 64 | b[i + 1] = m; 65 | Print(b, n); 66 | 67 | return 0; 68 | } 69 | 70 | int Get_L(int *b, int n) 71 | { 72 | int i, j; 73 | for (i = 2; i <= n/2; i *= 2) 74 | { 75 | for (j = i; j < n; j += i) 76 | { 77 | if (b[j - 1] > b[j]) 78 | return i; 79 | } 80 | } 81 | 82 | return n; 83 | } 84 | 85 | void Merge(int *b, int n) 86 | { 87 | int i, d = 0; 88 | 89 | d = Get_L(b, n); 90 | d *= 2; 91 | for (i = 0; i <= n - d; i += d) //利用快排求; 92 | sort(b + i, b + i + d - 1); 93 | if (i + d / 2 < n) 94 | sort(b + i, b + n - 1); 95 | cout << "Merge Sort" << endl; 96 | Print(b, n); 97 | 98 | return; 99 | } 100 | -------------------------------------------------------------------------------- /09-排序3 Insertion or Heap Sort.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int Is_Insert(int *a, int *b, int n); //判断是否插入; 5 | void Print(int *b, int n); //输出序列; 6 | void HeapSort(int *b, int n); //堆排; 7 | void AdjustDown(int *b, int n); //把根结点向下调整,使之有序; 8 | 9 | /* 10 | 思路:先判断是否插入。 11 | 堆的话找到待排序位置,执行一次调整就ok; 12 | 注意,一个测试点(最小N,heap)未通过; 13 | */ 14 | int main() 15 | { 16 | int n, i; 17 | cin >> n; 18 | int *A = new int[n + 1]; 19 | int *B = new int[n + 1]; 20 | for (i = 1; i <= n; i++) 21 | cin >> A[i]; 22 | for (i = 1; i <= n; i++) 23 | cin >> B[i]; 24 | 25 | int flag = Is_Insert(A, B, n); //判断是否插入; 26 | if (!flag) 27 | HeapSort(B, n); //堆排; 28 | 29 | delete[] A, B; 30 | return 0; 31 | } 32 | 33 | int Is_Insert(int *a, int *b, int n) 34 | { 35 | int j, i, x; 36 | for (i = 1; i < n; i++) 37 | { 38 | if (b[i] > b[i + 1]) 39 | { 40 | x = i + 1; 41 | if (i == 1 && a[1] != b[1]) //堆排; 42 | return 0; 43 | break; 44 | } 45 | } 46 | if (i == n) //序列有序,是堆排; 47 | return 0; 48 | b[0] = b[x]; 49 | for (j = i; b[j] > b[0]; j--) //插入调整; 50 | b[j + 1] = b[j]; 51 | b[j + 1] = b[0]; 52 | cout << "Insertion Sort" << endl; 53 | Print(b, n); 54 | return 1; 55 | } 56 | 57 | void Print(int *b, int n) 58 | { 59 | int i; 60 | for (i = 1; i <= n; i++) 61 | { 62 | if (i == n) 63 | cout << b[i] << endl; 64 | else 65 | cout << b[i] << ' '; 66 | } 67 | return; 68 | } 69 | 70 | void HeapSort(int *b, int n) 71 | { 72 | int i; 73 | for (i = n; b[i] > b[1]; i--); 74 | if (i > 1) 75 | { 76 | swap(b[1], b[i]); //找到位置,交换; 77 | i--; 78 | AdjustDown(b, i); //调整,使堆为最大堆; 79 | } 80 | cout << "Heap Sort" << endl; 81 | Print(b, n); 82 | 83 | return; 84 | } 85 | 86 | void AdjustDown(int *b, int n) //把根结点向下调整,使之有序; 87 | { 88 | int x = b[1]; 89 | int pa, ch; 90 | for (pa = 1; pa * 2 <= n; pa = ch) 91 | { 92 | ch = pa * 2; 93 | if (ch != n && b[ch] < b[ch + 1]) 94 | ch++; 95 | if (x >= b[ch]) 96 | break; 97 | else 98 | b[pa] = b[ch]; 99 | } 100 | b[pa] = x; 101 | 102 | return; 103 | } 104 | -------------------------------------------------------------------------------- /10-排序4 统计工龄.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | /* 5 | 建一个工龄数组,统计人数,类似桶排序的思想。 6 | */ 7 | int main() 8 | { 9 | int A[51] = { 0 }; 10 | int N, i, t, max = 0; 11 | cin >> N; 12 | for (i = 0; i < N; i++) 13 | { 14 | cin >> t; 15 | A[t]++; 16 | if (t > max) 17 | max = t; 18 | } 19 | for (i = 0; i <= max; i++) 20 | { 21 | if (A[i]) 22 | cout << i << ':' << A[i] << endl; 23 | } 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /10-排序5 PAT Judge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | #include 4 | struct Node 5 | { 6 | int id; 7 | int pbm[6]; //问题个数; 8 | int tscre; //总分; 9 | int fcnt; //满分个数; 10 | int fflag; //是否通过编译标志位; 11 | }; 12 | 13 | /* 14 | 核心写好快排的比较函数; 15 | 最后一个测试点未通过; 16 | */ 17 | static bool cmp(const Node &a, const Node &b); 18 | void Print(Node *stu, int n, int k); 19 | int main() 20 | { 21 | //freopen("in.txt", "r", stdin); 22 | int N, K, M, i, j; 23 | cin >> N >> K >> M; 24 | Node *stu = new Node[N + 1]; 25 | for (i = 0; i <= N; i++) //数组初始化; 26 | { 27 | stu[i].tscre = stu[i].fcnt = stu[i].fflag = 0; 28 | for (j = 0; j <= K; j++) 29 | stu[i].pbm[j] = -1; 30 | } 31 | 32 | int *scr = new int[K + 1]; //每个问题总分; 33 | for (i = 1; i <= K; i++) 34 | scanf("%d", &scr[i]); 35 | 36 | int t1, t2, t3, d; 37 | for (i = 0; i < M; i++) 38 | { 39 | scanf("%d %d %d", &t1, &t2, &t3); 40 | if (t3 > -1) 41 | stu[t1].fflag = 1; //置标志位; 42 | stu[t1].id = t1; 43 | t3 = t3 > -1 ? t3 : 0; //若得分-1,更改为0; 44 | if (stu[t1].pbm[t2] != -1) 45 | d = t3 - stu[t1].pbm[t2]; //判断一个题多次提交,计入的分数; 46 | else 47 | d = t3; //第一次提交; 48 | 49 | if (d > 0) 50 | { 51 | stu[t1].tscre += d; 52 | stu[t1].pbm[t2] = t3; 53 | if (t3 == scr[t2]) //此处会过滤掉多次得满分的情况; 54 | stu[t1].fcnt++; 55 | } 56 | } 57 | 58 | stu[0].tscre = -1; //数组第一个初始化,用来比较; 59 | sort(stu + 1, stu + N + 1, cmp); 60 | Print(stu, N, K); 61 | 62 | delete[] stu, scr; 63 | return 0; 64 | } 65 | 66 | bool cmp(const Node &a, const Node &b) 67 | { 68 | if (a.tscre != b.tscre) 69 | return a.tscre > b.tscre; 70 | else 71 | { 72 | if (a.fcnt != b.fcnt) 73 | return a.fcnt > b.fcnt; 74 | else 75 | return a.id < b.id; 76 | } 77 | } 78 | 79 | void Print(Node *stu, int n, int k) 80 | { 81 | int i, j, flag; 82 | for (i = 1; i <= n; i++) 83 | { 84 | if (stu[i].fflag) 85 | { 86 | if (stu[i].tscre != stu[i - 1].tscre) 87 | { 88 | flag = i; 89 | printf("%d ", flag); 90 | } 91 | else 92 | printf("%d ", flag); 93 | 94 | printf("%05d %d", stu[i].id, stu[i].tscre); 95 | for (j = 1; j <= k; j++) 96 | { 97 | if (stu[i].pbm[j] != -1) 98 | printf(" %d", stu[i].pbm[j]); 99 | else 100 | printf(" -"); 101 | } 102 | printf("\n"); 103 | } 104 | 105 | } 106 | 107 | return; 108 | } 109 | -------------------------------------------------------------------------------- /10-排序6 Sort with Swap(0, i).cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | /* 5 | 思路:最少的交换次数,即每次交换,有一个元素放到正确位置。 6 | 用A[0](不能是0)和下标是A[0]的元素交换,直到A[0]为0.此时 7 | 要判断所以元素是否是在正确位置。 8 | 如果不是,就让A[0]和这个元素交换。 9 | 这个位置如何选取?从下标1的位置开始扫描即可。 10 | */ 11 | void Swap(int *a, int *b); //交换; 12 | int FirstNot(int *A, int begin, int end); //寻找第一个不等的元素; 13 | int main() 14 | { 15 | //freopen("in.txt", "r", stdin); 16 | int N, i, cnt = 0; 17 | cin >> N; 18 | int *A = new int[N]; 19 | for (i = 0; i < N; i++) 20 | cin >> A[i]; 21 | 22 | int cur = FirstNot(A, 1, N - 1); //寻找第一个不等的元素; 23 | while (cur != 0) 24 | { 25 | if (A[0] == 0) //未交换完; 26 | { 27 | Swap(A, A + cur); 28 | cnt++; 29 | } 30 | 31 | while (A[0] != 0) 32 | { 33 | Swap(A, A + A[0]); 34 | cnt++; 35 | } 36 | cur = FirstNot(A, cur, N - 1); 37 | } 38 | cout << cnt << endl; 39 | 40 | return 0; 41 | } 42 | 43 | void Swap(int *a, int *b) 44 | { 45 | int t = *a; 46 | *a = *b; 47 | *b = t; 48 | } 49 | 50 | int FirstNot(int *A, int begin, int end) 51 | { 52 | for (int i = begin; i <= end; i++) 53 | { 54 | if (A[i] != i) 55 | return i; 56 | } 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /11-散列1 电话聊天狂人.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include //字符串处理函数; 4 | #define MAX 1000000 5 | using namespace std; 6 | 7 | struct Node //散列链表结点; 8 | { 9 | char data[12]; 10 | Node *next; 11 | int cnt; 12 | }; 13 | struct HashT //散列表; 14 | { 15 | int size; 16 | Node *ht; //散列表表头数组; 17 | }; 18 | 19 | /* 20 | 思路:为了提高速度,用散列结构(分离链接法)。 21 | 取号码后5位作为关键字。 22 | 注意:不能用cpp的string容器,其会超时,只有用c的char了。 23 | */ 24 | int Hash(int k, int p); //hash函数; 25 | HashT *Create(int N); //新表; 26 | int MinPrime(int N); //散列表的大小,比总数大的最小质数; 27 | Node *FindPos(HashT *T, char *key, int &pos); //查找结点; 28 | void Insert(HashT *T, char *key); //插入结点; 29 | void Output(HashT *T); 30 | int main() 31 | { 32 | //freopen("in.txt", "r", stdin); 33 | int N, i; 34 | char key[12]; 35 | cin >> N; 36 | HashT *T = Create(N * 2); 37 | for (i = 0; i < N; i++) //读入数据; 38 | { 39 | cin >> key; 40 | Insert(T, key); 41 | cin >> key; 42 | Insert(T, key); 43 | } 44 | Output(T); 45 | 46 | return 0; 47 | } 48 | 49 | int Hash(int k, int p) 50 | { 51 | return k%p; 52 | } 53 | int MinPrime(int N) 54 | { 55 | int t = (N % 2) ? N + 2 : N + 1; 56 | while (t < MAX) 57 | { 58 | int i = (int)sqrt(t); 59 | for (i; i > 2; i--) 60 | { 61 | if (t%i == 0) 62 | break; 63 | } 64 | if (i == 2) break; 65 | else t += 2; 66 | } 67 | return t; 68 | } 69 | 70 | HashT *Create(int N) 71 | { 72 | HashT *T = new HashT; 73 | T->size = MinPrime(N); 74 | T->ht = new Node[T->size]; 75 | for (int i = 0; i < T->size; i++) 76 | { 77 | T->ht[i].cnt = 0; 78 | T->ht[i].data[0] = '\0'; 79 | T->ht[i].next = NULL; 80 | } 81 | 82 | return T; 83 | } 84 | Node *FindPos(HashT *T, char *key, int &pos) 85 | { 86 | pos = Hash(atoi(key+6), T->size); 87 | Node *p = T->ht[pos].next; 88 | while (p && strcmp(p->data, key)) 89 | p = p->next; 90 | 91 | return p; 92 | } 93 | void Insert(HashT *T, char *key) 94 | { 95 | int pos; 96 | Node *p = FindPos(T, key, pos); 97 | if (!p) 98 | { 99 | Node *newn = new Node; 100 | newn->next = T->ht[pos].next; 101 | T->ht[pos].next = newn; 102 | newn->cnt = 1; 103 | strcpy(newn->data, key); 104 | } 105 | else 106 | p->cnt++; 107 | 108 | return; 109 | } 110 | void Output(HashT *T) //遍历散列表,找最大值; 111 | { 112 | int i, maxn, partner; 113 | Node *p; 114 | char re[12]; 115 | maxn = partner = 0; 116 | for (i = 0; i < T->size; i++) 117 | { 118 | p = T->ht[i].next; 119 | while (p) 120 | { 121 | if (maxn < p->cnt) 122 | { 123 | maxn = p->cnt; 124 | partner = 1; 125 | strcpy(re, p->data); 126 | } 127 | else if (maxn == p->cnt) 128 | { 129 | partner++; 130 | if (strcmp(re, p->data)>0) strcpy(re, p->data); 131 | } 132 | p = p->next; 133 | } 134 | } 135 | if (partner == 1) 136 | printf("%s %d\n", re, maxn); 137 | else 138 | printf("%s %d %d\n", re, maxn, partner); 139 | 140 | return; 141 | } 142 | -------------------------------------------------------------------------------- /11-散列2 Hashing.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define MAX 1000000 4 | using namespace std; 5 | 6 | //散列法-除留余数, 冲突用平方(正的)探测; 7 | int MinPrime(int n); 8 | void Output(int *t, int n, int size); 9 | int main() 10 | { 11 | int M, N; 12 | cin >> M >> N; 13 | int tsize = MinPrime(M); 14 | int *table = new int[tsize]; 15 | for (int i = 0; i < tsize; i++) table[i] = 0; 16 | Output(table, N, tsize); 17 | 18 | delete[] table; 19 | return 0; 20 | } 21 | int MinPrime(int n) //取得散列表大小; 22 | { 23 | int i, p; 24 | if (n < 3) return 2; 25 | p = n % 2 ? n : n + 1; 26 | while (p < MAX) 27 | { 28 | for (i = (int)sqrt(p); i > 2; i--) 29 | { 30 | if (p %i == 0) break; 31 | } 32 | if (i == 2) break; 33 | else p += 2; 34 | } 35 | 36 | return p; 37 | } 38 | void Output(int *t, int n, int size) 39 | { 40 | int i, j, data, pos; 41 | int half = size / 2; 42 | for (i = 0; i < n; i++) 43 | { 44 | if (i == 0) //先输出第一个; 45 | { 46 | cin >> data; 47 | pos = data % size; 48 | t[pos] = 1; 49 | cout << pos; 50 | } 51 | else 52 | { 53 | cin >> data; 54 | pos = data % size; 55 | j = 1; 56 | while (t[pos] && j <= half) //平方探测的j值<= 表长的一半; 57 | { 58 | pos = (data + j*j) % size; 59 | j++; 60 | } 61 | if (!t[pos]) 62 | { 63 | cout << ' ' << pos; 64 | t[pos] = 1; 65 | } 66 | else cout << " -"; 67 | } 68 | } 69 | cout << endl; 70 | 71 | return; 72 | } 73 | -------------------------------------------------------------------------------- /11-散列3 QQ帐户的申请与登陆.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | //这里取了个巧, 用了STL中的map。应该是用分离链表法进行散列的 7 | //散列函数用除留余数法,从号码第四位起作为关键字; 8 | int main() 9 | { 10 | map mymap; 11 | char a; 12 | string num, pw; 13 | int i, n; 14 | cin >> n; 15 | for (i = 0; i < n; i++) 16 | { 17 | cin >> a >> num >> pw; 18 | if (a == 'L') 19 | { 20 | if (mymap.find(num) == mymap.end()) 21 | cout << "ERROR: Not Exist" << endl; 22 | else if (mymap[num] != pw) 23 | cout << "ERROR: Wrong PW" << endl; 24 | else 25 | cout << "Login: OK" << endl; 26 | } 27 | else if (a == 'N') 28 | { 29 | if (mymap.find(num) != mymap.end()) 30 | cout << "ERROR: Exist" << endl; 31 | else 32 | { 33 | mymap.insert(make_pair(num, pw)); 34 | cout << "New: OK" << endl; 35 | } 36 | } 37 | 38 | } 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /11-散列4 Hashing - Hard Version.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define MAX 1001 5 | using namespace std; 6 | 7 | /* 8 | 思路:拓扑排序(哭晕了)。冲突说明关键字和该处的有关,可表示一条有向边; 9 | 冲突次数即该点的入度, 散列数组下标看作结点号; 10 | 不冲突时,按照字典序(从小到大)输出,用优先队列; 11 | 邻接表用二维vector模拟; 12 | */ 13 | int key[MAX], indg[MAX]; 14 | struct Inc_cmp 15 | { 16 | bool operator()(int a, int b) //优先队列的比较函数 17 | { 18 | return key[a] > key[b]; 19 | } 20 | }; 21 | 22 | int main() 23 | { 24 | int n, i, j, ka;//ka是散列地址; 25 | priority_queue, Inc_cmp> Q;//优先队列 26 | cin >> n; 27 | vector > G(n);//邻接表; 28 | for (i = 0; i < n; i++) 29 | { 30 | cin >> key[i]; 31 | ka = key[i] % n; 32 | 33 | if (key[i] > 0) 34 | { 35 | indg[i] = (i + n - ka) % n; //计算入度; 36 | 37 | if (indg[i] == 0) 38 | Q.push(i); 39 | else 40 | { 41 | for (j = 0; j < indg[i]; j++) 42 | G[(ka + j) % n].push_back(i);//结点i加入到(ka + j) % n代表的头结点对应的邻接点; 43 | } 44 | } 45 | } 46 | 47 | int t, cnt = 0; 48 | vector T(n);//保存拓扑的散列地址下标; 49 | while (!Q.empty()) 50 | { 51 | t = Q.top(); 52 | Q.pop(); 53 | T[cnt++] = t; 54 | for (j = 0; j < (int)G[t].size(); j++) 55 | { 56 | if (--indg[G[t][j]] == 0) 57 | Q.push(G[t][j]); 58 | } 59 | } 60 | 61 | for (i = 0; i < cnt; i++)//输出; 62 | { 63 | if (i == 0) 64 | cout << key[T[i]]; 65 | else 66 | cout << ' ' << key[T[i]]; 67 | } 68 | cout << endl; 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZJU_MOOC_DS 2 | 中国大学MOOC-陈越、何钦铭-数据结构-2016秋 3 | http://www.icourse163.org/learn/ZJU-93001?tid=1001757011#/learn/announce 4 | --------------------------------------------------------------------------------