CS106B笔记
CS106B笔记
织Recursion
- 关于recursion,CS106B给出了一个很好的模板。
- self-similar 问题用递归解决是一个良好方向。
1
2
3
4
5
6
7
8
9
10
11
12if (The problem is very simple) {
Directly solve the problem.
Return the solution.
} else {
Split the problem into one or more
smaller problems with the same
structure as the original.
Solve each of those smaller problems.
Combine the results to get the overall
Solution.
Return the overall solution.
} - backtracking在课程和作业中也有体现
1
2
3
4
5
6
7
8
9
10
11if (problem is sufficiently simple) {
return whether the problem is solvable
} else {
for (each choice) {
try out that choice
if (that choice leads to success) {
return success;
}
}
return failure;
} - cs106b中对利用BFS的一个问题给出的思路 # Sorting
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17create an empty queue
for (each water source at or below the water level)
{
flood that square;
add that square to the queue;
}
while (the queue is not empty)
{
dequeue a position from the front of the queue;
for (each square adjacent to the position in a cardinal direction)
{
if (that square is at or below the water level and isn't yet flooded) {
flood that square;
add that square to the queue;
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18//selection sorting
void selectionSort(Vector<int>& elems) {
for (int index = 0; index < elems.size(); index++) {
int smallestIndex = indexOfSmallest(elems, index);
swap(elems[index], elems[smallestIndex]);
}
}
int indexOfSmallest(const Vector<int>& elems, int startPoint)
{
int smallestIndex = startPoint;
for (int i = startPoint + 1; i < elems.size(); i++) {
if (elems[i] < elems[smallestIndex]) {
smallestIndex = i;
}
}
return smallestIndex;
}
1 | //Insertion Sort |
1 | //Merge Sort |
1 | 二分 |
Class
- Create a header file (typically suffixed with .h) describing what operations the class can perform and what internal state it needs.
- Create an implementation file (typically suffixed with .cpp) that contains the implementation of the class.
- Clients of the class can then include the header file to use the
class.
1
2
3
4
5
6
7
8
9
10
11//Example
class RandomBag {
public:
void add(int value);
int removeRandom();
bool isEmpty() const;
int size() const;
private:
Vector<int> elems;
}; - 主要部分
- Member variables (What subvariables make up this new variable type?)
- These are the variables stored within the classUsually not accessible outside the class implementation
- Member functions (What functions can you call on a variable of this
type?)
- Functions you can call on the object。
- Known as methods
- Constructor (What happens when you make a new instance of this
type?)
- Gets called when you create the object
- Sets the initial state of each new object
Dynamic Memory Allocation
概念性的如stack and heap
Types like Vector, Map, Set, etc. that store a variable number of items need space to store those elements.
When you use those types as a client, they just “work” and somehow figure out where to store things. You as the end user don’t see how.
Internally, those types use a technique called dynamic memory allocation to get space in RAM where they can put their elements.
1
2
3string* ptr = new string[3];
//Anything created with new[] persists until explicitly cleaned up.
delete[] ptr;使用C++自身的variables 和parameters 会自动处理内存分配和释放
但是使用new[]的不会,需要手动处理,防止内存泄漏,使用delete[] # Hash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20int nameHash(string first, string last){
/* This hashing scheme needs two prime numbers, a large prime and a small
* prime. These numbers were chosen because their product is less than
* 2^31 - kLargePrime - 1.
*/
static const int kLargePrime = 16908799;
static const int kSmallPrime = 127;
int hashVal = 0;
/* Iterate across all the characters in the first name, then the last
* name, updating the hash at each step.
*/
for (char ch: first + last) {
/* Convert the input character to lower case. The numeric values of
* lower-case letters are always less than 127.
*/
ch = tolower(ch);
hashVal = (kSmallPrime * hashVal + ch) % kLargePrime;
}
return hashVal;
}This is a hash function. It’s a type of function somesmart math and CS people came up with.
problem: 不同输入通过哈希函数可能有相同输出
Application:Map Set
1
2
3
4
5
6
7
8
9
10
11//Linear Probing
- To check if an element exists in the table:
Compute the hash code of the element.
Jump to that location in the table.
Scan forward – wrapping around if necessary – until the item or an empty slot is found.
- To insert an element into the table:
If the item already exists, do nothing.
Otherwise, jump to the slot given by the hash code of the element. Walk forward – wrapping around if necessary – until a blank spot or tombstone slot is found. Then, put the item there.
- To remove an element from the table:
Jump to the slot given by the hash code of the element.
Walk forward – wrapping around if necessary – until the item or and empty slot is found. If the item is found, replace it with a tombstone.
1 | //Robin Hood Hashing |
Linked Lists
1 | struct Node { |
1 | void prependTo(Node*& list, const string& value) { |
1 | //Doubly-Linked Lists |
Tree
- BST
- Binary tree (each node has 0, 1, or 2 children)
- For a node with value X:
- All nodes in its left subtree must be less than X
- All nodes in its right subtree must be greater than X
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28struct Node {
Type value;
Node* left; // Smaller values
Node* right; // Bigger values
};
/*
• Pre-order traversal
• In-order traversal
• Post-order traversal
*/
// Free tree
void freeTree(TreeNode* node) {
if (node == nullptr) {
return;
}
freeTree(node->left);
freeTree(node->right);
delete node;
}
//Balance
• A BST is balanced if its height is O(log n), where n is the number of nodes in the tree
• Theorem: If you start with an empty tree and add in random values, then with high probability the tree is balanced
• A self-balancing BST reshapes itself on insertions and deletions to
stay balanced (how to do this is beyond the scope of this class)
Graph
1 | // BFS |
碎碎念
本人学习cs的路程是先上了CS50,然后开始的CS106B。从个人体验上来讲,CS106B的作业质量很高,比起cs50难度跨越也更大。
一定一定要看对应作业的Slide,我学的是2022年的,2022年的作业许多内容都可以从Slide中找到对应的提示,其他年的Slide也可以看看,相当不错。
在课程学习的个人体会上,结合作业相关的提示,编写一个看起来仿佛可以的伪代码似乎并不是一个困难的事情,但伪代码的翻译相当的困难,还是代码写少了。
发现个人的问题是,一是看的,写的代码太少了,经常性的卡在一些细节性问题,或用一种很傻的方法去处理。二是编写的伪代码的架构问题,经常性的不足以把题目拆分清楚,解决好。
后续学习需要针对这两方面需要解决。