Retranslate the complete English edition from Simplified Chinese (#2010)

* Retranslate the complete English edition from Simplified Chinese

* Polish three English explanations after reader-focused review
This commit is contained in:
Yudong Jin
2026-10-31 03:35:51 +08:00
committed by GitHub
parent ef46e2ed95
commit 14c314c08c
1502 changed files with 29459 additions and 23517 deletions

View File

@@ -1,134 +1,28 @@
# Contributing guidelines for Chinese-to-English
# Contributing to the English edition
We are working on translating "Hello Algo" from Chinese to English with the following approach:
Help make *Hello Algo* accurate, clear, and enjoyable for readers learning data structures and algorithms. Corrections to explanations, terminology, code comments, examples, and links are welcome.
1. **AI translation**: Carry out an initial pass of translations using large language models.
2. **Human optimization**: Manually refine the machine-generated outputs to ensure authenticity and accuracy.
3. **Pull request review**: The optimized translation will be double checked by the reviewers through GitHub pull request workflow.
4. Repeat steps `2.` and `3.` for further improvements.
For the general contribution workflow, see [Contributing](https://www.hello-algo.com/en/chapter_appendix/contribution/). You can use the edit button on a book page for a small correction, or fork the repository, make and test your changes locally, and submit a pull request.
<img width="650" alt="translation_pipeline" src="https://github.com/user-attachments/assets/201930ef-723e-4179-b670-e5a084a8211e">
## Translating and reviewing a chapter
## Join us
Use the current Simplified Chinese source as the authority for meaning. Read the complete passage and its examples before changing a sentence. The English should convey the full explanation in natural English, including qualifications and assumptions.
We're seeking contributors who meet the following criteria.
1. Translate the complete document, including headings, tables, figure captions, callouts, questions, and code comments. Preserve the algorithms, example data, formulas, links, and code references.
2. Compare the English with the Chinese, checking technical meaning, completeness, terminology, and the steps in each example.
3. Read the English on its own. Make it clear and natural for a beginner, then check any revisions against the Chinese again.
4. Ask another reviewer to check the whole document in context. Resolve differences in interpretation before treating the translation as ready.
- **Technical background**: Strong foundation in computer science, particularly in data structures and algorithms.
- **Language skills**: Native proficiency in Chinese with professional-level English, or native English.
- **Available time**: Dedicated to contributing to open-source projects with a willingness to engage in long-term translation efforts.
Use clear American English and sentence case for headings. Prefer direct explanations to word-for-word renderings of Chinese sentence structure. Use the same term consistently, and distinguish concepts such as full, perfect, and complete binary trees by their definitions. See the [terminology table](https://www.hello-algo.com/en/chapter_appendix/terminology/) for reference.
That is, our contributors are computer scientists, engineers, and students from different linguistic backgrounds, and their objectives have different focal points:
If the Chinese source appears incorrect or ambiguous, describe the issue in the pull request. A translation should not silently change the algorithm or introduce a new technical claim. Likewise, keep example strings unchanged when they are program data, even if those strings contain Chinese characters.
- **Native Chinese with professional working English**: Ensuring translation accuracy and consistency between CN and EN versions.
- **Native English**: Enhance the authenticity and fluency of the English content to flow naturally and to be engaging.
## Checking the result
> [!note]
> If you are interested in joining us, don't hesitate to contact me via krahetx@gmail.com or WeChat `krahets-jyd`.
>
> We use this [Notion page](https://hello-algo.notion.site/chinese-to-english) to track progress and assign tasks. Please visit it for more details.
Review the rendered page as well as the Markdown. Check that formulas, emphasis, tables, images, links, code tabs, and PythonTutor examples still work. Translate the comments and explanatory output inside PythonTutor examples without deleting explanations to shorten the links.
## Translation process
Figure and table numbers are generated during the build; keep their placeholders intact. Chapter exercise pages are also generated: changes to exercise wording belong in the source exercise data and translation inputs in the companion [workspace repository](https://github.com/krahets/hello-algo-workspace), rather than directly in the generated pages.
> [!important]
> Before diving in, ensure you're comfortable with the GitHub pull request workflow and have read the "Translation standards" and "Pseudo-code for translation" below.
Keep a pull request focused on a complete document when possible; a small correction can be smaller. Explain what changed and how you checked it. Automated checks help find missing content and structural or code changes, but do not replace a careful language review.
1. **Task assignment**: Self-assign a task in the Notion workspace.
2. **Translation**: Optimize the translation on your local PC, referring to the “Translation Pseudo-Code” section below for more details.
3. **Peer review**: Carefully review your changes before submitting a Pull Request (PR). The PR will be merged into the main branch after approval from two reviewers.
## Translation standards
> [!tip]
> **The "Accuracy" and "Authenticity" are primarily handled by native Chinese speakers and native English speakers, respectively.**
>
> In some instances, "Accuracy (consistency)" and "Authenticity" represent a trade-off, where optimizing one aspect could significantly affect the other. In such cases, please leave a comment in the pull request for discussion.
**Accuracy**:
- Maintain consistency in terminology across translations by referring to the [Terminology](https://www.hello-algo.com/chapter_appendix/terminology/) section.
- Prioritize technical accuracy and maintain the tone and style of the Chinese version.
- Always take into account the content and context of the Chinese version to ensure modifications are accurate and comprehensive.
**Authenticity**:
- Translations should flow naturally and fluently, adhering to English expression conventions.
- Always consider the context of the content to harmonize the article.
- Be aware of cultural differences between Chinese and English. For instance, Chinese "pinyin" does not exist in English.
- If the optimized sentence could alter the original meaning, please add a comment for discussion.
**Formatting**:
- Figures and tables will be automatically numbered during deployment, so DO NOT manually number them.
- Each PR should cover at least one complete document to ensure manageable review sizes, except for bug fixes.
**Review**:
- During the review, prioritize evaluating the changes, consulting the surrounding context as needed.
- Learning from each other's perspectives can lead to better translations and more cohesive results.
## Translation pseudo-code
The following pseudo-code models the steps in a typical translation process.
```python
def optimize_translation(markdown_texts, lang_skill):
"""Optimize the translation"""
for sentence in markdown_texts:
"""Accuracy is handled primarily by native Chinese speakers"""
if lang_skill is "Native Chinese + Professional working English":
if is_accurate_Chinese_to_English(sentence):
continue
# Optimize the accuracy
result = refine_accuracy(sentence)
"""
Authenticity is handled primarily by native English speakers
and secondarily by native Chinese speakers
"""
if is_authentic_English(sentence):
continue
# Optimize the authenticity
result = refine_authenticity(sentence)
# Add comments in the PR if it may break consistency
if break_consistency(result):
add_comment(description)
pull_request = submit_pull_request(markdown_texts)
# The PR will be merged after approved by >= 2 reviewers
while count_approvals(pull_request) < 2:
continue
merge(pull_request)
```
The following pseudo-code is for the reviewers:
```python
def review_pull_requests(pull_request, lang_skill):
"""Review the PR"""
# Loop through all the changes in the PR
while is_anything_left_to_review(pull_request):
change = get_next_change(pull_request)
"""Accuracy is handled primarily by native Chinese speakers"""
if lang_skill is "Native Chinese + Professional working English":
# Check the accuracy(consistency) between CN and EN versions
if is_accurate_Chinese_to_English(change):
continue
# Optimize the accuracy(consistency)
result = refine_accuracy(change)
# Add comments in the PR
add_comment(result)
"""
Authenticity is handled primarily by native English speakers
and secondarily by native Chinese speakers
"""
if is_authentic_English(change):
continue
# Optimize the authenticity if it is not authentic English
result = refine_authenticity(change)
# Add comments in the PR
add_comment(result)
approve(pull_request)
```
If you find a problem in an image, open an [issue](https://github.com/krahets/hello-algo/issues) or leave a comment describing it so the image can be updated.

View File

@@ -4,9 +4,9 @@
</p>
<p align="center">
<img style="height: 60px;" src="https://readme-typing-svg.demolab.com?font=Roboto&weight=400&duration=3500&pause=2000&color=21C8B8&center=true&vCenter=true&random=false&width=200&lines=Hello%2C+Algo!" alt="hello-algo-typing-svg" />
<img style="height: 60px;" src="https://readme-typing-svg.demolab.com?font=Noto+Sans&weight=400&duration=3500&pause=2000&color=21C8B8&center=true&vCenter=true&random=false&width=200&lines=Hello%2C+Algo+!" alt="hello-algo-typing-svg" />
</br>
Data structures and algorithms tutorial with animated illustrations and ready-to-run code
A data structures and algorithms tutorial with animated illustrations and code you can run with one click
</p>
<p align="center">
@@ -38,7 +38,7 @@
</p>
<p align="center">
<a href="https://github.com/krahets/hello-algo">简体中文</a>
<a href="https://github.com/krahets/hello-algo/blob/main/README.md">简体中文</a>
|
<a href="https://github.com/krahets/hello-algo/blob/main/zh-hant/README.md">繁體中文</a>
|
@@ -51,41 +51,37 @@
<a href="https://github.com/krahets/hello-algo/blob/main/ko/README.md">한국어</a>
</p>
## The book
## About this book
This open-source project aims to create a free and beginner-friendly crash course for data structures and algorithms.
This project aims to create a free, open-source introduction to data structures and algorithms that is accessible to beginners.
- Animated illustrations, easy-to-understand content, and a smooth learning curve help beginners explore the "knowledge map" of data structures and algorithms.
- Run code with just one click, helping readers improve their programming skills and understand the working principle of algorithms and the underlying implementation of data structures.
- Promoting learning by teaching, feel free to ask questions and share insights. Let's grow together through discussion.
- Animated illustrations throughout the book, clear explanations, and a gradual learning curve guide beginners through data structures and algorithms.
- Code that runs with one click helps readers build programming skills through practice and understand how algorithms work and how data structures are implemented.
- Readers are encouraged to learn together. Ask questions and share insights in the comments so everyone can benefit from the discussion.
If you find this book helpful, please give it a Star :star: to support us, thank you!
If you find this book helpful, please support it by clicking Star :star: at the top right of the page. Thank you!
## Endorsements
> "An easy-to-understand book on data structures and algorithms, which guides readers to learn by minds-on and hands-on. Strongly recommended for algorithm beginners!"
> “An accessible introduction to data structures and algorithms that encourages readers to learn by thinking and doing. Highly recommended for anyone new to algorithms.”
>
> **—— Junhui Deng, Professor, Department of computer science and technology, Tsinghua University**
> **— Junhui Deng, Professor, Department of Computer Science, Tsinghua University**
> "If I had 'Hello Algo' when I was learning data structures and algorithms, it would have been 10 times easier!"
> “If I had had *Hello Algo* when I was learning data structures and algorithms, it would have been ten times easier!”
>
> **—— Mu Li, Senior Principal Scientist, Amazon**
> **— Mu Li, Senior Principal Scientist, Amazon**
## Contributing
> [!Important]
>
> Welcome to contribute to Chinese-to-English translation! For more information please see [CONTRIBUTING.md](CONTRIBUTING.md).
This open-source book is continually being updated. You are welcome to join the project and help improve the learning material for readers.
This open-source book is continuously being updated, and we welcome your participation in this project to provide better learning content for readers.
- [Content corrections](https://www.hello-algo.com/en/chapter_appendix/contribution/): Help fix or report grammatical errors, missing content, ambiguous wording, broken links, and code bugs in the comments.
- [Code ports](https://github.com/krahets/hello-algo/issues/15): Contributions in different programming languages are welcome. The book supports 12 languages, including Python, Java, C++, Go, and JavaScript.
- Translation and review: Help translate and proofread the book so more readers can learn data structures and algorithms in their own language.
- [Content Correction](https://www.hello-algo.com/en/chapter_appendix/contribution/): Please help us correct or point out mistakes in the comments section such as grammatical errors, missing content, ambiguities, invalid links, or code bugs.
- [Code Transpilation](https://github.com/krahets/hello-algo/issues/15): We look forward to your contributions in various programming languages. We currently support 12 languages including Python, Java, C++, Go, and JavaScript.
- Translation Review: Welcome to contribute to multilingual translation and review work, helping more readers learn data structures and algorithms in their native languages.
Feedback and suggestions are welcome. If you have questions, open an issue or contact `krahets-jyd` on WeChat.
We welcome your valuable suggestions and feedback. If you have any questions, please submit Issues or reach out via WeChat: `krahets-jyd`.
We would like to dedicate our thanks to all the contributors of this book. It is their selfless dedication that has made this book better. They are:
Thank you to everyone who has contributed to this open-source book. Their generous efforts have made it better:
<p align="left">
<a href="https://github.com/krahets/hello-algo/graphs/contributors">

35
en/codes/Dockerfile Normal file
View File

@@ -0,0 +1,35 @@
FROM ubuntu:latest
# Use Aliyun mirrors for Ubuntu packages
RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list && \
sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list && \
sed -i 's/ports.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
RUN apt-get update && apt-get install -y wget
# Install the requested language environments
ARG LANGS
RUN for LANG in $LANGS; do \
case $LANG in \
python) \
apt-get install -y python3.10 && \
update-alternatives --install /usr/bin/python python /usr/bin/python3.10 1 ;; \
cpp) \
apt-get install -y g++ gdb ;; \
java) \
apt-get install -y openjdk-17-jdk ;; \
csharp) \
wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb && \
dpkg -i packages-microsoft-prod.deb && \
apt-get update && \
apt-get install -y dotnet-sdk-8.0 ;; \
# More languages...
*) \
echo "Warning: No installation workflow for $LANG" ;; \
esac \
done
WORKDIR /codes
COPY ./ ./
CMD ["/bin/bash"]

View File

@@ -1,8 +1,8 @@
# Ignore all
*
# Unignore all with extensions
# Unignore all files with extensions
!*.*
# Unignore all dirs
# Unignore all directories
!*/
*.dSYM/

View File

@@ -6,60 +6,60 @@
#include "../utils/common.h"
/* Random access to element */
/* Access an element at a random index */
int randomAccess(int *nums, int size) {
// Randomly select a number from interval [0, size)
// Choose a random number in [0, size)
int randomIndex = rand() % size;
// Retrieve and return the random element
// Get and return the randomly selected element
int randomNum = nums[randomIndex];
return randomNum;
}
/* Extend array length */
/* Extend the array length */
int *extend(int *nums, int size, int enlarge) {
// Initialize an array with extended length
// Initialize an array with the extended length
int *res = (int *)malloc(sizeof(int) * (size + enlarge));
// Copy all elements from the original array to the new array
for (int i = 0; i < size; i++) {
res[i] = nums[i];
}
// Initialize expanded space
// Initialize the newly added space
for (int i = size; i < size + enlarge; i++) {
res[i] = 0;
}
// Return the extended new array
// Return the new, extended array
return res;
}
/* Insert element num at index index in the array */
/* Insert element num at index `index` in the array */
void insert(int *nums, int size, int num, int index) {
// Move all elements at and after index index backward by one position
// Shift all elements at and after index `index` one position to the right
for (int i = size - 1; i > index; i--) {
nums[i] = nums[i - 1];
}
// Assign num to the element at index index
// Assign num to the element at index `index`
nums[index] = num;
}
/* Remove the element at index index */
// Note: stdio.h occupies the remove keyword
/* Remove the element at index `index` */
// Note: stdio.h already declares a function named remove
void removeItem(int *nums, int size, int index) {
// Move all elements after index index forward by one position
// Shift all elements after index `index` one position to the left
for (int i = index; i < size - 1; i++) {
nums[i] = nums[i + 1];
}
}
/* Traverse array */
/* Traverse the array */
void traverse(int *nums, int size) {
int count = 0;
// Traverse array by index
// Traverse the array by index
for (int i = 0; i < size; i++) {
count += nums[i];
}
}
/* Find the specified element in the array */
/* Find a specified element in the array */
int find(int *nums, int size, int target) {
for (int i = 0; i < size; i++) {
if (nums[i] == target)
@@ -68,12 +68,12 @@ int find(int *nums, int size, int target) {
return -1;
}
/* Driver Code */
/* Driver code */
int main() {
/* Initialize the random seed once */
/* Initialize the random seed (only once) */
srand((unsigned)time(NULL));
/* Initialize array */
/* Initialize the array */
int size = 5;
int arr[5];
printf("Array arr = ");
@@ -83,33 +83,33 @@ int main() {
printf("Array nums = ");
printArray(nums, size);
/* Insert element */
/* Random access */
int randomNum = randomAccess(nums, size);
printf("Get random element %d from nums", randomNum);
printf("Random element selected from nums: %d", randomNum);
/* Traverse array */
/* Extend the length */
int enlarge = 3;
int *res = extend(nums, size, enlarge);
size += enlarge;
printf("Extend array length to 8, resulting in nums = ");
printf("Extend the array length to 8, giving nums = ");
printArray(res, size);
/* Insert element */
/* Insert an element */
insert(res, size, 6, 3);
printf("Insert number 6 at index 3, resulting in nums = ");
printf("Insert the number 6 at index 3, giving nums = ");
printArray(res, size);
/* Remove element */
/* Remove an element */
removeItem(res, size, 2);
printf("Remove element at index 2, resulting in nums = ");
printf("Remove the element at index 2, giving nums = ");
printArray(res, size);
/* Traverse array */
/* Traverse the array */
traverse(res, size);
/* Find element */
/* Find an element */
int index = find(res, size, 3);
printf("Find element 3 in res, index = %d\n", index);
printf("Find element 3 in res; its index = %d\n", index);
/* Free memory */
free(res);

View File

@@ -14,7 +14,7 @@ void insert(ListNode *n0, ListNode *P) {
}
/* Remove the first node after node n0 in the linked list */
// Note: stdio.h occupies the remove keyword
// Note: stdio.h already declares a function named remove
void removeItem(ListNode *n0) {
if (!n0->next)
return;
@@ -26,7 +26,7 @@ void removeItem(ListNode *n0) {
free(P);
}
/* Access the node at index index in the linked list */
/* Access the node at index `index` in the linked list */
ListNode *access(ListNode *head, int index) {
for (int i = 0; i < index; i++) {
if (head == NULL)
@@ -48,40 +48,40 @@ int find(ListNode *head, int target) {
return -1;
}
/* Driver Code */
/* Driver code */
int main() {
/* Initialize linked list */
// Initialize each node
/* Initialize the linked list */
// Initialize the individual nodes
ListNode *n0 = newListNode(1);
ListNode *n1 = newListNode(3);
ListNode *n2 = newListNode(2);
ListNode *n3 = newListNode(5);
ListNode *n4 = newListNode(4);
// Build references between nodes
// Set up references between the nodes
n0->next = n1;
n1->next = n2;
n2->next = n3;
n3->next = n4;
printf("Initialized linked list is\r\n");
printf("Initial linked list:\r\n");
printLinkedList(n0);
/* Insert node */
/* Insert a node */
insert(n0, newListNode(0));
printf("Linked list after node insertion is\r\n");
printf("Linked list after inserting a node:\r\n");
printLinkedList(n0);
/* Remove node */
/* Remove a node */
removeItem(n0);
printf("Linked list after node deletion is\r\n");
printf("Linked list after removing a node:\r\n");
printLinkedList(n0);
/* Access node */
/* Access a node */
ListNode *node = access(n0, 3);
printf("Value of node at index 3 in linked list = %d\r\n", node->val);
printf("Value of the linked list node at index 3 = %d\r\n", node->val);
/* Search node */
/* Find a node */
int index = find(n0, 2);
printf("Index of node with value 2 in linked list = %d\r\n", index);
printf("Index of the linked list node with value 2 = %d\r\n", index);
// Free memory
freeMemoryLinkedList(n0);

View File

@@ -6,12 +6,12 @@
#include "../utils/common.h"
/* List class */
/* List structure */
typedef struct {
int *arr; // Array (stores list elements)
int *arr; // Array (stores the list elements)
int capacity; // List capacity
int size; // List size
int extendRatio; // List expansion multiplier
int extendRatio; // List capacity growth factor
} MyList;
void extendCapacity(MyList *nums);
@@ -32,43 +32,43 @@ void delMyList(MyList *nums) {
free(nums);
}
/* Get list length */
/* Get the list size */
int size(MyList *nums) {
return nums->size;
}
/* Get list capacity */
/* Get the list capacity */
int capacity(MyList *nums) {
return nums->capacity;
}
/* Update element */
/* Access an element */
int get(MyList *nums, int index) {
assert(index >= 0 && index < nums->size);
return nums->arr[index];
}
/* Add elements at the end */
/* Update an element */
void set(MyList *nums, int index, int num) {
assert(index >= 0 && index < nums->size);
nums->arr[index] = num;
}
/* Direct traversal of list elements */
/* Append an element at the end */
void add(MyList *nums, int num) {
if (size(nums) == capacity(nums)) {
extendCapacity(nums); // Expand capacity
extendCapacity(nums); // Grow the capacity
}
nums->arr[size(nums)] = num;
nums->size++;
}
/* Sort list */
/* Insert an element in the middle */
void insert(MyList *nums, int index, int num) {
assert(index >= 0 && index < size(nums));
// When the number of elements exceeds capacity, trigger the extension mechanism
// Grow the capacity when adding an element would exceed it
if (size(nums) == capacity(nums)) {
extendCapacity(nums); // Expand capacity
extendCapacity(nums); // Grow the capacity
}
for (int i = size(nums); i > index; --i) {
nums->arr[i] = nums->arr[i - 1];
@@ -77,8 +77,8 @@ void insert(MyList *nums, int index, int num) {
nums->size++;
}
/* Remove element */
// Note: stdio.h occupies the remove keyword
/* Remove an element */
// Note: stdio.h already declares a function named remove
int removeItem(MyList *nums, int index) {
assert(index >= 0 && index < size(nums));
int num = nums->arr[index];
@@ -89,35 +89,35 @@ int removeItem(MyList *nums, int index) {
return num;
}
/* Driver Code */
/* Grow the list capacity */
void extendCapacity(MyList *nums) {
// Allocate space first
// Allocate new space first
int newCapacity = capacity(nums) * nums->extendRatio;
int *extend = (int *)malloc(sizeof(int) * newCapacity);
int *temp = nums->arr;
// Copy old data to new data
// Copy the old data into the new array
for (int i = 0; i < size(nums); i++)
extend[i] = nums->arr[i];
// Free old data
// Free the old array
free(temp);
// Update new data
// Update the array pointer and capacity
nums->arr = extend;
nums->capacity = newCapacity;
}
/* Convert list to Array for printing */
/* Convert the list to an array for printing */
int *toArray(MyList *nums) {
return nums->arr;
}
/* Driver Code */
/* Driver code */
int main() {
/* Initialize list */
/* Initialize the list */
MyList *nums = newMyList();
/* Direct traversal of list elements */
/* Append an element at the end */
add(nums, 1);
add(nums, 3);
add(nums, 2);
@@ -125,38 +125,38 @@ int main() {
add(nums, 4);
printf("List nums = ");
printArray(toArray(nums), size(nums));
printf("Capacity = %d, Length = %d\n", capacity(nums), size(nums));
printf("Capacity = %d, size = %d\n", capacity(nums), size(nums));
/* Sort list */
/* Insert an element in the middle */
insert(nums, 3, 6);
printf("Insert number 6 at index 3, resulting in nums = ");
printf("Insert the number 6 at index 3, giving nums = ");
printArray(toArray(nums), size(nums));
/* Remove element */
/* Remove an element */
removeItem(nums, 3);
printf("Remove element at index 3, resulting in nums = ");
printf("Remove the element at index 3, giving nums = ");
printArray(toArray(nums), size(nums));
/* Update element */
/* Access an element */
int num = get(nums, 1);
printf("Access element at index 1, get num = %d\n", num);
printf("Access the element at index 1; num = %d\n", num);
/* Add elements at the end */
/* Update an element */
set(nums, 1, 0);
printf("Update element at index 1 to 0, resulting in nums = ");
printf("Update the element at index 1 to 0, giving nums = ");
printArray(toArray(nums), size(nums));
/* Test capacity expansion mechanism */
/* Test capacity growth */
for (int i = 0; i < 10; i++) {
// At i = 5, the list length will exceed the list capacity, triggering the expansion mechanism
// When i = 5, the list length would exceed its capacity, triggering capacity growth
add(nums, i);
}
printf("List nums after expansion = ");
printf("List after capacity growth, nums = ");
printArray(toArray(nums), size(nums));
printf("Capacity = %d, Length = %d\n", capacity(nums), size(nums));
printf("Capacity = %d, size = %d\n", capacity(nums), size(nums));
/* Free allocated memory */
/* Free the allocated memory */
delMyList(nums);
return 0;

View File

@@ -8,10 +8,10 @@
#define MAX_SIZE 100
/* Backtracking algorithm: N queens */
/* Backtracking: n-queens */
void backtrack(int row, int n, char state[MAX_SIZE][MAX_SIZE], char ***res, int *resSize, bool cols[MAX_SIZE],
bool diags1[2 * MAX_SIZE - 1], bool diags2[2 * MAX_SIZE - 1]) {
// When all rows are placed, record the solution
// Record a solution when a queen has been placed in every row
if (row == n) {
res[*resSize] = (char **)malloc(sizeof(char *) * n);
for (int i = 0; i < n; ++i) {
@@ -21,38 +21,38 @@ void backtrack(int row, int n, char state[MAX_SIZE][MAX_SIZE], char ***res, int
(*resSize)++;
return;
}
// Traverse all columns
// Iterate over all columns
for (int col = 0; col < n; col++) {
// Calculate the main diagonal and anti-diagonal corresponding to this cell
// Calculate the main-diagonal and anti-diagonal indices for this square
int diag1 = row - col + n - 1;
int diag2 = row + col;
// Pruning: do not allow queens to exist in the column, main diagonal, and anti-diagonal of this cell
// Prune: the square must have no queen in its column, main diagonal, or anti-diagonal
if (!cols[col] && !diags1[diag1] && !diags2[diag2]) {
// Attempt: place the queen in this cell
// Try: place a queen on this square
state[row][col] = 'Q';
cols[col] = diags1[diag1] = diags2[diag2] = true;
// Place the next row
// Place a queen in the next row
backtrack(row + 1, n, state, res, resSize, cols, diags1, diags2);
// Backtrack: restore this cell to an empty cell
// Backtrack: restore this square to empty
state[row][col] = '#';
cols[col] = diags1[diag1] = diags2[diag2] = false;
}
}
}
/* Solve N queens */
/* Solve the n-queens problem */
char ***nQueens(int n, int *returnSize) {
char state[MAX_SIZE][MAX_SIZE];
// Initialize an n*n chessboard, where 'Q' represents a queen and '#' represents an empty cell
// Initialize an n*n board, where 'Q' represents a queen and '#' represents an empty square
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
state[i][j] = '#';
}
state[i][n] = '\0';
}
bool cols[MAX_SIZE] = {false}; // Record whether there is a queen in the column
bool diags1[2 * MAX_SIZE - 1] = {false}; // Record whether there is a queen on the main diagonal
bool diags2[2 * MAX_SIZE - 1] = {false}; // Record whether there is a queen on the anti-diagonal
bool cols[MAX_SIZE] = {false}; // Track whether a column contains a queen
bool diags1[2 * MAX_SIZE - 1] = {false}; // Track whether a main diagonal contains a queen
bool diags2[2 * MAX_SIZE - 1] = {false}; // Track whether an anti-diagonal contains a queen
char ***res = (char ***)malloc(sizeof(char **) * MAX_SIZE);
*returnSize = 0;
@@ -60,14 +60,14 @@ char ***nQueens(int n, int *returnSize) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
int n = 4;
int returnSize;
char ***res = nQueens(n, &returnSize);
printf("Input board size is %d\n", n);
printf("Total queen placement solutions: %d\n", returnSize);
printf("Board width and height: %d\n", n);
printf("Number of queen placement solutions: %d\n", returnSize);
for (int i = 0; i < returnSize; ++i) {
for (int j = 0; j < n; ++j) {
printf("[");

View File

@@ -6,12 +6,12 @@
#include "../utils/common.h"
// Assume at most 1000 permutations
// Assume there are at most 1000 permutations
#define MAX_SIZE 1000
/* Backtracking algorithm: Permutations I */
/* Backtracking: permutations I */
void backtrack(int *state, int stateSize, int *choices, int choicesSize, bool *selected, int **res, int *resSize) {
// When the state length equals the number of elements, record the solution
// Record a solution when the state length equals the number of elements
if (stateSize == choicesSize) {
res[*resSize] = (int *)malloc(choicesSize * sizeof(int));
for (int i = 0; i < choicesSize; i++) {
@@ -20,17 +20,17 @@ void backtrack(int *state, int stateSize, int *choices, int choicesSize, bool *s
(*resSize)++;
return;
}
// Traverse all choices
// Iterate over all choices
for (int i = 0; i < choicesSize; i++) {
int choice = choices[i];
// Pruning: do not allow repeated selection of elements
// Prune: do not choose an element more than once
if (!selected[i]) {
// Attempt: make choice, update state
// Try: make a choice and update the state
selected[i] = true;
state[stateSize] = choice;
// Proceed to the next round of selection
// Proceed to the next choice
backtrack(state, stateSize + 1, choices, choicesSize, selected, res, resSize);
// Backtrack: undo choice, restore to previous state
// Backtrack: undo the choice and restore the previous state
selected[i] = false;
}
}
@@ -54,7 +54,7 @@ int **permutationsI(int *nums, int numsSize, int *returnSize) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
int nums[] = {1, 2, 3};
int numsSize = sizeof(nums) / sizeof(nums[0]);

View File

@@ -6,12 +6,12 @@
#include "../utils/common.h"
// Assume at most 1000 permutations, max element value 1000
// Assume at most 1000 permutations and a maximum element value of 1000
#define MAX_SIZE 1000
/* Backtracking algorithm: Permutations II */
/* Backtracking: permutations II */
void backtrack(int *state, int stateSize, int *choices, int choicesSize, bool *selected, int **res, int *resSize) {
// When the state length equals the number of elements, record the solution
// Record a solution when the state length equals the number of elements
if (stateSize == choicesSize) {
res[*resSize] = (int *)malloc(choicesSize * sizeof(int));
for (int i = 0; i < choicesSize; i++) {
@@ -20,19 +20,19 @@ void backtrack(int *state, int stateSize, int *choices, int choicesSize, bool *s
(*resSize)++;
return;
}
// Traverse all choices
// Iterate over all choices
bool duplicated[MAX_SIZE] = {false};
for (int i = 0; i < choicesSize; i++) {
int choice = choices[i];
// Pruning: do not allow repeated selection of elements and do not allow repeated selection of equal elements
// Prune: do not reuse an element or choose the same value again at this depth
if (!selected[i] && !duplicated[choice]) {
// Attempt: make choice, update state
duplicated[choice] = true; // Record the selected element value
// Try: make a choice and update the state
duplicated[choice] = true; // Record the chosen value
selected[i] = true;
state[stateSize] = choice;
// Proceed to the next round of selection
// Proceed to the next choice
backtrack(state, stateSize + 1, choices, choicesSize, selected, res, resSize);
// Backtrack: undo choice, restore to previous state
// Backtrack: undo the choice and restore the previous state
selected[i] = false;
}
}
@@ -56,7 +56,7 @@ int **permutationsII(int *nums, int numsSize, int *returnSize) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
int nums[] = {1, 1, 2};
int numsSize = sizeof(nums) / sizeof(nums[0]);

View File

@@ -6,36 +6,36 @@
#include "../utils/common.h"
// Assume result length not exceeding 100
// Assume the result contains at most 100 entries
#define MAX_SIZE 100
TreeNode *res[MAX_SIZE];
int resSize = 0;
/* Preorder traversal: Example 1 */
/* Preorder traversal: example 1 */
void preOrder(TreeNode *root) {
if (root == NULL) {
return;
}
if (root->val == 7) {
// Record solution
// Record the solution
res[resSize++] = root;
}
preOrder(root->left);
preOrder(root->right);
}
/* Driver Code */
/* Driver code */
int main() {
int arr[] = {1, 7, 3, 4, 5, 6, 7};
TreeNode *root = arrayToTree(arr, sizeof(arr) / sizeof(arr[0]));
printf("\nInitialize binary tree\n");
printf("\nInitialize the binary tree\n");
printTree(root);
// Preorder traversal
preOrder(root);
printf("\nOutput all nodes with value 7\n");
printf("\nPrint all nodes with value 7\n");
int *vals = malloc(resSize * sizeof(int));
for (int i = 0; i < resSize; i++) {
vals[i] = res[i]->val;

View File

@@ -6,7 +6,7 @@
#include "../utils/common.h"
// Assume path and result length not exceeding 100
// Assume each path and the result list contain at most 100 entries
#define MAX_SIZE 100
#define MAX_RES_SIZE 100
@@ -14,15 +14,15 @@ TreeNode *path[MAX_SIZE];
TreeNode *res[MAX_RES_SIZE][MAX_SIZE];
int pathSize = 0, resSize = 0;
/* Preorder traversal: Example 2 */
/* Preorder traversal: example 2 */
void preOrder(TreeNode *root) {
if (root == NULL) {
return;
}
// Attempt
// Try
path[pathSize++] = root;
if (root->val == 7) {
// Record solution
// Record the solution
for (int i = 0; i < pathSize; ++i) {
res[resSize][i] = path[i];
}
@@ -34,17 +34,17 @@ void preOrder(TreeNode *root) {
pathSize--;
}
/* Driver Code */
/* Driver code */
int main() {
int arr[] = {1, 7, 3, 4, 5, 6, 7};
TreeNode *root = arrayToTree(arr, sizeof(arr) / sizeof(arr[0]));
printf("\nInitialize binary tree\n");
printf("\nInitialize the binary tree\n");
printTree(root);
// Preorder traversal
preOrder(root);
printf("\nOutput all paths from root to node 7\n");
printf("\nPrint all paths from the root to nodes with value 7\n");
for (int i = 0; i < resSize; ++i) {
int *vals = malloc(MAX_SIZE * sizeof(int));
int size = 0;

View File

@@ -6,7 +6,7 @@
#include "../utils/common.h"
// Assume path and result length not exceeding 100
// Assume each path and the result list contain at most 100 entries
#define MAX_SIZE 100
#define MAX_RES_SIZE 100
@@ -14,16 +14,16 @@ TreeNode *path[MAX_SIZE];
TreeNode *res[MAX_RES_SIZE][MAX_SIZE];
int pathSize = 0, resSize = 0;
/* Preorder traversal: Example 3 */
/* Preorder traversal: example 3 */
void preOrder(TreeNode *root) {
// Pruning
// Prune
if (root == NULL || root->val == 3) {
return;
}
// Attempt
// Try
path[pathSize++] = root;
if (root->val == 7) {
// Record solution
// Record the solution
for (int i = 0; i < pathSize; i++) {
res[resSize][i] = path[i];
}
@@ -35,17 +35,17 @@ void preOrder(TreeNode *root) {
pathSize--;
}
/* Driver Code */
/* Driver code */
int main() {
int arr[] = {1, 7, 3, 4, 5, 6, 7};
TreeNode *root = arrayToTree(arr, sizeof(arr) / sizeof(arr[0]));
printf("\nInitialize binary tree\n");
printf("\nInitialize the binary tree\n");
printTree(root);
// Preorder traversal
preOrder(root);
printf("\nOutput all paths from root to node 7, excluding nodes with value 3\n");
printf("\nPrint all paths from the root to nodes with value 7 that contain no node with value 3\n");
for (int i = 0; i < resSize; ++i) {
int *vals = malloc(MAX_SIZE * sizeof(int));
int size = 0;

View File

@@ -6,7 +6,7 @@
#include "../utils/common.h"
// Assume path and result length not exceeding 100
// Assume each path and the result list contain at most 100 entries
#define MAX_SIZE 100
#define MAX_RES_SIZE 100
@@ -14,12 +14,12 @@ TreeNode *path[MAX_SIZE];
TreeNode *res[MAX_RES_SIZE][MAX_SIZE];
int pathSize = 0, resSize = 0;
/* Check if the current state is a solution */
/* Check whether the current state is a solution */
bool isSolution(void) {
return pathSize > 0 && path[pathSize - 1]->val == 7;
}
/* Record solution */
/* Record the solution */
void recordSolution(void) {
for (int i = 0; i < pathSize; i++) {
res[resSize][i] = path[i];
@@ -27,56 +27,56 @@ void recordSolution(void) {
resSize++;
}
/* Check if the choice is valid under the current state */
/* Check whether the choice is valid in the current state */
bool isValid(TreeNode *choice) {
return choice != NULL && choice->val != 3;
}
/* Update state */
/* Update the state */
void makeChoice(TreeNode *choice) {
path[pathSize++] = choice;
}
/* Restore state */
/* Restore the state */
void undoChoice(void) {
pathSize--;
}
/* Backtracking algorithm: Example 3 */
/* Backtracking: example 3 */
void backtrack(TreeNode *choices[2]) {
// Check if it is a solution
// Check whether this is a solution
if (isSolution()) {
// Record solution
// Record the solution
recordSolution();
}
// Traverse all choices
// Iterate over all choices
for (int i = 0; i < 2; i++) {
TreeNode *choice = choices[i];
// Pruning: check if the choice is valid
// Prune: check whether the choice is valid
if (isValid(choice)) {
// Attempt: make choice, update state
// Try: make a choice and update the state
makeChoice(choice);
// Proceed to the next round of selection
// Proceed to the next choice
TreeNode *nextChoices[2] = {choice->left, choice->right};
backtrack(nextChoices);
// Backtrack: undo choice, restore to previous state
// Backtrack: undo the choice and restore the previous state
undoChoice();
}
}
}
/* Driver Code */
/* Driver code */
int main() {
int arr[] = {1, 7, 3, 4, 5, 6, 7};
TreeNode *root = arrayToTree(arr, sizeof(arr) / sizeof(arr[0]));
printf("\nInitialize binary tree\n");
printf("\nInitialize the binary tree\n");
printTree(root);
// Backtracking algorithm
TreeNode *choices[2] = {root, NULL};
backtrack(choices);
printf("\nOutput all paths from root to node 7, excluding nodes with value 3\n");
printf("\nPrint all paths from the root to nodes with value 7 that contain no node with value 3\n");
for (int i = 0; i < resSize; ++i) {
int *vals = malloc(MAX_SIZE * sizeof(int));
int size = 0;

View File

@@ -13,14 +13,14 @@
int state[MAX_SIZE];
int stateSize = 0;
// Result list (subset list)
// Result list (list of subsets)
int res[MAX_RES_SIZE][MAX_SIZE];
int resColSizes[MAX_RES_SIZE];
int resSize = 0;
/* Backtracking algorithm: Subset sum I */
/* Backtracking: subset sum I */
void backtrack(int target, int *choices, int choicesSize, int start) {
// When the subset sum equals target, record the solution
// Record a solution when the remaining target is 0
if (target == 0) {
for (int i = 0; i < stateSize; ++i) {
res[resSize][i] = state[i];
@@ -28,20 +28,20 @@ void backtrack(int target, int *choices, int choicesSize, int start) {
resColSizes[resSize++] = stateSize;
return;
}
// Traverse all choices
// Pruning 2: start traversing from start to avoid generating duplicate subsets
// Iterate over all choices
// Pruning 2: iterate from start to avoid generating duplicate subsets
for (int i = start; i < choicesSize; i++) {
// Pruning 1: if the subset sum exceeds target, end the loop directly
// This is because the array is sorted, and later elements are larger, so the subset sum will definitely exceed target
// Pruning 1: exit the loop if the choice exceeds the remaining target
// The array is sorted, so later elements are at least as large and also exceed the remaining target
if (target - choices[i] < 0) {
break;
}
// Attempt: make choice, update target, start
// Try: make a choice and update target and start
state[stateSize] = choices[i];
stateSize++;
// Proceed to the next round of selection
// Proceed to the next choice
backtrack(target - choices[i], choices, choicesSize, i);
// Backtrack: undo choice, restore to previous state
// Backtrack: undo the choice and restore the previous state
stateSize--;
}
}
@@ -54,11 +54,11 @@ int cmp(const void *a, const void *b) {
/* Solve subset sum I */
void subsetSumI(int *nums, int numsSize, int target) {
qsort(nums, numsSize, sizeof(int), cmp); // Sort nums
int start = 0; // Start point for traversal
int start = 0; // Starting index for iteration
backtrack(target, nums, numsSize, start);
}
/* Driver Code */
/* Driver code */
int main() {
int nums[] = {3, 4, 5};
int numsSize = sizeof(nums) / sizeof(nums[0]);
@@ -69,7 +69,7 @@ int main() {
printf("Input array nums = ");
printArray(nums, numsSize);
printf("target = %d\n", target);
printf("All subsets with sum equal to %d res = \n", target);
printf("All subsets whose sum equals %d, res = \n", target);
for (int i = 0; i < resSize; ++i) {
printArray(res[i], resColSizes[i]);
}

View File

@@ -13,14 +13,14 @@
int state[MAX_SIZE];
int stateSize = 0;
// Result list (subset list)
// Result list (list of subsets)
int res[MAX_RES_SIZE][MAX_SIZE];
int resColSizes[MAX_RES_SIZE];
int resSize = 0;
/* Backtracking algorithm: Subset sum I */
/* Backtracking: subset sum I */
void backtrack(int target, int total, int *choices, int choicesSize) {
// When the subset sum equals target, record the solution
// Record a solution when the subset sum equals target
if (total == target) {
for (int i = 0; i < stateSize; i++) {
res[resSize][i] = state[i];
@@ -28,28 +28,28 @@ void backtrack(int target, int total, int *choices, int choicesSize) {
resColSizes[resSize++] = stateSize;
return;
}
// Traverse all choices
// Iterate over all choices
for (int i = 0; i < choicesSize; i++) {
// Pruning: if the subset sum exceeds target, skip this choice
// Prune: skip this choice if the subset sum would exceed target
if (total + choices[i] > target) {
continue;
}
// Attempt: make choice, update element sum total
// Try: make a choice and update the sum total
state[stateSize++] = choices[i];
// Proceed to the next round of selection
// Proceed to the next choice
backtrack(target, total + choices[i], choices, choicesSize);
// Backtrack: undo choice, restore to previous state
// Backtrack: undo the choice and restore the previous state
stateSize--;
}
}
/* Solve subset sum I (including duplicate subsets) */
/* Solve subset sum I (with duplicate subsets) */
void subsetSumINaive(int *nums, int numsSize, int target) {
resSize = 0; // Initialize solution count to 0
resSize = 0; // Initialize the solution count to 0
backtrack(target, 0, nums, numsSize);
}
/* Driver Code */
/* Driver code */
int main() {
int nums[] = {3, 4, 5};
int numsSize = sizeof(nums) / sizeof(nums[0]);
@@ -60,7 +60,7 @@ int main() {
printf("Input array nums = ");
printArray(nums, numsSize);
printf("target = %d\n", target);
printf("All subsets with sum equal to %d res = \n", target);
printf("All subsets whose sum equals %d, res = \n", target);
for (int i = 0; i < resSize; i++) {
printArray(res[i], resColSizes[i]);
}

View File

@@ -13,14 +13,14 @@
int state[MAX_SIZE];
int stateSize = 0;
// Result list (subset list)
// Result list (list of subsets)
int res[MAX_RES_SIZE][MAX_SIZE];
int resColSizes[MAX_RES_SIZE];
int resSize = 0;
/* Backtracking algorithm: Subset sum II */
/* Backtracking: subset sum II */
void backtrack(int target, int *choices, int choicesSize, int start) {
// When the subset sum equals target, record the solution
// Record a solution when the remaining target is 0
if (target == 0) {
for (int i = 0; i < stateSize; i++) {
res[resSize][i] = state[i];
@@ -28,24 +28,24 @@ void backtrack(int target, int *choices, int choicesSize, int start) {
resColSizes[resSize++] = stateSize;
return;
}
// Traverse all choices
// Pruning 2: start traversing from start to avoid generating duplicate subsets
// Pruning 3: start traversing from start to avoid repeatedly selecting the same element
// Iterate over all choices
// Pruning 2: iterate from start to avoid generating duplicate subsets
// Pruning 3: iterate from start to avoid choosing the same element again
for (int i = start; i < choicesSize; i++) {
// Pruning 1: Skip if subset sum exceeds target
// Pruning 1: skip this choice if it exceeds the remaining target
if (target - choices[i] < 0) {
continue;
}
// Pruning 4: if this element equals the left element, it means this search branch is duplicate, skip it directly
// Pruning 4: if this element equals its left neighbor at the same search depth, the branch is a duplicate; skip it
if (i > start && choices[i] == choices[i - 1]) {
continue;
}
// Attempt: make choice, update target, start
// Try: make a choice and update target and start
state[stateSize] = choices[i];
stateSize++;
// Proceed to the next round of selection
// Proceed to the next choice
backtrack(target - choices[i], choices, choicesSize, i + 1);
// Backtrack: undo choice, restore to previous state
// Backtrack: undo the choice and restore the previous state
stateSize--;
}
}
@@ -63,7 +63,7 @@ void subsetSumII(int *nums, int numsSize, int target) {
backtrack(target, nums, numsSize, 0);
}
/* Driver Code */
/* Driver code */
int main() {
int nums[] = {4, 4, 5};
int numsSize = sizeof(nums) / sizeof(nums[0]);
@@ -74,7 +74,7 @@ int main() {
printf("Input array nums = ");
printArray(nums, numsSize);
printf("target = %d\n", target);
printf("All subsets with sum equal to %d res = \n", target);
printf("All subsets whose sum equals %d, res = \n", target);
for (int i = 0; i < resSize; ++i) {
printArray(res[i], resColSizes[i]);
}

View File

@@ -6,7 +6,7 @@
#include <assert.h>
/* Iterative summation */
/* Sum using iteration */
int sumIter(int n) {
int res = 0;
for (int i = 1; i <= n; i++) {
@@ -15,7 +15,7 @@ int sumIter(int n) {
return res;
}
/* Recursive summation */
/* Sum using recursion */
int sumRecur(int n) {
if (n == 1) {
return 1;
@@ -23,7 +23,7 @@ int sumRecur(int n) {
return n + sumRecur(n - 1);
}
/* Linear loop */
/* Linear-time loop */
int linearLoop(int n) {
int res = 0;
for (int i = 0; i < n; i++) {
@@ -32,7 +32,7 @@ int linearLoop(int n) {
return res;
}
/* Quadratic loop */
/* Quadratic-time loop */
int quadraticLoop(int n) {
int res = 0;
for (int i = 0; i < n; i++) {
@@ -43,7 +43,7 @@ int quadraticLoop(int n) {
return res;
}
/* Logarithmic loop */
/* Logarithmic-time loop */
int logarithmicLoop(int n) {
while (n > 1) {
n /= 2;

View File

@@ -9,7 +9,7 @@
/* for loop */
int forLoop(int n) {
int res = 0;
// Sum 1, 2, ..., n-1, n
// Sum 1, 2, ..., n-1, n in a loop
for (int i = 1; i <= n; i++) {
res += i;
}
@@ -19,11 +19,11 @@ int forLoop(int n) {
/* while loop */
int whileLoop(int n) {
int res = 0;
int i = 1; // Initialize condition variable
// Sum 1, 2, ..., n-1, n
int i = 1; // Initialize the loop control variable
// Sum 1, 2, ..., n-1, n in a loop
while (i <= n) {
res += i;
i++; // Update condition variable
i++; // Update the loop control variable
}
return res;
}
@@ -31,25 +31,25 @@ int whileLoop(int n) {
/* while loop (two updates) */
int whileLoopII(int n) {
int res = 0;
int i = 1; // Initialize condition variable
// Sum 1, 4, 10, ...
int i = 1; // Initialize the loop control variable
// Sum 1, 4, 10, ... in a loop
while (i <= n) {
res += i;
// Update condition variable
// Update the loop control variable
i++;
i *= 2;
}
return res;
}
/* Nested for loop */
/* Nested for loops */
char *nestedForLoop(int n) {
// n * n is the number of points, "(i, j), " string max length is 6+10*2, plus extra space for null character \0
// There are n * n points; each "(i, j), " takes at most 6+10*2 characters, plus space for the final null character \0
int size = n * n * 26 + 1;
char *res = malloc(size * sizeof(char));
// Loop i = 1, 2, ..., n-1, n
// Loop over i = 1, 2, ..., n-1, n
for (int i = 1; i <= n; i++) {
// Loop j = 1, 2, ..., n-1, n
// Loop over j = 1, 2, ..., n-1, n
for (int j = 1; j <= n; j++) {
char tmp[26];
snprintf(tmp, sizeof(tmp), "(%d, %d), ", i, j);
@@ -59,22 +59,22 @@ char *nestedForLoop(int n) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
int n = 5;
int res;
res = forLoop(n);
printf("\nFor loop sum result res = %d\n", res);
printf("\nSum from the for loop, res = %d\n", res);
res = whileLoop(n);
printf("\nWhile loop sum result res = %d\n", res);
printf("\nSum from the while loop, res = %d\n", res);
res = whileLoopII(n);
printf("\nWhile loop (two updates) sum result res = %d\n", res);
printf("\nSum from the while loop (two updates), res = %d\n", res);
char *resStr = nestedForLoop(n);
printf("\nNested for loop traversal result %s\r\n", resStr);
printf("\nTraversal result from nested for loops: %s\r\n", resStr);
free(resStr);
return 0;

View File

@@ -8,28 +8,28 @@
/* Recursion */
int recur(int n) {
// Termination condition
// Base case
if (n == 1)
return 1;
// Recurse: recursive call
// Recurse: make a recursive call
int res = recur(n - 1);
// Return: return result
// Unwind: return the result
return n + res;
}
/* Simulate recursion using iteration */
int forLoopRecur(int n) {
int stack[1000]; // Use a large array to simulate stack
int top = -1; // Stack top index
int stack[1000]; // Use a large array to simulate a stack
int top = -1; // Top-of-stack index
int res = 0;
// Recurse: recursive call
// Recurse: make a recursive call
for (int i = n; i > 0; i--) {
// Simulate "recurse" with "push"
// Simulate recursive calls by pushing onto the stack
stack[1 + top++] = i;
}
// Return: return result
// Unwind: return the result
while (top >= 0) {
// Simulate "return" with "pop"
// Simulate unwinding by popping from the stack
res += stack[top--];
}
// res = 1+2+3+...+n
@@ -38,40 +38,40 @@ int forLoopRecur(int n) {
/* Tail recursion */
int tailRecur(int n, int res) {
// Termination condition
// Base case
if (n == 0)
return res;
// Tail recursive call
// Tail-recursive call
return tailRecur(n - 1, res + n);
}
/* Fibonacci sequence: recursion */
int fib(int n) {
// Termination condition f(1) = 0, f(2) = 1
// Base cases: f(1) = 0, f(2) = 1
if (n == 1 || n == 2)
return n - 1;
// Recursive call f(n) = f(n-1) + f(n-2)
// Recursive calls: f(n) = f(n-1) + f(n-2)
int res = fib(n - 1) + fib(n - 2);
// Return result f(n)
// Return the result f(n)
return res;
}
/* Driver Code */
/* Driver code */
int main() {
int n = 5;
int res;
res = recur(n);
printf("\nRecursion sum result res = %d\n", res);
printf("\nSum from the recursive function, res = %d\n", res);
res = forLoopRecur(n);
printf("\nUsing iteration to simulate recursion sum result res = %d\n", res);
printf("\nSum from simulating recursion with iteration, res = %d\n", res);
res = tailRecur(n, 0);
printf("\nTail recursion sum result res = %d\n", res);
printf("\nSum from the tail-recursive function, res = %d\n", res);
res = fib(n);
printf("\nThe %dth Fibonacci number is %d\n", n, res);
printf("\nFibonacci term %d is %d\n", n, res);
return 0;
}

View File

@@ -12,9 +12,9 @@ int func() {
return 0;
}
/* Constant order */
/* Constant complexity */
void constant(int n) {
// Constants, variables, objects occupy O(1) space
// Constants, variables, and objects occupy O(1) space
const int a = 0;
int b = 0;
int nums[1000];
@@ -24,7 +24,7 @@ void constant(int n) {
for (int i = 0; i < n; i++) {
int c = 0;
}
// Functions in the loop occupy O(1) space
// Function calls in the loop occupy O(1) space
for (int i = 0; i < n; i++) {
func();
}
@@ -37,9 +37,9 @@ typedef struct {
UT_hash_handle hh; // Implemented using uthash.h
} HashTable;
/* Linear order */
/* Linear complexity */
void linear(int n) {
// Array of length n uses O(n) space
// An array of length n uses O(n) space
int *nums = malloc(sizeof(int) * n);
free(nums);
@@ -48,13 +48,13 @@ void linear(int n) {
for (int i = 0; i < n; i++) {
nodes[i] = newListNode(i);
}
// Memory release
// Free memory
for (int i = 0; i < n; i++) {
free(nodes[i]);
}
free(nodes);
// A hash table of length n occupies O(n) space
// A hash table with n entries occupies O(n) space
HashTable *h = NULL;
for (int i = 0; i < n; i++) {
HashTable *tmp = malloc(sizeof(HashTable));
@@ -63,7 +63,7 @@ void linear(int n) {
HASH_ADD_INT(h, key, tmp);
}
// Memory release
// Free memory
HashTable *curr, *tmp;
HASH_ITER(hh, h, curr, tmp) {
HASH_DEL(h, curr);
@@ -71,17 +71,17 @@ void linear(int n) {
}
}
/* Linear order (recursive implementation) */
/* Linear complexity (recursive implementation) */
void linearRecur(int n) {
printf("Recursion n = %d\r\n", n);
printf("Recursive call n = %d\r\n", n);
if (n == 1)
return;
linearRecur(n - 1);
}
/* Exponential order */
/* Quadratic complexity */
void quadratic(int n) {
// 2D list uses O(n^2) space
// The two-dimensional list occupies O(n^2) space
int **numMatrix = malloc(sizeof(int *) * n);
for (int i = 0; i < n; i++) {
int *tmp = malloc(sizeof(int) * n);
@@ -91,25 +91,25 @@ void quadratic(int n) {
numMatrix[i] = tmp;
}
// Memory release
// Free memory
for (int i = 0; i < n; i++) {
free(numMatrix[i]);
}
free(numMatrix);
}
/* Quadratic order (recursive implementation) */
/* Quadratic complexity (recursive implementation) */
int quadraticRecur(int n) {
if (n <= 0)
return 0;
int *nums = malloc(sizeof(int) * n);
printf("In recursion n = %d, nums length = %d\r\n", n, n);
printf("In recursive call n = %d, nums has length = %d\r\n", n, n);
int res = quadraticRecur(n - 1);
free(nums);
return res;
}
/* Driver Code */
/* Exponential complexity (building a perfect binary tree) */
TreeNode *buildTree(int n) {
if (n == 0)
return NULL;
@@ -119,18 +119,18 @@ TreeNode *buildTree(int n) {
return root;
}
/* Driver Code */
/* Driver code */
int main() {
int n = 5;
// Constant order
// Constant complexity
constant(n);
// Linear order
// Linear complexity
linear(n);
linearRecur(n);
// Exponential order
// Quadratic complexity
quadratic(n);
quadraticRecur(n);
// Exponential order
// Exponential complexity
TreeNode *root = buildTree(n);
printTree(root);

View File

@@ -6,7 +6,7 @@
#include "../utils/common.h"
/* Constant order */
/* Constant complexity */
int constant(int n) {
int count = 0;
int size = 100000;
@@ -16,7 +16,7 @@ int constant(int n) {
return count;
}
/* Linear order */
/* Linear complexity */
int linear(int n) {
int count = 0;
for (int i = 0; i < n; i++) {
@@ -25,20 +25,20 @@ int linear(int n) {
return count;
}
/* Linear order (traversing array) */
/* Linear complexity (array traversal) */
int arrayTraversal(int *nums, int n) {
int count = 0;
// Number of iterations is proportional to the array length
// The number of iterations is proportional to the array length
for (int i = 0; i < n; i++) {
count++;
}
return count;
}
/* Exponential order */
/* Quadratic complexity */
int quadratic(int n) {
int count = 0;
// Number of iterations is quadratically related to the data size n
// The number of iterations is proportional to the square of the input size n
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
count++;
@@ -47,30 +47,30 @@ int quadratic(int n) {
return count;
}
/* Quadratic order (bubble sort) */
/* Quadratic complexity (bubble sort) */
int bubbleSort(int *nums, int n) {
int count = 0; // Counter
// Outer loop: unsorted range is [0, i]
// Outer loop: the unsorted range is [0, i]
for (int i = n - 1; i > 0; i--) {
// Inner loop: swap the largest element in the unsorted range [0, i] to the rightmost end of that range
// Inner loop: move the largest element in the unsorted range [0, i] to its right end through swaps
for (int j = 0; j < i; j++) {
if (nums[j] > nums[j + 1]) {
// Swap nums[j] and nums[j + 1]
int tmp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = tmp;
count += 3; // Element swap includes 3 unit operations
count += 3; // Swapping two elements takes 3 elementary operations
}
}
}
return count;
}
/* Exponential order (loop implementation) */
/* Exponential complexity (iterative implementation) */
int exponential(int n) {
int count = 0;
int bas = 1;
// Cells divide into two every round, forming sequence 1, 2, 4, 8, ..., 2^(n-1)
// Each cell divides into two per round, giving the sequence 1, 2, 4, 8, ..., 2^(n-1)
for (int i = 0; i < n; i++) {
for (int j = 0; j < bas; j++) {
count++;
@@ -81,14 +81,14 @@ int exponential(int n) {
return count;
}
/* Exponential order (recursive implementation) */
/* Exponential complexity (recursive implementation) */
int expRecur(int n) {
if (n == 1)
return 1;
return expRecur(n - 1) + expRecur(n - 1) + 1;
}
/* Logarithmic order (loop implementation) */
/* Logarithmic complexity (iterative implementation) */
int logarithmic(int n) {
int count = 0;
while (n > 1) {
@@ -98,14 +98,14 @@ int logarithmic(int n) {
return count;
}
/* Logarithmic order (recursive implementation) */
/* Logarithmic complexity (recursive implementation) */
int logRecur(int n) {
if (n <= 1)
return 0;
return logRecur(n / 2) + 1;
}
/* Linearithmic order */
/* Linearithmic complexity */
int linearLogRecur(int n) {
if (n <= 1)
return 1;
@@ -116,7 +116,7 @@ int linearLogRecur(int n) {
return count;
}
/* Factorial order (recursive implementation) */
/* Factorial complexity (recursive implementation) */
int factorialRecur(int n) {
if (n == 0)
return 1;
@@ -127,47 +127,47 @@ int factorialRecur(int n) {
return count;
}
/* Driver Code */
/* Driver code */
int main(int argc, char *argv[]) {
// You can modify n to run and observe the trend of the number of operations for various complexities
// Try different values of n to see how the operation count grows for each complexity
int n = 8;
printf("Input data size n = %d\n", n);
printf("Input size n = %d\n", n);
int count = constant(n);
printf("Constant-time operations count = %d\n", count);
printf("Operation count for constant complexity = %d\n", count);
count = linear(n);
printf("Linear-time operations count = %d\n", count);
// Allocate heap memory (create 1D variable-length array: n elements of type int)
printf("Operation count for linear complexity = %d\n", count);
// Allocate heap memory for a one-dimensional array of n int elements
int *nums = (int *)malloc(n * sizeof(int));
count = arrayTraversal(nums, n);
printf("Linear-time (array traversal) operations count = %d\n", count);
printf("Operation count for linear complexity (array traversal) = %d\n", count);
count = quadratic(n);
printf("Quadratic-time operations count = %d\n", count);
printf("Operation count for quadratic complexity = %d\n", count);
for (int i = 0; i < n; i++) {
nums[i] = n - i; // [n,n-1,...,2,1]
}
count = bubbleSort(nums, n);
printf("Quadratic-time (bubble sort) operations count = %d\n", count);
printf("Operation count for quadratic complexity (bubble sort) = %d\n", count);
count = exponential(n);
printf("Exponential-time (iterative) operations count = %d\n", count);
printf("Operation count for exponential complexity (iteration) = %d\n", count);
count = expRecur(n);
printf("Exponential-time (recursive) operations count = %d\n", count);
printf("Operation count for exponential complexity (recursion) = %d\n", count);
count = logarithmic(n);
printf("Logarithmic-time (iterative) operations count = %d\n", count);
printf("Operation count for logarithmic complexity (iteration) = %d\n", count);
count = logRecur(n);
printf("Logarithmic-time (recursive) operations count = %d\n", count);
printf("Operation count for logarithmic complexity (recursion) = %d\n", count);
count = linearLogRecur(n);
printf("Linearithmic-time (recursive) operations count = %d\n", count);
printf("Operation count for linearithmic complexity (recursion) = %d\n", count);
count = factorialRecur(n);
printf("Factorial-time (recursive) operations count = %d\n", count);
printf("Operation count for factorial complexity (recursion) = %d\n", count);
// Free heap memory
// Free the heap memory
if (nums != NULL) {
free(nums);
nums = NULL;

View File

@@ -6,15 +6,15 @@
#include "../utils/common.h"
/* Generate an array with elements { 1, 2, ..., n }, order shuffled */
/* Generate an array containing { 1, 2, ..., n } in shuffled order */
int *randomNumbers(int n) {
// Allocate heap memory (create 1D variable-length array: n elements of type int)
// Allocate heap memory for a one-dimensional array of n int elements
int *nums = (int *)malloc(n * sizeof(int));
// Generate array nums = { 1, 2, 3, ..., n }
// Generate the array nums = { 1, 2, 3, ..., n }
for (int i = 0; i < n; i++) {
nums[i] = i + 1;
}
// Randomly shuffle array elements
// Randomly shuffle the array elements
for (int i = n - 1; i > 0; i--) {
int j = rand() % (i + 1);
int temp = nums[i];
@@ -24,20 +24,20 @@ int *randomNumbers(int n) {
return nums;
}
/* Find the index of number 1 in array nums */
/* Find the index of the number 1 in array nums */
int findOne(int *nums, int n) {
for (int i = 0; i < n; i++) {
// When element 1 is at the head of the array, best time complexity O(1) is achieved
// When element 1 is at the tail of the array, worst time complexity O(n) is achieved
// When 1 is at the start of the array, the best-case time complexity is O(1)
// When 1 is at the end of the array, the worst-case time complexity is O(n)
if (nums[i] == 1)
return i;
}
return -1;
}
/* Driver Code */
/* Driver code */
int main(int argc, char *argv[]) {
// Initialize random seed
// Initialize the random seed
srand((unsigned int)time(NULL));
for (int i = 0; i < 10; i++) {
int n = 100;
@@ -45,8 +45,8 @@ int main(int argc, char *argv[]) {
int index = findOne(nums, n);
printf("\nArray [ 1, 2, ..., n ] after shuffling = ");
printArray(nums, n);
printf("Index of number 1 is %d\n", index);
// Free heap memory
printf("Index of the number 1: %d\n", index);
// Free the heap memory
if (nums != NULL) {
free(nums);
nums = NULL;

View File

@@ -8,20 +8,20 @@
/* Binary search: problem f(i, j) */
int dfs(int nums[], int target, int i, int j) {
// If the interval is empty, it means there is no target element, return -1
// If the interval is empty, the target is absent; return -1
if (i > j) {
return -1;
}
// Calculate the midpoint index m
int m = (i + j) / 2;
if (nums[m] < target) {
// Recursion subproblem f(m+1, j)
// Recurse on subproblem f(m+1, j)
return dfs(nums, target, m + 1, j);
} else if (nums[m] > target) {
// Recursion subproblem f(i, m-1)
// Recurse on subproblem f(i, m-1)
return dfs(nums, target, i, m - 1);
} else {
// Found the target element, return its index
// The target element was found; return its index
return m;
}
}
@@ -29,17 +29,17 @@ int dfs(int nums[], int target, int i, int j) {
/* Binary search */
int binarySearch(int nums[], int target, int numsSize) {
int n = numsSize;
// Solve the problem f(0, n-1)
// Solve problem f(0, n-1)
return dfs(nums, target, 0, n - 1);
}
/* Driver Code */
/* Driver code */
int main() {
int target = 6;
int nums[] = {1, 3, 6, 8, 12, 15, 23, 26, 31, 35};
int numsSize = sizeof(nums) / sizeof(nums[0]);
// Binary search (closed interval on both sides)
// Binary search (closed interval)
int index = binarySearch(nums, target, numsSize);
printf("Index of target element 6 = %d\n", index);

View File

@@ -6,12 +6,12 @@
#include "../utils/common.h"
// Assume all elements less than 1000
// Assume all elements are less than 1000
#define MAX_SIZE 1000
/* Build binary tree: divide and conquer */
/* Build a binary tree: divide and conquer */
TreeNode *dfs(int *preorder, int *inorderMap, int i, int l, int r, int size) {
// Terminate when the subtree interval is empty
// Stop when the subtree interval is empty
if (r - l < 0)
return NULL;
// Initialize the root node
@@ -19,7 +19,7 @@ TreeNode *dfs(int *preorder, int *inorderMap, int i, int l, int r, int size) {
root->val = preorder[i];
root->left = NULL;
root->right = NULL;
// Query m to divide the left and right subtrees
// Look up m to separate the left and right subtrees
int m = inorderMap[preorder[i]];
// Subproblem: build the left subtree
root->left = dfs(preorder, inorderMap, i + 1, l, m - 1, size);
@@ -29,9 +29,9 @@ TreeNode *dfs(int *preorder, int *inorderMap, int i, int l, int r, int size) {
return root;
}
/* Build binary tree */
/* Build a binary tree */
TreeNode *buildTree(int *preorder, int preorderSize, int *inorder, int inorderSize) {
// Initialize hash map, storing the mapping from inorder elements to indices
// Initialize a lookup array mapping inorder values to their indices
int *inorderMap = (int *)malloc(sizeof(int) * MAX_SIZE);
for (int i = 0; i < inorderSize; i++) {
inorderMap[inorder[i]] = i;
@@ -41,7 +41,7 @@ TreeNode *buildTree(int *preorder, int preorderSize, int *inorder, int inorderSi
return root;
}
/* Driver Code */
/* Driver code */
int main() {
int preorder[] = {3, 9, 2, 1, 7};
int inorder[] = {9, 3, 1, 2, 7};
@@ -53,7 +53,7 @@ int main() {
printArray(inorder, inorderSize);
TreeNode *root = buildTree(preorder, preorderSize, inorder, inorderSize);
printf("The constructed binary tree is:\n");
printf("Constructed binary tree:\n");
printTree(root);
freeMemoryTree(root);

View File

@@ -6,7 +6,7 @@
#include <assert.h>
/* Exponentiation by squaring */
/* Fast exponentiation */
int fastPow(int x, int n) {
if (n == 0) {
return 1;

View File

@@ -6,12 +6,12 @@
#include "../utils/common.h"
// Assume at most 1000 permutations
// Assume at most 1000 disks
#define MAX_SIZE 1000
/* Move a disk */
/* Move one disk */
void move(int *src, int *srcSize, int *tar, int *tarSize) {
// Take out a disk from the top of src
// Take a disk from the top of src
int pan = src[*srcSize - 1];
src[*srcSize - 1] = 0;
(*srcSize)--;
@@ -22,14 +22,14 @@ void move(int *src, int *srcSize, int *tar, int *tarSize) {
/* Solve the Tower of Hanoi problem f(i) */
void dfs(int i, int *src, int *srcSize, int *buf, int *bufSize, int *tar, int *tarSize) {
// If there is only one disk left in src, move it directly to tar
// If only one disk remains to be moved from src, move it directly to tar
if (i == 1) {
move(src, srcSize, tar, tarSize);
return;
}
// Subproblem f(i-1): move the top i-1 disks from src to buf using tar
dfs(i - 1, src, srcSize, tar, tarSize, buf, bufSize);
// Subproblem f(1): move the remaining disk from src to tar
// Subproblem f(1): move the remaining disk of this subproblem from src to tar
move(src, srcSize, tar, tarSize);
// Subproblem f(i-1): move the top i-1 disks from buf to tar using src
dfs(i - 1, buf, bufSize, src, srcSize, tar, tarSize);
@@ -41,9 +41,9 @@ void solveHanota(int *A, int *ASize, int *B, int *BSize, int *C, int *CSize) {
dfs(*ASize, A, ASize, B, BSize, C, CSize);
}
/* Driver Code */
/* Driver code */
int main() {
// The tail of the list is the top of the rod
// The end of each list represents the top of the peg
int a[] = {5, 4, 3, 2, 1};
int b[MAX_SIZE] = {0};
int c[MAX_SIZE] = {0};
@@ -62,7 +62,7 @@ int main() {
solveHanota(a, &ASize, b, &BSize, c, &CSize);
printf("\nAfter disk movement:");
printf("\nAfter moving the disks:");
printf("A = ");
printArray(a, ASize);
printf("B = ");

View File

@@ -8,27 +8,27 @@
/* Backtracking */
void backtrack(int *choices, int state, int n, int *res, int len) {
// When climbing to the n-th stair, add 1 to the solution count
// When step n is reached, increase the number of ways by 1
if (state == n)
res[0]++;
// Traverse all choices
// Iterate over all choices
for (int i = 0; i < len; i++) {
int choice = choices[i];
// Pruning: not allowed to go beyond the n-th stair
// Prune: do not go beyond step n
if (state + choice > n)
continue;
// Attempt: make choice, update state
// Try: make a choice and update the state
backtrack(choices, state + choice, n, res, len);
// Backtrack
}
}
/* Climbing stairs: Backtracking */
/* Climbing stairs: backtracking */
int climbingStairsBacktrack(int n) {
int choices[2] = {1, 2}; // Can choose to climb up 1 or 2 stairs
int state = 0; // Start climbing from the 0-th stair
int choices[2] = {1, 2}; // Choose to climb 1 or 2 steps
int state = 0; // Start climbing from step 0
int *res = (int *)malloc(sizeof(int));
*res = 0; // Use res[0] to record the solution count
*res = 0; // Use res[0] to record the number of ways
int len = sizeof(choices) / sizeof(int);
backtrack(choices, state, n, res, len);
int result = *res;
@@ -36,12 +36,12 @@ int climbingStairsBacktrack(int n) {
return result;
}
/* Driver Code */
/* Driver code */
int main() {
int n = 9;
int res = climbingStairsBacktrack(n);
printf("Climbing %d stairs has %d solutions\n", n, res);
printf("Number of ways to climb %d stairs: %d\n", n, res);
return 0;
}

View File

@@ -6,22 +6,22 @@
#include "../utils/common.h"
/* Climbing stairs with constraint: Dynamic programming */
/* Climbing stairs with constraints: dynamic programming */
int climbingStairsConstraintDP(int n) {
if (n == 1 || n == 2) {
return 1;
}
// Initialize dp table, used to store solutions to subproblems
// Initialize the dp table to store subproblem solutions
int **dp = malloc((n + 1) * sizeof(int *));
for (int i = 0; i <= n; i++) {
dp[i] = calloc(3, sizeof(int));
}
// Initial state: preset the solution to the smallest subproblem
// Initial states: set the solutions to the smallest subproblems
dp[1][1] = 1;
dp[1][2] = 0;
dp[2][1] = 0;
dp[2][2] = 1;
// State transition: gradually solve larger subproblems from smaller ones
// State transitions: solve progressively larger subproblems using smaller ones
for (int i = 3; i <= n; i++) {
dp[i][1] = dp[i - 1][2];
dp[i][2] = dp[i - 2][1] + dp[i - 2][2];
@@ -35,12 +35,12 @@ int climbingStairsConstraintDP(int n) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
int n = 9;
int res = climbingStairsConstraintDP(n);
printf("Climbing %d stairs has %d solutions\n", n, res);
printf("Number of ways to climb %d stairs: %d\n", n, res);
return 0;
}

View File

@@ -8,7 +8,7 @@
/* Search */
int dfs(int i) {
// Known dp[1] and dp[2], return them
// The values of dp[1] and dp[2] are known; return them
if (i == 1 || i == 2)
return i;
// dp[i] = dp[i-1] + dp[i-2]
@@ -16,17 +16,17 @@ int dfs(int i) {
return count;
}
/* Climbing stairs: Search */
/* Climbing stairs: search */
int climbingStairsDFS(int n) {
return dfs(n);
}
/* Driver Code */
/* Driver code */
int main() {
int n = 9;
int res = climbingStairsDFS(n);
printf("Climbing %d stairs has %d solutions\n", n, res);
printf("Number of ways to climb %d stairs: %d\n", n, res);
return 0;
}

View File

@@ -6,12 +6,12 @@
#include "../utils/common.h"
/* Memoization search */
/* Memoized search */
int dfs(int i, int *mem) {
// Known dp[1] and dp[2], return them
// The values of dp[1] and dp[2] are known; return them
if (i == 1 || i == 2)
return i;
// If record dp[i] exists, return it directly
// If dp[i] has been recorded, return it directly
if (mem[i] != -1)
return mem[i];
// dp[i] = dp[i-1] + dp[i-2]
@@ -21,9 +21,9 @@ int dfs(int i, int *mem) {
return count;
}
/* Climbing stairs: Memoization search */
/* Climbing stairs: memoized search */
int climbingStairsDFSMem(int n) {
// mem[i] records the total number of solutions to climb to the i-th stair, -1 means no record
// mem[i] stores the number of ways to reach step i; -1 means no result has been recorded
int *mem = (int *)malloc((n + 1) * sizeof(int));
for (int i = 0; i <= n; i++) {
mem[i] = -1;
@@ -33,12 +33,12 @@ int climbingStairsDFSMem(int n) {
return result;
}
/* Driver Code */
/* Driver code */
int main() {
int n = 9;
int res = climbingStairsDFSMem(n);
printf("Climbing %d stairs has %d solutions\n", n, res);
printf("Number of ways to climb %d stairs: %d\n", n, res);
return 0;
}

View File

@@ -6,16 +6,16 @@
#include "../utils/common.h"
/* Climbing stairs: Dynamic programming */
/* Climbing stairs: dynamic programming */
int climbingStairsDP(int n) {
if (n == 1 || n == 2)
return n;
// Initialize dp table, used to store solutions to subproblems
// Initialize the dp table to store subproblem solutions
int *dp = (int *)malloc((n + 1) * sizeof(int));
// Initial state: preset the solution to the smallest subproblem
// Initial states: set the solutions to the smallest subproblems
dp[1] = 1;
dp[2] = 2;
// State transition: gradually solve larger subproblems from smaller ones
// State transitions: solve progressively larger subproblems using smaller ones
for (int i = 3; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
@@ -24,7 +24,7 @@ int climbingStairsDP(int n) {
return result;
}
/* Climbing stairs: Space-optimized dynamic programming */
/* Climbing stairs: space-optimized dynamic programming */
int climbingStairsDPComp(int n) {
if (n == 1 || n == 2)
return n;
@@ -37,15 +37,15 @@ int climbingStairsDPComp(int n) {
return b;
}
/* Driver Code */
/* Driver code */
int main() {
int n = 9;
int res = climbingStairsDP(n);
printf("Climbing %d stairs has %d solutions\n", n, res);
printf("Number of ways to climb %d stairs: %d\n", n, res);
res = climbingStairsDPComp(n);
printf("Climbing %d stairs has %d solutions\n", n, res);
printf("Number of ways to climb %d stairs: %d\n", n, res);
return 0;
}

View File

@@ -6,32 +6,32 @@
#include "../utils/common.h"
/* Find minimum value */
/* Find the minimum */
int myMin(int a, int b) {
return a < b ? a : b;
}
/* Coin change: Dynamic programming */
/* Coin change: dynamic programming */
int coinChangeDP(int coins[], int amt, int coinsSize) {
int n = coinsSize;
int MAX = amt + 1;
// Initialize dp table
// Initialize the dp table
int **dp = malloc((n + 1) * sizeof(int *));
for (int i = 0; i <= n; i++) {
dp[i] = calloc(amt + 1, sizeof(int));
}
// State transition: first row and first column
// State transitions: first row and first column
for (int a = 1; a <= amt; a++) {
dp[0][a] = MAX;
}
// State transition: rest of the rows and columns
// State transitions: remaining rows and columns
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// If exceeds target amount, don't select coin i
// If the coin exceeds the target amount, do not choose coin i
dp[i][a] = dp[i - 1][a];
} else {
// The smaller value between not selecting and selecting coin i
// Take the smaller result of not choosing and choosing coin i
dp[i][a] = myMin(dp[i - 1][a], dp[i][a - coins[i - 1]] + 1);
}
}
@@ -45,25 +45,25 @@ int coinChangeDP(int coins[], int amt, int coinsSize) {
return res;
}
/* Coin change: Space-optimized dynamic programming */
/* Coin change: space-optimized dynamic programming */
int coinChangeDPComp(int coins[], int amt, int coinsSize) {
int n = coinsSize;
int MAX = amt + 1;
// Initialize dp table
// Initialize the dp table
int *dp = malloc((amt + 1) * sizeof(int));
for (int j = 1; j <= amt; j++) {
dp[j] = MAX;
}
dp[0] = 0;
// State transition
// State transitions
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// If exceeds target amount, don't select coin i
// If the coin exceeds the target amount, do not choose coin i
dp[a] = dp[a];
} else {
// The smaller value between not selecting and selecting coin i
// Take the smaller result of not choosing and choosing coin i
dp[a] = myMin(dp[a], dp[a - coins[i - 1]] + 1);
}
}
@@ -82,11 +82,11 @@ int main() {
// Dynamic programming
int res = coinChangeDP(coins, amt, coinsSize);
printf("Minimum number of coins needed to make target amount is %d\n", res);
printf("Minimum number of coins needed to make the target amount: %d\n", res);
// Space-optimized dynamic programming
res = coinChangeDPComp(coins, amt, coinsSize);
printf("Minimum number of coins needed to make target amount is %d\n", res);
printf("Minimum number of coins needed to make the target amount: %d\n", res);
return 0;
}

View File

@@ -6,26 +6,26 @@
#include "../utils/common.h"
/* Coin change II: Dynamic programming */
/* Coin change II: dynamic programming */
int coinChangeIIDP(int coins[], int amt, int coinsSize) {
int n = coinsSize;
// Initialize dp table
// Initialize the dp table
int **dp = malloc((n + 1) * sizeof(int *));
for (int i = 0; i <= n; i++) {
dp[i] = calloc(amt + 1, sizeof(int));
}
// Initialize first column
// Initialize the first column
for (int i = 0; i <= n; i++) {
dp[i][0] = 1;
}
// State transition
// State transitions
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// If exceeds target amount, don't select coin i
// If the coin exceeds the target amount, do not choose coin i
dp[i][a] = dp[i - 1][a];
} else {
// Sum of the two options: not selecting and selecting coin i
// Add the numbers of ways without and with coin i
dp[i][a] = dp[i - 1][a] + dp[i][a - coins[i - 1]];
}
}
@@ -39,20 +39,20 @@ int coinChangeIIDP(int coins[], int amt, int coinsSize) {
return res;
}
/* Coin change II: Space-optimized dynamic programming */
/* Coin change II: space-optimized dynamic programming */
int coinChangeIIDPComp(int coins[], int amt, int coinsSize) {
int n = coinsSize;
// Initialize dp table
// Initialize the dp table
int *dp = calloc(amt + 1, sizeof(int));
dp[0] = 1;
// State transition
// State transitions
for (int i = 1; i <= n; i++) {
for (int a = 1; a <= amt; a++) {
if (coins[i - 1] > a) {
// If exceeds target amount, don't select coin i
// If the coin exceeds the target amount, do not choose coin i
dp[a] = dp[a];
} else {
// Sum of the two options: not selecting and selecting coin i
// Add the numbers of ways without and with coin i
dp[a] = dp[a] + dp[a - coins[i - 1]];
}
}
@@ -71,11 +71,11 @@ int main() {
// Dynamic programming
int res = coinChangeIIDP(coins, amt, coinsSize);
printf("Number of coin combinations to make target amount is %d\n", res);
printf("Number of coin combinations that make the target amount: %d\n", res);
// Space-optimized dynamic programming
res = coinChangeIIDPComp(coins, amt, coinsSize);
printf("Number of coin combinations to make target amount is %d\n", res);
printf("Number of coin combinations that make the target amount: %d\n", res);
return 0;
}

View File

@@ -6,80 +6,80 @@
#include "../utils/common.h"
/* Find minimum value */
/* Find the minimum */
int myMin(int a, int b) {
return a < b ? a : b;
}
/* Edit distance: Brute-force search */
/* Edit distance: brute-force search */
int editDistanceDFS(char *s, char *t, int i, int j) {
// If both s and t are empty, return 0
// If both prefixes s[0:i] and t[0:j] are empty, return 0
if (i == 0 && j == 0)
return 0;
// If s is empty, return length of t
// If the prefix s[0:i] is empty, return j, the length of t[0:j]
if (i == 0)
return j;
// If t is empty, return length of s
// If the prefix t[0:j] is empty, return i, the length of s[0:i]
if (j == 0)
return i;
// If two characters are equal, skip both characters
// If the two characters are equal, skip both of them
if (s[i - 1] == t[j - 1])
return editDistanceDFS(s, t, i - 1, j - 1);
// Minimum edit steps = minimum edit steps of insert, delete, replace + 1
// Minimum edits = the minimum among the insertion, deletion, and replacement subproblems + 1
int insert = editDistanceDFS(s, t, i, j - 1);
int del = editDistanceDFS(s, t, i - 1, j);
int replace = editDistanceDFS(s, t, i - 1, j - 1);
// Return minimum edit steps
// Return the minimum number of edits
return myMin(myMin(insert, del), replace) + 1;
}
/* Edit distance: Memoization search */
/* Edit distance: memoized search */
int editDistanceDFSMem(char *s, char *t, int memCols, int **mem, int i, int j) {
// If both s and t are empty, return 0
// If both prefixes s[0:i] and t[0:j] are empty, return 0
if (i == 0 && j == 0)
return 0;
// If s is empty, return length of t
// If the prefix s[0:i] is empty, return j, the length of t[0:j]
if (i == 0)
return j;
// If t is empty, return length of s
// If the prefix t[0:j] is empty, return i, the length of s[0:i]
if (j == 0)
return i;
// If there's a record, return it directly
// If a result has already been recorded, return it directly
if (mem[i][j] != -1)
return mem[i][j];
// If two characters are equal, skip both characters
// If the two characters are equal, skip both of them
if (s[i - 1] == t[j - 1])
return editDistanceDFSMem(s, t, memCols, mem, i - 1, j - 1);
// Minimum edit steps = minimum edit steps of insert, delete, replace + 1
// Minimum edits = the minimum among the insertion, deletion, and replacement subproblems + 1
int insert = editDistanceDFSMem(s, t, memCols, mem, i, j - 1);
int del = editDistanceDFSMem(s, t, memCols, mem, i - 1, j);
int replace = editDistanceDFSMem(s, t, memCols, mem, i - 1, j - 1);
// Record and return minimum edit steps
// Record and return the minimum number of edits
mem[i][j] = myMin(myMin(insert, del), replace) + 1;
return mem[i][j];
}
/* Edit distance: Dynamic programming */
/* Edit distance: dynamic programming */
int editDistanceDP(char *s, char *t, int n, int m) {
int **dp = malloc((n + 1) * sizeof(int *));
for (int i = 0; i <= n; i++) {
dp[i] = calloc(m + 1, sizeof(int));
}
// State transition: first row and first column
// State transitions: first row and first column
for (int i = 1; i <= n; i++) {
dp[i][0] = i;
}
for (int j = 1; j <= m; j++) {
dp[0][j] = j;
}
// State transition: rest of the rows and columns
// State transitions: remaining rows and columns
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (s[i - 1] == t[j - 1]) {
// If two characters are equal, skip both characters
// If the two characters are equal, skip both of them
dp[i][j] = dp[i - 1][j - 1];
} else {
// Minimum edit steps = minimum edit steps of insert, delete, replace + 1
// Minimum edits = the minimum among the insertion, deletion, and replacement subproblems + 1
dp[i][j] = myMin(myMin(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1;
}
}
@@ -92,29 +92,29 @@ int editDistanceDP(char *s, char *t, int n, int m) {
return res;
}
/* Edit distance: Space-optimized dynamic programming */
/* Edit distance: space-optimized dynamic programming */
int editDistanceDPComp(char *s, char *t, int n, int m) {
int *dp = calloc(m + 1, sizeof(int));
// State transition: first row
// State transitions: first row
for (int j = 1; j <= m; j++) {
dp[j] = j;
}
// State transition: rest of the rows
// State transitions: remaining rows
for (int i = 1; i <= n; i++) {
// State transition: first column
// State transitions: first column
int leftup = dp[0]; // Temporarily store dp[i-1, j-1]
dp[0] = i;
// State transition: rest of the columns
// State transitions: remaining columns
for (int j = 1; j <= m; j++) {
int temp = dp[j];
if (s[i - 1] == t[j - 1]) {
// If two characters are equal, skip both characters
// If the two characters are equal, skip both of them
dp[j] = leftup;
} else {
// Minimum edit steps = minimum edit steps of insert, delete, replace + 1
// Minimum edits = the minimum among the insertion, deletion, and replacement subproblems + 1
dp[j] = myMin(myMin(dp[j - 1], dp[j]), leftup) + 1;
}
leftup = temp; // Update for next round's dp[i-1, j-1]
leftup = temp; // Update to dp[i-1, j-1] for the next iteration
}
}
int res = dp[m];
@@ -123,7 +123,7 @@ int editDistanceDPComp(char *s, char *t, int n, int m) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
char *s = "bag";
char *t = "pack";
@@ -131,16 +131,16 @@ int main() {
// Brute-force search
int res = editDistanceDFS(s, t, n, m);
printf("Changing %s to %s requires a minimum of %d edits\n", s, t, res);
printf("Changing %s to %s requires at least %d edits\n", s, t, res);
// Memoization search
// Memoized search
int **mem = malloc((n + 1) * sizeof(int *));
for (int i = 0; i <= n; i++) {
mem[i] = malloc((m + 1) * sizeof(int));
memset(mem[i], -1, (m + 1) * sizeof(int));
}
res = editDistanceDFSMem(s, t, m + 1, mem, n, m);
printf("Changing %s to %s requires a minimum of %d edits\n", s, t, res);
printf("Changing %s to %s requires at least %d edits\n", s, t, res);
// Free memory
for (int i = 0; i <= n; i++) {
free(mem[i]);
@@ -149,11 +149,11 @@ int main() {
// Dynamic programming
res = editDistanceDP(s, t, n, m);
printf("Changing %s to %s requires a minimum of %d edits\n", s, t, res);
printf("Changing %s to %s requires at least %d edits\n", s, t, res);
// Space-optimized dynamic programming
res = editDistanceDPComp(s, t, n, m);
printf("Changing %s to %s requires a minimum of %d edits\n", s, t, res);
printf("Changing %s to %s requires at least %d edits\n", s, t, res);
return 0;
}

View File

@@ -6,66 +6,66 @@
#include "../utils/common.h"
/* Find maximum value */
/* Find the maximum */
int myMax(int a, int b) {
return a > b ? a : b;
}
/* 0-1 knapsack: Brute-force search */
/* 0-1 knapsack: brute-force search */
int knapsackDFS(int wgt[], int val[], int i, int c) {
// If all items have been selected or knapsack has no remaining capacity, return value 0
// If all items have been considered or no capacity remains, return value 0
if (i == 0 || c == 0) {
return 0;
}
// If exceeds knapsack capacity, can only choose not to put it in
// If the item exceeds the remaining capacity, it must be excluded
if (wgt[i - 1] > c) {
return knapsackDFS(wgt, val, i - 1, c);
}
// Calculate the maximum value of not putting in and putting in item i
// Calculate the maximum values obtained by excluding and including item i
int no = knapsackDFS(wgt, val, i - 1, c);
int yes = knapsackDFS(wgt, val, i - 1, c - wgt[i - 1]) + val[i - 1];
// Return the larger value of the two options
// Return the larger value from the two choices
return myMax(no, yes);
}
/* 0-1 knapsack: Memoization search */
/* 0-1 knapsack: memoized search */
int knapsackDFSMem(int wgt[], int val[], int memCols, int **mem, int i, int c) {
// If all items have been selected or knapsack has no remaining capacity, return value 0
// If all items have been considered or no capacity remains, return value 0
if (i == 0 || c == 0) {
return 0;
}
// If there's a record, return it directly
// If a result has already been recorded, return it directly
if (mem[i][c] != -1) {
return mem[i][c];
}
// If exceeds knapsack capacity, can only choose not to put it in
// If the item exceeds the remaining capacity, it must be excluded
if (wgt[i - 1] > c) {
return knapsackDFSMem(wgt, val, memCols, mem, i - 1, c);
}
// Calculate the maximum value of not putting in and putting in item i
// Calculate the maximum values obtained by excluding and including item i
int no = knapsackDFSMem(wgt, val, memCols, mem, i - 1, c);
int yes = knapsackDFSMem(wgt, val, memCols, mem, i - 1, c - wgt[i - 1]) + val[i - 1];
// Record and return the larger value of the two options
// Record and return the larger value from the two choices
mem[i][c] = myMax(no, yes);
return mem[i][c];
}
/* 0-1 knapsack: Dynamic programming */
/* 0-1 knapsack: dynamic programming */
int knapsackDP(int wgt[], int val[], int cap, int wgtSize) {
int n = wgtSize;
// Initialize dp table
// Initialize the dp table
int **dp = malloc((n + 1) * sizeof(int *));
for (int i = 0; i <= n; i++) {
dp[i] = calloc(cap + 1, sizeof(int));
}
// State transition
// State transitions
for (int i = 1; i <= n; i++) {
for (int c = 1; c <= cap; c++) {
if (wgt[i - 1] > c) {
// If exceeds knapsack capacity, don't select item i
// If item i exceeds the remaining capacity, do not choose it
dp[i][c] = dp[i - 1][c];
} else {
// The larger value between not selecting and selecting item i
// Take the larger value obtained by excluding and including item i
dp[i][c] = myMax(dp[i - 1][c], dp[i - 1][c - wgt[i - 1]] + val[i - 1]);
}
}
@@ -78,17 +78,17 @@ int knapsackDP(int wgt[], int val[], int cap, int wgtSize) {
return res;
}
/* 0-1 knapsack: Space-optimized dynamic programming */
/* 0-1 knapsack: space-optimized dynamic programming */
int knapsackDPComp(int wgt[], int val[], int cap, int wgtSize) {
int n = wgtSize;
// Initialize dp table
// Initialize the dp table
int *dp = calloc(cap + 1, sizeof(int));
// State transition
// State transitions
for (int i = 1; i <= n; i++) {
// Traverse in reverse order
// Traverse in decreasing order
for (int c = cap; c >= 1; c--) {
if (wgt[i - 1] <= c) {
// The larger value between not selecting and selecting item i
// Take the larger value obtained by excluding and including item i
dp[c] = myMax(dp[c], dp[c - wgt[i - 1]] + val[i - 1]);
}
}
@@ -99,7 +99,7 @@ int knapsackDPComp(int wgt[], int val[], int cap, int wgtSize) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
int wgt[] = {10, 20, 30, 40, 50};
int val[] = {50, 120, 150, 210, 240};
@@ -109,16 +109,16 @@ int main() {
// Brute-force search
int res = knapsackDFS(wgt, val, n, cap);
printf("Maximum item value not exceeding knapsack capacity is %d\n", res);
printf("Maximum item value within the knapsack capacity: %d\n", res);
// Memoization search
// Memoized search
int **mem = malloc((n + 1) * sizeof(int *));
for (int i = 0; i <= n; i++) {
mem[i] = malloc((cap + 1) * sizeof(int));
memset(mem[i], -1, (cap + 1) * sizeof(int));
}
res = knapsackDFSMem(wgt, val, cap + 1, mem, n, cap);
printf("Maximum item value not exceeding knapsack capacity is %d\n", res);
printf("Maximum item value within the knapsack capacity: %d\n", res);
// Free memory
for (int i = 0; i <= n; i++) {
free(mem[i]);
@@ -127,11 +127,11 @@ int main() {
// Dynamic programming
res = knapsackDP(wgt, val, cap, wgtSize);
printf("Maximum item value not exceeding knapsack capacity is %d\n", res);
printf("Maximum item value within the knapsack capacity: %d\n", res);
// Space-optimized dynamic programming
res = knapsackDPComp(wgt, val, cap, wgtSize);
printf("Maximum item value not exceeding knapsack capacity is %d\n", res);
printf("Maximum item value within the knapsack capacity: %d\n", res);
return 0;
}

View File

@@ -6,22 +6,22 @@
#include "../utils/common.h"
/* Find minimum value */
/* Find the minimum */
int myMin(int a, int b) {
return a < b ? a : b;
}
/* Minimum cost climbing stairs: Dynamic programming */
/* Minimum cost to climb stairs: dynamic programming */
int minCostClimbingStairsDP(int cost[], int costSize) {
int n = costSize - 1;
if (n == 1 || n == 2)
return cost[n];
// Initialize dp table, used to store solutions to subproblems
// Initialize the dp table to store subproblem solutions
int *dp = calloc(n + 1, sizeof(int));
// Initial state: preset the solution to the smallest subproblem
// Initial states: set the solutions to the smallest subproblems
dp[1] = cost[1];
dp[2] = cost[2];
// State transition: gradually solve larger subproblems from smaller ones
// State transitions: solve progressively larger subproblems using smaller ones
for (int i = 3; i <= n; i++) {
dp[i] = myMin(dp[i - 1], dp[i - 2]) + cost[i];
}
@@ -31,7 +31,7 @@ int minCostClimbingStairsDP(int cost[], int costSize) {
return res;
}
/* Minimum cost climbing stairs: Space-optimized dynamic programming */
/* Minimum cost to climb stairs: space-optimized dynamic programming */
int minCostClimbingStairsDPComp(int cost[], int costSize) {
int n = costSize - 1;
if (n == 1 || n == 2)
@@ -45,18 +45,18 @@ int minCostClimbingStairsDPComp(int cost[], int costSize) {
return b;
}
/* Driver Code */
/* Driver code */
int main() {
int cost[] = {0, 1, 10, 1, 1, 1, 10, 1, 1, 10, 1};
int costSize = sizeof(cost) / sizeof(cost[0]);
printf("Input stair cost list is:");
printf("Input list of stair costs:");
printArray(cost, costSize);
int res = minCostClimbingStairsDP(cost, costSize);
printf("Minimum cost to climb stairs is %d\n", res);
printf("Minimum cost to climb the stairs: %d\n", res);
res = minCostClimbingStairsDPComp(cost, costSize);
printf("Minimum cost to climb stairs is %d\n", res);
printf("Minimum cost to climb the stairs: %d\n", res);
return 0;
}

View File

@@ -6,70 +6,70 @@
#include "../utils/common.h"
// Assume max matrix rows and columns is 100
// Assume the matrix has at most 100 rows and 100 columns
#define MAX_SIZE 100
/* Find minimum value */
/* Find the minimum */
int myMin(int a, int b) {
return a < b ? a : b;
}
/* Minimum path sum: Brute-force search */
/* Minimum path sum: brute-force search */
int minPathSumDFS(int grid[MAX_SIZE][MAX_SIZE], int i, int j) {
// If it's the top-left cell, terminate the search
// Stop searching at the top-left cell
if (i == 0 && j == 0) {
return grid[0][0];
}
// If row or column index is out of bounds, return +∞ cost
// If a row or column index is out of bounds, return a cost of +∞
if (i < 0 || j < 0) {
return INT_MAX;
}
// Calculate the minimum path cost from top-left to (i-1, j) and (i, j-1)
// Calculate the minimum path costs from the top-left corner to (i-1, j) and (i, j-1)
int up = minPathSumDFS(grid, i - 1, j);
int left = minPathSumDFS(grid, i, j - 1);
// Return the minimum path cost from top-left to (i, j)
// Return the minimum path cost from the top-left corner to (i, j)
return myMin(left, up) != INT_MAX ? myMin(left, up) + grid[i][j] : INT_MAX;
}
/* Minimum path sum: Memoization search */
/* Minimum path sum: memoized search */
int minPathSumDFSMem(int grid[MAX_SIZE][MAX_SIZE], int mem[MAX_SIZE][MAX_SIZE], int i, int j) {
// If it's the top-left cell, terminate the search
// Stop searching at the top-left cell
if (i == 0 && j == 0) {
return grid[0][0];
}
// If row or column index is out of bounds, return +∞ cost
// If a row or column index is out of bounds, return a cost of +∞
if (i < 0 || j < 0) {
return INT_MAX;
}
// If there's a record, return it directly
// If a result has already been recorded, return it directly
if (mem[i][j] != -1) {
return mem[i][j];
}
// Minimum path cost for left and upper cells
// Minimum path costs to the cells on the left and above
int up = minPathSumDFSMem(grid, mem, i - 1, j);
int left = minPathSumDFSMem(grid, mem, i, j - 1);
// Record and return the minimum path cost from top-left to (i, j)
// Record and return the minimum path cost from the top-left corner to (i, j)
mem[i][j] = myMin(left, up) != INT_MAX ? myMin(left, up) + grid[i][j] : INT_MAX;
return mem[i][j];
}
/* Minimum path sum: Dynamic programming */
/* Minimum path sum: dynamic programming */
int minPathSumDP(int grid[MAX_SIZE][MAX_SIZE], int n, int m) {
// Initialize dp table
// Initialize the dp table
int **dp = malloc(n * sizeof(int *));
for (int i = 0; i < n; i++) {
dp[i] = calloc(m, sizeof(int));
}
dp[0][0] = grid[0][0];
// State transition: first row
// State transitions: first row
for (int j = 1; j < m; j++) {
dp[0][j] = dp[0][j - 1] + grid[0][j];
}
// State transition: first column
// State transitions: first column
for (int i = 1; i < n; i++) {
dp[i][0] = dp[i - 1][0] + grid[i][0];
}
// State transition: rest of the rows and columns
// State transitions: remaining rows and columns
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
dp[i][j] = myMin(dp[i][j - 1], dp[i - 1][j]) + grid[i][j];
@@ -83,20 +83,20 @@ int minPathSumDP(int grid[MAX_SIZE][MAX_SIZE], int n, int m) {
return res;
}
/* Minimum path sum: Space-optimized dynamic programming */
/* Minimum path sum: space-optimized dynamic programming */
int minPathSumDPComp(int grid[MAX_SIZE][MAX_SIZE], int n, int m) {
// Initialize dp table
// Initialize the dp table
int *dp = calloc(m, sizeof(int));
// State transition: first row
// State transitions: first row
dp[0] = grid[0][0];
for (int j = 1; j < m; j++) {
dp[j] = dp[j - 1] + grid[0][j];
}
// State transition: rest of the rows
// State transitions: remaining rows
for (int i = 1; i < n; i++) {
// State transition: first column
// State transitions: first column
dp[0] = dp[0] + grid[i][0];
// State transition: rest of the columns
// State transitions: remaining columns
for (int j = 1; j < m; j++) {
dp[j] = myMin(dp[j - 1], dp[j]) + grid[i][j];
}
@@ -107,28 +107,28 @@ int minPathSumDPComp(int grid[MAX_SIZE][MAX_SIZE], int n, int m) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
int grid[MAX_SIZE][MAX_SIZE] = {{1, 3, 1, 5}, {2, 2, 4, 2}, {5, 3, 2, 1}, {4, 3, 5, 2}};
int n = 4, m = 4; // Matrix capacity is MAX_SIZE * MAX_SIZE, valid rows and columns are n * m
int n = 4, m = 4; // The matrix capacity is MAX_SIZE * MAX_SIZE; the active region has n rows and m columns
// Brute-force search
int res = minPathSumDFS(grid, n - 1, m - 1);
printf("Minimum path sum from top-left to bottom-right is %d\n", res);
printf("Minimum path sum from the top-left to the bottom-right corner: %d\n", res);
// Memoization search
// Memoized search
int mem[MAX_SIZE][MAX_SIZE];
memset(mem, -1, sizeof(mem));
res = minPathSumDFSMem(grid, mem, n - 1, m - 1);
printf("Minimum path sum from top-left to bottom-right is %d\n", res);
printf("Minimum path sum from the top-left to the bottom-right corner: %d\n", res);
// Dynamic programming
res = minPathSumDP(grid, n, m);
printf("Minimum path sum from top-left to bottom-right is %d\n", res);
printf("Minimum path sum from the top-left to the bottom-right corner: %d\n", res);
// Space-optimized dynamic programming
res = minPathSumDPComp(grid, n, m);
printf("Minimum path sum from top-left to bottom-right is %d\n", res);
printf("Minimum path sum from the top-left to the bottom-right corner: %d\n", res);
return 0;
}

View File

@@ -6,27 +6,27 @@
#include "../utils/common.h"
/* Find maximum value */
/* Find the maximum */
int myMax(int a, int b) {
return a > b ? a : b;
}
/* Unbounded knapsack: Dynamic programming */
/* Unbounded knapsack: dynamic programming */
int unboundedKnapsackDP(int wgt[], int val[], int cap, int wgtSize) {
int n = wgtSize;
// Initialize dp table
// Initialize the dp table
int **dp = malloc((n + 1) * sizeof(int *));
for (int i = 0; i <= n; i++) {
dp[i] = calloc(cap + 1, sizeof(int));
}
// State transition
// State transitions
for (int i = 1; i <= n; i++) {
for (int c = 1; c <= cap; c++) {
if (wgt[i - 1] > c) {
// If exceeds knapsack capacity, don't select item i
// If item i exceeds the remaining capacity, do not choose it
dp[i][c] = dp[i - 1][c];
} else {
// The larger value between not selecting and selecting item i
// Take the larger value obtained by excluding and including item i
dp[i][c] = myMax(dp[i - 1][c], dp[i][c - wgt[i - 1]] + val[i - 1]);
}
}
@@ -39,19 +39,19 @@ int unboundedKnapsackDP(int wgt[], int val[], int cap, int wgtSize) {
return res;
}
/* Unbounded knapsack: Space-optimized dynamic programming */
/* Unbounded knapsack: space-optimized dynamic programming */
int unboundedKnapsackDPComp(int wgt[], int val[], int cap, int wgtSize) {
int n = wgtSize;
// Initialize dp table
// Initialize the dp table
int *dp = calloc(cap + 1, sizeof(int));
// State transition
// State transitions
for (int i = 1; i <= n; i++) {
for (int c = 1; c <= cap; c++) {
if (wgt[i - 1] > c) {
// If exceeds knapsack capacity, don't select item i
// If item i exceeds the remaining capacity, do not choose it
dp[c] = dp[c];
} else {
// The larger value between not selecting and selecting item i
// Take the larger value obtained by excluding and including item i
dp[c] = myMax(dp[c], dp[c - wgt[i - 1]] + val[i - 1]);
}
}
@@ -71,11 +71,11 @@ int main() {
// Dynamic programming
int res = unboundedKnapsackDP(wgt, val, cap, wgtSize);
printf("Maximum item value not exceeding knapsack capacity is %d\n", res);
printf("Maximum item value within the knapsack capacity: %d\n", res);
// Space-optimized dynamic programming
res = unboundedKnapsackDPComp(wgt, val, cap, wgtSize);
printf("Maximum item value not exceeding knapsack capacity is %d\n", res);
printf("Maximum item value within the knapsack capacity: %d\n", res);
return 0;
}

View File

@@ -6,19 +6,19 @@
#include "../utils/common.h"
// Assume max node count is 100
// Assume at most 100 vertices
#define MAX_SIZE 100
/* Node structure */
/* Adjacency-list node structure */
typedef struct AdjListNode {
Vertex *vertex; // Vertex
struct AdjListNode *next; // Successor node
struct AdjListNode *next; // Next node
} AdjListNode;
/* Undirected graph class based on adjacency list */
/* Undirected graph structure implemented with an adjacency list */
typedef struct {
AdjListNode *heads[MAX_SIZE]; // Node array
int size; // Node count
AdjListNode *heads[MAX_SIZE]; // Array of list heads
int size; // Number of vertices
} GraphAdjList;
/* Constructor */
@@ -51,7 +51,7 @@ void delGraphAdjList(GraphAdjList *graph) {
free(graph);
}
/* Find node corresponding to vertex */
/* Find the list node corresponding to a vertex */
AdjListNode *findNode(GraphAdjList *graph, Vertex *vet) {
for (int i = 0; i < graph->size; i++) {
if (graph->heads[i]->vertex == vet) {
@@ -61,16 +61,16 @@ AdjListNode *findNode(GraphAdjList *graph, Vertex *vet) {
return NULL;
}
/* Add edge helper function */
/* Helper for adding an edge */
void addEdgeHelper(AdjListNode *head, Vertex *vet) {
AdjListNode *node = (AdjListNode *)malloc(sizeof(AdjListNode));
node->vertex = vet;
// Head insertion
// Insert at the front of the neighbor list
node->next = head->next;
head->next = node;
}
/* Add edge */
/* Add an edge */
void addEdge(GraphAdjList *graph, Vertex *vet1, Vertex *vet2) {
AdjListNode *head1 = findNode(graph, vet1);
AdjListNode *head2 = findNode(graph, vet2);
@@ -80,24 +80,24 @@ void addEdge(GraphAdjList *graph, Vertex *vet1, Vertex *vet2) {
addEdgeHelper(head2, vet1);
}
/* Remove edge helper function */
/* Helper for removing an edge */
void removeEdgeHelper(AdjListNode *head, Vertex *vet) {
AdjListNode *pre = head;
AdjListNode *cur = head->next;
// Search for node corresponding to vet in list
// Search the linked list for the node corresponding to vet
while (cur != NULL && cur->vertex != vet) {
pre = cur;
cur = cur->next;
}
if (cur == NULL)
return;
// Remove node corresponding to vet from list
// Remove the node corresponding to vet from the linked list
pre->next = cur->next;
// Free memory
free(cur);
}
/* Remove edge */
/* Remove an edge */
void removeEdge(GraphAdjList *graph, Vertex *vet1, Vertex *vet2) {
AdjListNode *head1 = findNode(graph, vet1);
AdjListNode *head2 = findNode(graph, vet2);
@@ -107,28 +107,28 @@ void removeEdge(GraphAdjList *graph, Vertex *vet1, Vertex *vet2) {
removeEdgeHelper(head2, head1->vertex);
}
/* Add vertex */
/* Add a vertex */
void addVertex(GraphAdjList *graph, Vertex *vet) {
assert(graph != NULL && graph->size < MAX_SIZE);
AdjListNode *head = (AdjListNode *)malloc(sizeof(AdjListNode));
head->vertex = vet;
head->next = NULL;
// Add a new linked list in the adjacency list
// Add a new list to the adjacency list
graph->heads[graph->size++] = head;
}
/* Remove vertex */
/* Remove a vertex */
void removeVertex(GraphAdjList *graph, Vertex *vet) {
AdjListNode *node = findNode(graph, vet);
assert(node != NULL);
// Remove the linked list corresponding to vertex vet in the adjacency list
// Remove the list corresponding to vertex vet from the adjacency list
AdjListNode *cur = node, *pre = NULL;
while (cur) {
pre = cur;
cur = cur->next;
free(pre);
}
// Traverse the linked lists of other vertices and remove all edges containing vet
// Traverse the lists of the other vertices and remove all edges incident to vet
for (int i = 0; i < graph->size; i++) {
cur = graph->heads[i];
pre = NULL;
@@ -142,7 +142,7 @@ void removeVertex(GraphAdjList *graph, Vertex *vet) {
}
}
}
// Move vertices after this vertex forward to fill gap
// Shift subsequent vertices forward to fill the gap
int i;
for (i = 0; i < graph->size; i++) {
if (graph->heads[i] == node)
@@ -155,7 +155,7 @@ void removeVertex(GraphAdjList *graph, Vertex *vet) {
free(vet);
}
/* Print adjacency list */
/* Print the adjacency list */
void printGraph(const GraphAdjList *graph) {
printf("Adjacency list =\n");
for (int i = 0; i < graph->size; ++i) {

View File

@@ -6,7 +6,7 @@
#include "graph_adjacency_list.c"
/* Driver Code */
/* Driver code */
int main() {
int vals[] = {1, 3, 2, 5, 4};
int size = sizeof(vals) / sizeof(vals[0]);
@@ -21,31 +21,31 @@ int main() {
for (int i = 0; i < egdeSize; i++) {
addEdge(graph, edges[i][0], edges[i][1]);
}
printf("\nAfter initialization, graph is\n");
printf("\nGraph after initialization:\n");
printGraph(graph);
/* Add edge */
// Vertices 1, 3 are v[0], v[1]
/* Add an edge */
// Vertices 1 and 2 are v[0] and v[2]
addEdge(graph, v[0], v[2]);
printf("\nAfter adding edge 1-2, graph is\n");
printf("\nGraph after adding edge 1-2:\n");
printGraph(graph);
/* Remove edge */
// Vertex 3 is v[1]
/* Remove an edge */
// Vertices 1 and 3 are v[0] and v[1]
removeEdge(graph, v[0], v[1]);
printf("\nAfter deleting edge 1-3, graph is\n");
printf("\nGraph after removing edge 1-3:\n");
printGraph(graph);
/* Add vertex */
/* Add a vertex */
Vertex *v5 = newVertex(6);
addVertex(graph, v5);
printf("\nAfter adding vertex 6, graph is\n");
printf("\nGraph after adding vertex 6:\n");
printGraph(graph);
/* Remove vertex */
/* Remove a vertex */
// Vertex 3 is v[1]
removeVertex(graph, v[1]);
printf("\nAfter deleting vertex 3, graph is:\n");
printf("\nGraph after removing vertex 3:\n");
printGraph(graph);
// Free memory

View File

@@ -6,10 +6,10 @@
#include "../utils/common.h"
// Assume max vertex count is 100
// Assume at most 100 vertices
#define MAX_SIZE 100
/* Undirected graph structure based on adjacency matrix */
/* Undirected graph structure implemented with an adjacency matrix */
typedef struct {
int vertices[MAX_SIZE];
int adjMat[MAX_SIZE][MAX_SIZE];
@@ -33,13 +33,13 @@ void delGraphAdjMat(GraphAdjMat *graph) {
free(graph);
}
/* Add vertex */
/* Add a vertex */
void addVertex(GraphAdjMat *graph, int val) {
if (graph->size == MAX_SIZE) {
fprintf(stderr, "Graph vertex count has reached maximum\n");
fprintf(stderr, "The graph has reached its maximum number of vertices\n");
return;
}
// Add nth vertex and zero nth row and column
// Add the vertex at index n and set row n and column n to zero
int n = graph->size;
graph->vertices[n] = val;
for (int i = 0; i <= n; i++) {
@@ -48,23 +48,23 @@ void addVertex(GraphAdjMat *graph, int val) {
graph->size++;
}
/* Remove vertex */
/* Remove a vertex */
void removeVertex(GraphAdjMat *graph, int index) {
if (index < 0 || index >= graph->size) {
fprintf(stderr, "Vertex index out of bounds\n");
return;
}
// Remove the vertex at index from the vertex list
// Remove the vertex at index `index` from the vertex list
for (int i = index; i < graph->size - 1; i++) {
graph->vertices[i] = graph->vertices[i + 1];
}
// Remove the row at index from the adjacency matrix
// Remove row `index` from the adjacency matrix
for (int i = index; i < graph->size - 1; i++) {
for (int j = 0; j < graph->size; j++) {
graph->adjMat[i][j] = graph->adjMat[i + 1][j];
}
}
// Remove the column at index from the adjacency matrix
// Remove column `index` from the adjacency matrix
for (int i = 0; i < graph->size; i++) {
for (int j = index; j < graph->size - 1; j++) {
graph->adjMat[i][j] = graph->adjMat[i][j + 1];
@@ -73,29 +73,29 @@ void removeVertex(GraphAdjMat *graph, int index) {
graph->size--;
}
/* Add edge */
// Parameters i, j correspond to the vertices element indices
/* Add an edge */
// Parameters i and j are element indices in vertices
void addEdge(GraphAdjMat *graph, int i, int j) {
if (i < 0 || j < 0 || i >= graph->size || j >= graph->size || i == j) {
fprintf(stderr, "Edge index out of bounds or equal\n");
fprintf(stderr, "Edge endpoint indices are out of bounds or equal\n");
return;
}
graph->adjMat[i][j] = 1;
graph->adjMat[j][i] = 1;
}
/* Remove edge */
// Parameters i, j correspond to the vertices element indices
/* Remove an edge */
// Parameters i and j are element indices in vertices
void removeEdge(GraphAdjMat *graph, int i, int j) {
if (i < 0 || j < 0 || i >= graph->size || j >= graph->size || i == j) {
fprintf(stderr, "Edge index out of bounds or equal\n");
fprintf(stderr, "Edge endpoint indices are out of bounds or equal\n");
return;
}
graph->adjMat[i][j] = 0;
graph->adjMat[j][i] = 0;
}
/* Print adjacency matrix */
/* Print the adjacency matrix */
void printGraphAdjMat(GraphAdjMat *graph) {
printf("Vertex list = ");
printArray(graph->vertices, graph->size);
@@ -105,9 +105,9 @@ void printGraphAdjMat(GraphAdjMat *graph) {
}
}
/* Driver Code */
/* Driver code */
int main() {
// Add edge
// Initialize the undirected graph
GraphAdjMat *graph = newGraphAdjMat();
int vertices[] = {1, 3, 2, 5, 4};
for (int i = 0; i < 5; i++) {
@@ -117,30 +117,30 @@ int main() {
for (int i = 0; i < 6; i++) {
addEdge(graph, edges[i][0], edges[i][1]);
}
printf("\nAfter initialization, graph is\n");
printf("\nGraph after initialization:\n");
printGraphAdjMat(graph);
/* Add edge */
// Add vertex
/* Add an edge */
// Vertices 1 and 2 have indices 0 and 2, respectively
addEdge(graph, 0, 2);
printf("\nAfter adding edge 1-2, graph is\n");
printf("\nGraph after adding edge 1-2:\n");
printGraphAdjMat(graph);
/* Remove edge */
// Vertices 1, 3 have indices 0, 1 respectively
/* Remove an edge */
// Vertices 1 and 3 have indices 0 and 1, respectively
removeEdge(graph, 0, 1);
printf("\nAfter deleting edge 1-3, graph is\n");
printf("\nGraph after removing edge 1-3:\n");
printGraphAdjMat(graph);
/* Add vertex */
/* Add a vertex */
addVertex(graph, 6);
printf("\nAfter adding vertex 6, graph is\n");
printf("\nGraph after adding vertex 6:\n");
printGraphAdjMat(graph);
/* Remove vertex */
/* Remove a vertex */
// Vertex 3 has index 1
removeVertex(graph, 1);
printf("\nAfter deleting vertex 3, graph is\n");
printf("\nGraph after removing vertex 3:\n");
printGraphAdjMat(graph);
// Free memory

View File

@@ -6,10 +6,10 @@
#include "graph_adjacency_list.c"
// Assume max node count is 100
// Assume at most 100 vertices
#define MAX_SIZE 100
/* Node queue structure */
/* Vertex queue structure */
typedef struct {
Vertex *vertices[MAX_SIZE];
int front, rear, size;
@@ -22,7 +22,7 @@ Queue *newQueue() {
return q;
}
/* Check if the queue is empty */
/* Check whether the queue is empty */
int isEmpty(Queue *q) {
return q->size == 0;
}
@@ -42,9 +42,9 @@ Vertex *dequeue(Queue *q) {
return vet;
}
/* Check if vertex has been visited */
/* Check whether a vertex has been visited */
int isVisited(Vertex **visited, int size, Vertex *vet) {
// Traverse to find node using O(n) time
// Search for the vertex with a linear scan in O(n) time
for (int i = 0; i < size; i++) {
if (visited[i] == vet)
return 1;
@@ -53,22 +53,22 @@ int isVisited(Vertex **visited, int size, Vertex *vet) {
}
/* Breadth-first traversal */
// Use adjacency list to represent the graph, in order to obtain all adjacent vertices of a specified vertex
// Represent the graph with an adjacency list to access all neighbors of a given vertex
void graphBFS(GraphAdjList *graph, Vertex *startVet, Vertex **res, int *resSize, Vertex **visited, int *visitedSize) {
// Queue used to implement BFS
// Use a queue to implement BFS
Queue *queue = newQueue();
enqueue(queue, startVet);
visited[(*visitedSize)++] = startVet;
// Starting from vertex vet, loop until all vertices are visited
// Starting from startVet, continue until all reachable vertices have been visited
while (!isEmpty(queue)) {
Vertex *vet = dequeue(queue); // Dequeue the front vertex
res[(*resSize)++] = vet; // Record visited vertex
// Traverse all adjacent vertices of this vertex
res[(*resSize)++] = vet; // Record the visited vertex
// Traverse all neighbors of this vertex
AdjListNode *node = findNode(graph, vet);
while (node != NULL) {
// Skip vertices that have been visited
// Skip vertices that have already been visited
if (!isVisited(visited, *visitedSize, node->vertex)) {
enqueue(queue, node->vertex); // Only enqueue unvisited vertices
enqueue(queue, node->vertex); // Enqueue only unvisited vertices
visited[(*visitedSize)++] = node->vertex; // Mark this vertex as visited
}
node = node->next;
@@ -78,9 +78,9 @@ void graphBFS(GraphAdjList *graph, Vertex *startVet, Vertex **res, int *resSize,
free(queue);
}
/* Driver Code */
/* Driver code */
int main() {
// Add edge
// Initialize the undirected graph
int vals[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int size = sizeof(vals) / sizeof(vals[0]);
Vertex **v = valsToVets(vals, size);
@@ -95,18 +95,18 @@ int main() {
for (int i = 0; i < egdeSize; i++) {
addEdge(graph, edges[i][0], edges[i][1]);
}
printf("\nAfter initialization, graph is\n");
printf("\nGraph after initialization:\n");
printGraph(graph);
// Breadth-first traversal
// Vertex traversal sequence
Vertex *res[MAX_SIZE];
int resSize = 0;
// Used to record visited vertices
// Track vertices that have already been visited
Vertex *visited[MAX_SIZE];
int visitedSize = 0;
graphBFS(graph, v[0], res, &resSize, visited, &visitedSize);
printf("\nBreadth-first traversal (BFS) vertex sequence is\n");
printf("\nVertex sequence from breadth-first traversal (BFS):\n");
printArray(vetsToVals(res, resSize), resSize);
// Free memory

View File

@@ -6,12 +6,12 @@
#include "graph_adjacency_list.c"
// Assume max node count is 100
// Assume at most 100 vertices
#define MAX_SIZE 100
/* Check if vertex has been visited */
/* Check whether a vertex has been visited */
int isVisited(Vertex **res, int size, Vertex *vet) {
// Traverse to find node using O(n) time
// Search for the vertex with a linear scan in O(n) time
for (int i = 0; i < size; i++) {
if (res[i] == vet) {
return 1;
@@ -22,14 +22,14 @@ int isVisited(Vertex **res, int size, Vertex *vet) {
/* Depth-first traversal helper function */
void dfs(GraphAdjList *graph, Vertex **res, int *resSize, Vertex *vet) {
// Record visited vertex
// Record the visited vertex
res[(*resSize)++] = vet;
// Traverse all adjacent vertices of this vertex
// Traverse all neighbors of this vertex
AdjListNode *node = findNode(graph, vet);
while (node != NULL) {
// Skip vertices that have been visited
// Skip vertices that have already been visited
if (!isVisited(res, *resSize, node->vertex)) {
// Recursively visit adjacent vertices
// Recursively visit the neighboring vertex
dfs(graph, res, resSize, node->vertex);
}
node = node->next;
@@ -37,14 +37,14 @@ void dfs(GraphAdjList *graph, Vertex **res, int *resSize, Vertex *vet) {
}
/* Depth-first traversal */
// Use adjacency list to represent the graph, in order to obtain all adjacent vertices of a specified vertex
// Represent the graph with an adjacency list to access all neighbors of a given vertex
void graphDFS(GraphAdjList *graph, Vertex *startVet, Vertex **res, int *resSize) {
dfs(graph, res, resSize, startVet);
}
/* Driver Code */
/* Driver code */
int main() {
// Add edge
// Initialize the undirected graph
int vals[] = {0, 1, 2, 3, 4, 5, 6};
int size = sizeof(vals) / sizeof(vals[0]);
Vertex **v = valsToVets(vals, size);
@@ -58,14 +58,14 @@ int main() {
for (int i = 0; i < egdeSize; i++) {
addEdge(graph, edges[i][0], edges[i][1]);
}
printf("\nAfter initialization, graph is\n");
printf("\nGraph after initialization:\n");
printGraph(graph);
// Depth-first traversal
Vertex *res[MAX_SIZE];
int resSize = 0;
graphDFS(graph, v[0], res, &resSize);
printf("\nDepth-first traversal (DFS) vertex sequence is\n");
printf("\nVertex sequence from depth-first traversal (DFS):\n");
printArray(vetsToVals(res, resSize), resSize);
// Free memory

View File

@@ -6,14 +6,14 @@
#include "../utils/common.h"
/* Coin change: Greedy algorithm */
/* Coin change: greedy algorithm */
int coinChangeGreedy(int *coins, int size, int amt) {
// Assume coins list is sorted
// Assume the coins list is sorted
int i = size - 1;
int count = 0;
// Loop to make greedy choices until no remaining amount
// Repeatedly make greedy choices until no amount remains
while (amt > 0) {
// Find the coin that is less than and closest to the remaining amount
// Find the largest coin no greater than the remaining amount
while (i > 0 && coins[i] > amt) {
i--;
}
@@ -21,40 +21,40 @@ int coinChangeGreedy(int *coins, int size, int amt) {
amt -= coins[i];
count++;
}
// If no feasible solution is found, return -1
// Return -1 if no feasible solution was found
return amt == 0 ? count : -1;
}
/* Driver Code */
/* Driver code */
int main() {
// Greedy algorithm: Can guarantee finding the global optimal solution
// Greedy algorithm: guaranteed to find a globally optimal solution
int coins1[6] = {1, 5, 10, 20, 50, 100};
int amt = 186;
int res = coinChangeGreedy(coins1, 6, amt);
printf("\ncoins = ");
printArray(coins1, 6);
printf("amt = %d\n", amt);
printf("Minimum number of coins needed to make %d is %d\n", amt, res);
printf("Greedy coin count for amount %d: %d\n", amt, res);
// Greedy algorithm: Cannot guarantee finding the global optimal solution
// Greedy algorithm: not guaranteed to find a globally optimal solution
int coins2[3] = {1, 20, 50};
amt = 60;
res = coinChangeGreedy(coins2, 3, amt);
printf("\ncoins = ");
printArray(coins2, 3);
printf("amt = %d\n", amt);
printf("Minimum number of coins needed to make %d is %d\n", amt, res);
printf("Actually minimum needed is 3, i.e., 20 + 20 + 20\n");
printf("Greedy coin count for amount %d: %d\n", amt, res);
printf("The actual minimum is 3 coins: 20 + 20 + 20\n");
// Greedy algorithm: Cannot guarantee finding the global optimal solution
// Greedy algorithm: not guaranteed to find a globally optimal solution
int coins3[3] = {1, 49, 50};
amt = 98;
res = coinChangeGreedy(coins3, 3, amt);
printf("\ncoins = ");
printArray(coins3, 3);
printf("amt = %d\n", amt);
printf("Minimum number of coins needed to make %d is %d\n", amt, res);
printf("Actually minimum needed is 2, i.e., 49 + 49\n");
printf("Greedy coin count for amount %d: %d\n", amt, res);
printf("The actual minimum is 2 coins: 49 + 49\n");
return 0;
}

View File

@@ -12,31 +12,31 @@ typedef struct {
int v; // Item value
} Item;
/* Sort by value density */
/* Sort by value per unit weight */
int sortByValueDensity(const void *a, const void *b) {
Item *t1 = (Item *)a;
Item *t2 = (Item *)b;
return (float)(t1->v) / t1->w < (float)(t2->v) / t2->w;
}
/* Fractional knapsack: Greedy algorithm */
/* Fractional knapsack: greedy algorithm */
float fractionalKnapsack(int wgt[], int val[], int itemCount, int cap) {
// Create item list with two attributes: weight, value
// Create a list of items, each with two attributes: weight and value
Item *items = malloc(sizeof(Item) * itemCount);
for (int i = 0; i < itemCount; i++) {
items[i] = (Item){.w = wgt[i], .v = val[i]};
}
// Sort by unit value item.v / item.w from high to low
// Sort by value per unit weight, item.v / item.w, in descending order
qsort(items, (size_t)itemCount, sizeof(Item), sortByValueDensity);
// Loop for greedy selection
// Repeatedly make greedy choices
float res = 0.0;
for (int i = 0; i < itemCount; i++) {
if (items[i].w <= cap) {
// If remaining capacity is sufficient, put the entire current item into the knapsack
// If enough capacity remains, put the entire current item in the knapsack
res += items[i].v;
cap -= items[i].w;
} else {
// If remaining capacity is insufficient, put part of the current item into the knapsack
// If the remaining capacity is insufficient, put part of the current item in the knapsack
res += (float)cap / items[i].w * items[i].v;
cap = 0;
break;
@@ -46,7 +46,7 @@ float fractionalKnapsack(int wgt[], int val[], int itemCount, int cap) {
return res;
}
/* Driver Code */
/* Driver code */
int main(void) {
int wgt[] = {10, 20, 30, 40, 50};
int val[] = {50, 120, 150, 210, 240};
@@ -54,7 +54,7 @@ int main(void) {
// Greedy algorithm
float res = fractionalKnapsack(wgt, val, sizeof(wgt) / sizeof(int), capacity);
printf("Maximum item value not exceeding knapsack capacity is %0.2f\n", res);
printf("Maximum item value within the knapsack capacity: %0.2f\n", res);
return 0;
}

View File

@@ -6,28 +6,28 @@
#include "../utils/common.h"
/* Find minimum value */
/* Find the minimum */
int myMin(int a, int b) {
return a < b ? a : b;
}
/* Find maximum value */
/* Find the maximum */
int myMax(int a, int b) {
return a > b ? a : b;
}
/* Max capacity: Greedy algorithm */
/* Maximum container capacity: greedy algorithm */
int maxCapacity(int ht[], int htLength) {
// Initialize i, j to be at both ends of the array
// Initialize i and j at opposite ends of the array
int i = 0;
int j = htLength - 1;
// Initial max capacity is 0
// The initial maximum capacity is 0
int res = 0;
// Loop for greedy selection until the two boards meet
// Repeatedly make greedy choices until the two sides meet
while (i < j) {
// Update max capacity
// Update the maximum capacity
int capacity = myMin(ht[i], ht[j]) * (j - i);
res = myMax(res, capacity);
// Move the shorter board inward
// Move the shorter side inward
if (ht[i] < ht[j]) {
i++;
} else {
@@ -37,13 +37,13 @@ int maxCapacity(int ht[], int htLength) {
return res;
}
/* Driver Code */
/* Driver code */
int main(void) {
int ht[] = {3, 8, 5, 2, 7, 7, 3, 4};
// Greedy algorithm
int res = maxCapacity(ht, sizeof(ht) / sizeof(int));
printf("Maximum capacity is %d\n", res);
printf("Maximum capacity: %d\n", res);
return 0;
}

View File

@@ -6,33 +6,33 @@
#include "../utils/common.h"
/* Max product cutting: Greedy algorithm */
/* Maximum product after splitting: greedy algorithm */
int maxProductCutting(int n) {
// When n <= 3, must cut out a 1
// When n <= 3, one part must be 1
if (n <= 3) {
return 1 * (n - 1);
}
// Greedily cut out 3, a is the number of 3s, b is the remainder
// Greedily split off parts of size 3; a is the number of 3s and b is the remainder
int a = n / 3;
int b = n % 3;
if (b == 1) {
// When the remainder is 1, convert a pair of 1 * 3 to 2 * 2
// When the remainder is 1, replace one pair 1 * 3 with 2 * 2
return pow(3, a - 1) * 2 * 2;
}
if (b == 2) {
// When the remainder is 2, do nothing
// When the remainder is 2, no adjustment is needed
return pow(3, a) * 2;
}
// When the remainder is 0, do nothing
// When the remainder is 0, no adjustment is needed
return pow(3, a);
}
/* Driver Code */
/* Driver code */
int main(void) {
int n = 58;
// Greedy algorithm
int res = maxProductCutting(n);
printf("Maximum cutting product is %d\n", res);
printf("Maximum product after splitting: %d\n", res);
return 0;
}

View File

@@ -9,7 +9,7 @@
/* Default hash table size */
#define MAX_SIZE 100
/* Key-value pair int->string */
/* Key-value pair: int -> string */
typedef struct {
int key;
char *val;
@@ -21,7 +21,7 @@ typedef struct {
int len;
} MapSet;
/* Hash table based on array implementation */
/* Hash table implemented with an array */
typedef struct {
Pair *buckets[MAX_SIZE];
} ArrayHashMap;
@@ -52,7 +52,7 @@ int hashFunc(int key) {
return index;
}
/* Query operation */
/* Lookup operation */
const char *get(const ArrayHashMap *hmap, const int key) {
int index = hashFunc(key);
const Pair *Pair = hmap->buckets[index];
@@ -61,7 +61,7 @@ const char *get(const ArrayHashMap *hmap, const int key) {
return Pair->val;
}
/* Add operation */
/* Insert operation */
void put(ArrayHashMap *hmap, const int key, const char *val) {
Pair *Pair = malloc(sizeof(Pair));
Pair->key = key;
@@ -85,7 +85,7 @@ void pairSet(ArrayHashMap *hmap, MapSet *set) {
Pair *entries;
int i = 0, index = 0;
int total = 0;
/* Count valid key-value pairs */
/* Count stored key-value pairs */
for (i = 0; i < MAX_SIZE; i++) {
if (hmap->buckets[i] != NULL) {
total++;
@@ -109,7 +109,7 @@ void keySet(ArrayHashMap *hmap, MapSet *set) {
int *keys;
int i = 0, index = 0;
int total = 0;
/* Count valid key-value pairs */
/* Count stored key-value pairs */
for (i = 0; i < MAX_SIZE; i++) {
if (hmap->buckets[i] != NULL) {
total++;
@@ -131,7 +131,7 @@ void valueSet(ArrayHashMap *hmap, MapSet *set) {
char **vals;
int i = 0, index = 0;
int total = 0;
/* Count valid key-value pairs */
/* Count stored key-value pairs */
for (i = 0; i < MAX_SIZE; i++) {
if (hmap->buckets[i] != NULL) {
total++;
@@ -148,7 +148,7 @@ void valueSet(ArrayHashMap *hmap, MapSet *set) {
set->len = total;
}
/* Print hash table */
/* Print the hash table */
void print(ArrayHashMap *hmap) {
int i;
MapSet set;
@@ -160,43 +160,43 @@ void print(ArrayHashMap *hmap) {
free(set.set);
}
/* Driver Code */
/* Driver code */
int main() {
/* Initialize hash table */
/* Initialize the hash table */
ArrayHashMap *hmap = newArrayHashMap();
/* Add operation */
// Add key-value pair (key, value) to the hash table
put(hmap, 12836, "Xiao Ha");
put(hmap, 15937, "Xiao Luo");
put(hmap, 16750, "Xiao Suan");
put(hmap, 13276, "Xiao Fa");
put(hmap, 10583, "Xiao Ya");
printf("\nAfter addition, hash table is\nKey -> Value\n");
/* Insert operation */
// Insert the key-value pair (key, value) into the hash table
put(hmap, 12836, "小哈");
put(hmap, 15937, "小啰");
put(hmap, 16750, "小算");
put(hmap, 13276, "小法");
put(hmap, 10583, "小鸭");
printf("\nHash table after insertion:\nKey -> Value\n");
print(hmap);
/* Query operation */
// Input key into hash table to get value
/* Lookup operation */
// Look up key in the hash table to obtain value
const char *name = get(hmap, 15937);
printf("\nInput student ID 15937, found name %s\n", name);
printf("\nLook up student ID 15937; name found: %s\n", name);
/* Remove operation */
// Remove key-value pair (key, value) from hash table
// Remove the key-value pair (key, value) from the hash table
removeItem(hmap, 10583);
printf("\nAfter deleting 10583, hash table is\nKey -> Value\n");
printf("\nHash table after removing 10583:\nKey -> Value\n");
print(hmap);
/* Traverse hash table */
/* Traverse the hash table */
int i;
printf("\nTraverse key-value pairs Key->Value\n");
printf("\nIterate over key-value pairs, Key->Value\n");
print(hmap);
MapSet set;
keySet(hmap, &set);
int *keys = (int *)set.set;
printf("\nTraverse keys only Key\n");
printf("\nIterate over keys only, Key\n");
for (i = 0; i < set.len; i++) {
printf("%d\n", keys[i]);
}
@@ -204,7 +204,7 @@ int main() {
valueSet(hmap, &set);
char **vals = (char **)set.set;
printf("\nTraverse values only Value\n");
printf("\nIterate over values only, Value\n");
for (i = 0; i < set.len; i++) {
printf("%s\n", vals[i]);
}

View File

@@ -8,7 +8,7 @@
#include <stdlib.h>
#include <string.h>
// Assume max val length is 100
// Assume val has a maximum length of 100
#define MAX_SIZE 100
/* Key-value pair */
@@ -27,8 +27,8 @@ typedef struct Node {
typedef struct {
int size; // Number of key-value pairs
int capacity; // Hash table capacity
double loadThres; // Load factor threshold for triggering expansion
int extendRatio; // Expansion multiplier
double loadThres; // Load factor threshold that triggers capacity growth
int extendRatio; // Capacity growth factor
Node **buckets; // Bucket array
} HashMapChaining;
@@ -71,10 +71,10 @@ double loadFactor(HashMapChaining *hashMap) {
return (double)hashMap->size / (double)hashMap->capacity;
}
/* Query operation */
/* Lookup operation */
char *get(HashMapChaining *hashMap, int key) {
int index = hashFunc(hashMap, key);
// Traverse bucket, if key is found, return corresponding val
// Traverse the bucket; if key is found, return its corresponding val
Node *cur = hashMap->buckets[index];
while (cur) {
if (cur->pair->key == key) {
@@ -82,25 +82,25 @@ char *get(HashMapChaining *hashMap, int key) {
}
cur = cur->next;
}
return ""; // Return empty string if key not found
return ""; // Return an empty string if key is not found
}
/* Add operation */
/* Insert operation */
void put(HashMapChaining *hashMap, int key, const char *val);
/* Expand hash table */
/* Grow the hash table capacity */
void extend(HashMapChaining *hashMap) {
// Temporarily store the original hash table
// Keep a reference to the original hash table
int oldCapacity = hashMap->capacity;
Node **oldBuckets = hashMap->buckets;
// Initialize expanded new hash table
// Initialize a new hash table with the expanded capacity
hashMap->capacity *= hashMap->extendRatio;
hashMap->buckets = (Node **)malloc(hashMap->capacity * sizeof(Node *));
for (int i = 0; i < hashMap->capacity; i++) {
hashMap->buckets[i] = NULL;
}
hashMap->size = 0;
// Move key-value pairs from original hash table to new hash table
// Move the key-value pairs from the original hash table to the new one
for (int i = 0; i < oldCapacity; i++) {
Node *cur = oldBuckets[i];
while (cur) {
@@ -116,23 +116,23 @@ void extend(HashMapChaining *hashMap) {
free(oldBuckets);
}
/* Add operation */
/* Insert operation */
void put(HashMapChaining *hashMap, int key, const char *val) {
// When load factor exceeds threshold, perform expansion
// Grow the capacity when the load factor exceeds the threshold
if (loadFactor(hashMap) > hashMap->loadThres) {
extend(hashMap);
}
int index = hashFunc(hashMap, key);
// Traverse bucket, if specified key is encountered, update corresponding val and return
// Traverse the bucket; if the specified key is found, update its val and return
Node *cur = hashMap->buckets[index];
while (cur) {
if (cur->pair->key == key) {
strcpy(cur->pair->val, val); // If specified key is found, update corresponding val and return
strcpy(cur->pair->val, val); // If the specified key is found, update its val and return
return;
}
cur = cur->next;
}
// If key not found, add key-value pair to list head
// If key is absent, add the key-value pair at the head of the linked list
Pair *newPair = (Pair *)malloc(sizeof(Pair));
newPair->key = key;
strcpy(newPair->val, val);
@@ -150,7 +150,7 @@ void removeItem(HashMapChaining *hashMap, int key) {
Node *pre = NULL;
while (cur) {
if (cur->pair->key == key) {
// Remove key-value pair from it
// Remove the key-value pair from the list
if (pre) {
pre->next = cur->next;
} else {
@@ -167,7 +167,7 @@ void removeItem(HashMapChaining *hashMap, int key) {
}
}
/* Print hash table */
/* Print the hash table */
void print(HashMapChaining *hashMap) {
for (int i = 0; i < hashMap->capacity; i++) {
Node *cur = hashMap->buckets[i];
@@ -180,33 +180,33 @@ void print(HashMapChaining *hashMap) {
}
}
/* Driver Code */
/* Driver code */
int main() {
/* Initialize hash table */
/* Initialize the hash table */
HashMapChaining *hashMap = newHashMapChaining();
/* Add operation */
// Add key-value pair (key, value) to the hash table
put(hashMap, 12836, "Xiao Ha");
put(hashMap, 15937, "Xiao Luo");
put(hashMap, 16750, "Xiao Suan");
put(hashMap, 13276, "Xiao Fa");
put(hashMap, 10583, "Xiao Ya");
printf("\nAfter addition, hash table is\nKey -> Value\n");
/* Insert operation */
// Insert the key-value pair (key, value) into the hash table
put(hashMap, 12836, "小哈");
put(hashMap, 15937, "小啰");
put(hashMap, 16750, "小算");
put(hashMap, 13276, "小法");
put(hashMap, 10583, "小鸭");
printf("\nHash table after insertion:\nKey -> Value\n");
print(hashMap);
/* Query operation */
// Input key into hash table to get value
/* Lookup operation */
// Look up key in the hash table to obtain value
char *name = get(hashMap, 13276);
printf("\nInput student ID 13276, found name %s\n", name);
printf("\nLook up student ID 13276; name found: %s\n", name);
/* Remove operation */
// Remove key-value pair (key, value) from hash table
// Remove the key-value pair (key, value) from the hash table
removeItem(hashMap, 12836);
printf("\nAfter deleting student ID 12836, hash table is\nKey -> Value\n");
printf("\nHash table after removing student ID 12836:\nKey -> Value\n");
print(hashMap);
/* Free hash table space */
/* Free the hash table's memory */
delHashMapChaining(hashMap);
return 0;

View File

@@ -6,7 +6,7 @@
#include "../utils/common.h"
/* Hash table with open addressing */
/* Key-value pair */
typedef struct {
int key;
char *val;
@@ -16,10 +16,10 @@ typedef struct {
typedef struct {
int size; // Number of key-value pairs
int capacity; // Hash table capacity
double loadThres; // Load factor threshold for triggering expansion
int extendRatio; // Expansion multiplier
double loadThres; // Load factor threshold that triggers capacity growth
int extendRatio; // Capacity growth factor
Pair **buckets; // Bucket array
Pair *TOMBSTONE; // Removal marker
Pair *TOMBSTONE; // Tombstone marker
} HashMapOpenAddressing;
// Function declaration
@@ -64,54 +64,54 @@ double loadFactor(HashMapOpenAddressing *hashMap) {
return (double)hashMap->size / (double)hashMap->capacity;
}
/* Search for bucket index corresponding to key */
/* Find the bucket index for key */
int findBucket(HashMapOpenAddressing *hashMap, int key) {
int index = hashFunc(hashMap, key);
int firstTombstone = -1;
// Linear probing, break when encountering an empty bucket
// Probe linearly until an empty bucket is reached
while (hashMap->buckets[index] != NULL) {
// If key is encountered, return the corresponding bucket index
// If key is found, return its bucket index
if (hashMap->buckets[index]->key == key) {
// If a removal marker was encountered before, move the key-value pair to that index
// If a tombstone was encountered earlier, move the key-value pair to that index
if (firstTombstone != -1) {
hashMap->buckets[firstTombstone] = hashMap->buckets[index];
hashMap->buckets[index] = hashMap->TOMBSTONE;
return firstTombstone; // Return the moved bucket index
return firstTombstone; // Return the bucket index after the move
}
return index; // Return bucket index
return index; // Return the bucket index
}
// Record the first removal marker encountered
// Record the first tombstone encountered
if (firstTombstone == -1 && hashMap->buckets[index] == hashMap->TOMBSTONE) {
firstTombstone = index;
}
// Calculate bucket index, wrap around to the head if past the tail
// Calculate the bucket index, wrapping to the beginning after the end
index = (index + 1) % hashMap->capacity;
}
// If key does not exist, return the index for insertion
// If key is absent, return the index for insertion
return firstTombstone == -1 ? index : firstTombstone;
}
/* Query operation */
/* Lookup operation */
char *get(HashMapOpenAddressing *hashMap, int key) {
// Search for bucket index corresponding to key
// Find the bucket index for key
int index = findBucket(hashMap, key);
// If key-value pair is found, return corresponding val
// If the key-value pair is found, return its val
if (hashMap->buckets[index] != NULL && hashMap->buckets[index] != hashMap->TOMBSTONE) {
return hashMap->buckets[index]->val;
}
// Return empty string if key-value pair does not exist
// Return an empty string if the key-value pair does not exist
return "";
}
/* Add operation */
/* Insert operation */
void put(HashMapOpenAddressing *hashMap, int key, char *val) {
// When load factor exceeds threshold, perform expansion
// Grow the capacity when the load factor exceeds the threshold
if (loadFactor(hashMap) > hashMap->loadThres) {
extend(hashMap);
}
// Search for bucket index corresponding to key
// Find the bucket index for key
int index = findBucket(hashMap, key);
// If key-value pair is found, overwrite val and return
// If the key-value pair is found, overwrite val and return
if (hashMap->buckets[index] != NULL && hashMap->buckets[index] != hashMap->TOMBSTONE) {
free(hashMap->buckets[index]->val);
hashMap->buckets[index]->val = (char *)malloc(sizeof(strlen(val) + 1));
@@ -119,7 +119,7 @@ void put(HashMapOpenAddressing *hashMap, int key, char *val) {
hashMap->buckets[index]->val[strlen(val)] = '\0';
return;
}
// If key-value pair does not exist, add the key-value pair
// If the key-value pair is absent, insert it
Pair *pair = (Pair *)malloc(sizeof(Pair));
pair->key = key;
pair->val = (char *)malloc(sizeof(strlen(val) + 1));
@@ -132,9 +132,9 @@ void put(HashMapOpenAddressing *hashMap, int key, char *val) {
/* Remove operation */
void removeItem(HashMapOpenAddressing *hashMap, int key) {
// Search for bucket index corresponding to key
// Find the bucket index for key
int index = findBucket(hashMap, key);
// If key-value pair is found, overwrite it with removal marker
// If the key-value pair is found, replace it with a tombstone
if (hashMap->buckets[index] != NULL && hashMap->buckets[index] != hashMap->TOMBSTONE) {
Pair *pair = hashMap->buckets[index];
free(pair->val);
@@ -144,16 +144,16 @@ void removeItem(HashMapOpenAddressing *hashMap, int key) {
}
}
/* Expand hash table */
/* Grow the hash table capacity */
void extend(HashMapOpenAddressing *hashMap) {
// Temporarily store the original hash table
// Keep a reference to the original hash table
Pair **bucketsTmp = hashMap->buckets;
int oldCapacity = hashMap->capacity;
// Initialize expanded new hash table
// Initialize a new hash table with the expanded capacity
hashMap->capacity *= hashMap->extendRatio;
hashMap->buckets = (Pair **)calloc(hashMap->capacity, sizeof(Pair *));
hashMap->size = 0;
// Move key-value pairs from original hash table to new hash table
// Move the key-value pairs from the original hash table to the new one
for (int i = 0; i < oldCapacity; i++) {
Pair *pair = bucketsTmp[i];
if (pair != NULL && pair != hashMap->TOMBSTONE) {
@@ -165,7 +165,7 @@ void extend(HashMapOpenAddressing *hashMap) {
free(bucketsTmp);
}
/* Print hash table */
/* Print the hash table */
void print(HashMapOpenAddressing *hashMap) {
for (int i = 0; i < hashMap->capacity; i++) {
Pair *pair = hashMap->buckets[i];
@@ -179,33 +179,33 @@ void print(HashMapOpenAddressing *hashMap) {
}
}
/* Driver Code */
/* Driver code */
int main() {
// Initialize hash table
// Initialize the hash table
HashMapOpenAddressing *hashmap = newHashMapOpenAddressing();
// Add operation
// Add key-value pair (key, val) to the hash table
put(hashmap, 12836, "Xiao Ha");
put(hashmap, 15937, "Xiao Luo");
put(hashmap, 16750, "Xiao Suan");
put(hashmap, 13276, "Xiao Fa");
put(hashmap, 10583, "Xiao Ya");
printf("\nAfter addition, hash table is\nKey -> Value\n");
// Insert operation
// Insert the key-value pair (key, val) into the hash table
put(hashmap, 12836, "小哈");
put(hashmap, 15937, "小啰");
put(hashmap, 16750, "小算");
put(hashmap, 13276, "小法");
put(hashmap, 10583, "小鸭");
printf("\nHash table after insertion:\nKey -> Value\n");
print(hashmap);
// Query operation
// Input key into hash table to get value val
// Lookup operation
// Look up key in the hash table to obtain val
char *name = get(hashmap, 13276);
printf("\nInput student ID 13276, found name %s\n", name);
printf("\nLook up student ID 13276; name found: %s\n", name);
// Remove operation
// Remove key-value pair (key, val) from hash table
// Remove the key-value pair (key, val) from the hash table
removeItem(hashmap, 16750);
printf("\nAfter deleting 16750, hash table is\nKey -> Value\n");
printf("\nHash table after removing 16750:\nKey -> Value\n");
print(hashmap);
// Destroy hash table
// Destroy the hash table
delHashMapOpenAddressing(hashmap);
return 0;
}

View File

@@ -37,7 +37,7 @@ int xorHash(char *key) {
return hash & MODULUS;
}
/* Rotational hash */
/* Rotating hash */
int rotHash(char *key) {
long long hash = 0;
const int MODULUS = 1000000007;
@@ -48,21 +48,21 @@ int rotHash(char *key) {
return (int)hash;
}
/* Driver Code */
/* Driver code */
int main() {
char *key = "Hello Algo";
char *key = "Hello 算法";
int hash = addHash(key);
printf("Additive hash value is %d\n", hash);
printf("Additive hash value: %d\n", hash);
hash = mulHash(key);
printf("Multiplicative hash value is %d\n", hash);
printf("Multiplicative hash value: %d\n", hash);
hash = xorHash(key);
printf("XOR hash value is %d\n", hash);
printf("XOR hash value: %d\n", hash);
hash = rotHash(key);
printf("Rotational hash value is %d\n", hash);
printf("Rotation hash value: %d\n", hash);
return 0;
}

View File

@@ -10,9 +10,9 @@
/* Max heap */
typedef struct {
// size represents the actual number of elements
// size is the actual number of elements
int size;
// Use pre-allocated array to avoid expansion
// Use a preallocated array to avoid resizing
int data[MAX_SIZE];
} MaxHeap;
@@ -21,14 +21,14 @@ void siftDown(MaxHeap *maxHeap, int i);
void siftUp(MaxHeap *maxHeap, int i);
int parent(MaxHeap *maxHeap, int i);
/* Constructor, build heap from slice */
/* Constructor: build a heap from the input array */
MaxHeap *newMaxHeap(int nums[], int size) {
// Push all elements to heap
// Place all elements in the heap
MaxHeap *maxHeap = (MaxHeap *)malloc(sizeof(MaxHeap));
maxHeap->size = size;
memcpy(maxHeap->data, nums, size * sizeof(int));
for (int i = parent(maxHeap, size - 1); i >= 0; i--) {
// Heapify all nodes except leaf nodes
// Sift down from every non-leaf node
siftDown(maxHeap, i);
}
return maxHeap;
@@ -40,19 +40,19 @@ void delMaxHeap(MaxHeap *maxHeap) {
free(maxHeap);
}
/* Get index of left child node */
/* Get the left child index */
int left(MaxHeap *maxHeap, int i) {
return 2 * i + 1;
}
/* Get index of right child node */
/* Get the right child index */
int right(MaxHeap *maxHeap, int i) {
return 2 * i + 2;
}
/* Get index of parent node */
/* Get the parent index */
int parent(MaxHeap *maxHeap, int i) {
return (i - 1) / 2; // Round down
return (i - 1) / 2; // Integer division truncates toward zero
}
/* Swap elements */
@@ -62,59 +62,59 @@ void swap(MaxHeap *maxHeap, int i, int j) {
maxHeap->data[j] = temp;
}
/* Get heap size */
/* Get the heap size */
int size(MaxHeap *maxHeap) {
return maxHeap->size;
}
/* Check if heap is empty */
/* Check whether the heap is empty */
int isEmpty(MaxHeap *maxHeap) {
return maxHeap->size == 0;
}
/* Access top element */
/* Access the top element of the heap */
int peek(MaxHeap *maxHeap) {
return maxHeap->data[0];
}
/* Element enters heap */
/* Push an element onto the heap */
void push(MaxHeap *maxHeap, int val) {
// By default, should not add this many nodes
// Normally, the number of nodes should remain below this limit
if (maxHeap->size == MAX_SIZE) {
printf("heap is full!");
printf("Heap is full!");
return;
}
// Add node
// Add a node
maxHeap->data[maxHeap->size] = val;
maxHeap->size++;
// Heapify from bottom to top
// Sift up
siftUp(maxHeap, maxHeap->size - 1);
}
/* Element exits heap */
/* Pop an element from the heap */
int pop(MaxHeap *maxHeap) {
// Handle empty case
// Handle an empty heap
if (isEmpty(maxHeap)) {
printf("heap is empty!");
printf("Heap is empty!");
return INT_MAX;
}
// Delete node
// Swap the root with the rightmost leaf on the last level (swap the first and last elements)
swap(maxHeap, 0, size(maxHeap) - 1);
// Remove node
// Remove a node
int val = maxHeap->data[maxHeap->size - 1];
maxHeap->size--;
// Return top element
// Sift down
siftDown(maxHeap, 0);
// Return heap top element
// Return the top element of the heap
return val;
}
/* Starting from node i, heapify from top to bottom */
/* Sift down starting from node i */
void siftDown(MaxHeap *maxHeap, int i) {
while (true) {
// Find node with maximum value among nodes i, l, r, denoted as max
// Find the node with the largest value among i, l, and r, and store its index in max
int l = left(maxHeap, i);
int r = right(maxHeap, i);
int max = i;
@@ -124,29 +124,29 @@ void siftDown(MaxHeap *maxHeap, int i) {
if (r < size(maxHeap) && maxHeap->data[r] > maxHeap->data[max]) {
max = r;
}
// Swap two nodes
// Stop if node i is largest or both child indices l and r are out of bounds
if (max == i) {
break;
}
// Swap two nodes
// Swap the two nodes
swap(maxHeap, i, max);
// Loop downwards heapification
// Continue sifting down
i = max;
}
}
/* Starting from node i, heapify from bottom to top */
/* Sift up starting from node i */
void siftUp(MaxHeap *maxHeap, int i) {
while (true) {
// Get parent node of node i
// Get the parent of node i
int p = parent(maxHeap, i);
// When "crossing root node" or "node needs no repair", end heapify
// Stop sifting when the root has been passed or the node needs no repair
if (p < 0 || maxHeap->data[i] <= maxHeap->data[p]) {
break;
}
// Swap two nodes
// Swap the two nodes
swap(maxHeap, i, p);
// Loop upward heapify
// Continue sifting up
i = p;
}
}

View File

@@ -6,33 +6,33 @@
#include "my_heap.c"
/* Driver Code */
/* Driver code */
int main() {
/* Initialize heap */
// Consider negating the elements before entering the heap, which can reverse the size relationship, thus implementing max heap
/* Initialize the heap */
// Initialize a max heap
int nums[] = {9, 8, 6, 6, 7, 5, 2, 1, 4, 3, 6, 2};
MaxHeap *maxHeap = newMaxHeap(nums, sizeof(nums) / sizeof(int));
printf("After input array and building heap\n");
printf("After building a heap from the input array:\n");
printHeap(maxHeap->data, maxHeap->size);
/* Check if heap is empty */
printf("\nHeap top element is %d\n", peek(maxHeap));
/* Get the top element of the heap */
printf("\nTop element of the heap: %d\n", peek(maxHeap));
/* Element enters heap */
/* Push an element onto the heap */
push(maxHeap, 7);
printf("\nAfter element 7 pushes to heap\n");
printf("\nAfter pushing element 7 onto the heap:\n");
printHeap(maxHeap->data, maxHeap->size);
/* Time complexity is O(n), not O(nlogn) */
/* Pop the top element from the heap */
int top = pop(maxHeap);
printf("\nAfter heap top element %d exits heap\n", top);
printf("\nAfter popping top element %d from the heap:\n", top);
printHeap(maxHeap->data, maxHeap->size);
/* Get heap size */
printf("\nHeap element count is %d\n", size(maxHeap));
/* Get the heap size */
printf("\nNumber of elements in the heap: %d\n", size(maxHeap));
/* Check if heap is empty */
printf("\nIs heap empty %d\n", isEmpty(maxHeap));
/* Check whether the heap is empty */
printf("\nIs the heap empty: %d\n", isEmpty(maxHeap));
// Free memory
delMaxHeap(maxHeap);

View File

@@ -6,27 +6,27 @@
#include "my_heap.c"
/* Element enters heap */
/* Push an element onto the heap */
void pushMinHeap(MaxHeap *maxHeap, int val) {
// Negate element
// Negate the element
push(maxHeap, -val);
}
/* Element exits heap */
/* Pop an element from the heap */
int popMinHeap(MaxHeap *maxHeap) {
// Negate element
// Negate the element
return -pop(maxHeap);
}
/* Access top element */
/* Access the top element of the heap */
int peekMinHeap(MaxHeap *maxHeap) {
// Negate element
// Negate the element
return -peek(maxHeap);
}
/* Extract elements from heap */
/* Get the elements in the heap */
int *getMinHeap(MaxHeap *maxHeap) {
// Negate all heap elements and store in res array
// Negate every element in the heap and store the results in array res
int *res = (int *)malloc(maxHeap->size * sizeof(int));
for (int i = 0; i < maxHeap->size; i++) {
res[i] = -maxHeap->data[i];
@@ -34,19 +34,19 @@ int *getMinHeap(MaxHeap *maxHeap) {
return res;
}
// Function to find k largest elements in array using heap
// Use a heap to find the k largest elements in an array
int *topKHeap(int *nums, int sizeNums, int k) {
// Python's heapq module implements min heap by default
// Note: We negate all heap elements to simulate min heap using max heap
// Initialize a min heap
// Note: negate every element to simulate a min heap with a max heap
int *empty = (int *)malloc(0);
MaxHeap *maxHeap = newMaxHeap(empty, 0);
// Enter the first k elements of array into heap
// Push the first k array elements onto the heap
for (int i = 0; i < k; i++) {
pushMinHeap(maxHeap, nums[i]);
}
// Starting from the (k+1)th element, maintain heap length as k
// Starting with element k+1, keep the heap size at k
for (int i = k; i < sizeNums; i++) {
// If current element is greater than top element, top element exits heap, current element enters heap
// If the current element is larger than the heap top, pop the top element and push the current element
if (nums[i] > peekMinHeap(maxHeap)) {
popMinHeap(maxHeap);
pushMinHeap(maxHeap, nums[i]);
@@ -58,14 +58,14 @@ int *topKHeap(int *nums, int sizeNums, int k) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
int nums[] = {1, 7, 6, 3, 2};
int k = 3;
int sizeNums = sizeof(nums) / sizeof(nums[0]);
int *res = topKHeap(nums, sizeNums, k);
printf("The largest %d elements are: ", k);
printf("The %d largest elements are: ", k);
printArray(res, k);
free(res);

View File

@@ -6,52 +6,52 @@
#include "../utils/common.h"
/* Binary search (closed interval on both sides) */
/* Binary search (closed interval) */
int binarySearch(int *nums, int len, int target) {
// Initialize closed interval [0, n-1], i.e., i, j point to the first and last elements of the array
// Initialize the closed interval [0, n-1], with i and j pointing to the first and last elements
int i = 0, j = len - 1;
// Loop, exit when the search interval is empty (empty when i > j)
// Loop until the search interval is empty (when i > j)
while (i <= j) {
int m = i + (j - i) / 2; // Calculate the midpoint index m
if (nums[m] < target) // This means target is in the interval [m+1, j]
if (nums[m] < target) // In this case, target must be in [m+1, j] if it exists
i = m + 1;
else if (nums[m] > target) // This means target is in the interval [i, m-1]
else if (nums[m] > target) // In this case, target must be in [i, m-1] if it exists
j = m - 1;
else // Found the target element, return its index
else // The target element was found; return its index
return m;
}
// Target element not found, return -1
// The target element was not found; return -1
return -1;
}
/* Binary search (left-closed right-open interval) */
/* Binary search (left-closed, right-open interval) */
int binarySearchLCRO(int *nums, int len, int target) {
// Initialize left-closed right-open interval [0, n), i.e., i, j point to the first element and last element+1
// Initialize the left-closed, right-open interval [0, n), with i at the first element and j one past the last
int i = 0, j = len;
// Loop, exit when the search interval is empty (empty when i = j)
// Loop until the search interval is empty (when i = j)
while (i < j) {
int m = i + (j - i) / 2; // Calculate the midpoint index m
if (nums[m] < target) // This means target is in the interval [m+1, j)
if (nums[m] < target) // In this case, target must be in [m+1, j) if it exists
i = m + 1;
else if (nums[m] > target) // This means target is in the interval [i, m)
else if (nums[m] > target) // In this case, target must be in [i, m) if it exists
j = m;
else // Found the target element, return its index
else // The target element was found; return its index
return m;
}
// Target element not found, return -1
// The target element was not found; return -1
return -1;
}
/* Driver Code */
/* Driver code */
int main() {
int target = 6;
int nums[10] = {1, 3, 6, 8, 12, 15, 23, 26, 31, 35};
/* Binary search (closed interval on both sides) */
/* Binary search (closed interval) */
int index = binarySearch(nums, 10, target);
printf("Index of target element 6 = %d\n", index);
/* Binary search (left-closed right-open interval) */
/* Binary search (left-closed, right-open interval) */
index = binarySearchLCRO(nums, 10, target);
printf("Index of target element 6 = %d\n", index);

View File

@@ -6,61 +6,61 @@
#include "../utils/common.h"
/* Binary search for insertion point (with duplicate elements) */
/* Find an insertion point using binary search (with duplicates) */
int binarySearchInsertion(int *nums, int numSize, int target) {
int i = 0, j = numSize - 1; // Initialize closed interval [0, n-1]
int i = 0, j = numSize - 1; // Initialize the closed interval [0, n-1]
while (i <= j) {
int m = i + (j - i) / 2; // Calculate the midpoint index m
if (nums[m] < target) {
i = m + 1; // target is in the interval [m+1, j]
i = m + 1; // Target must be in [m+1, j] if it exists
} else {
j = m - 1; // The rightmost element less than target is in the interval [i, m-1]
j = m - 1; // Continue in [i, m-1] to find the rightmost element smaller than target
}
}
// Return insertion point i
return i;
}
/* Binary search for the leftmost target */
/* Find the leftmost occurrence of target using binary search */
int binarySearchLeftEdge(int *nums, int numSize, int target) {
// Equivalent to finding the insertion point of target
// This is equivalent to finding the insertion point of target
int i = binarySearchInsertion(nums, numSize, target);
// Target not found, return -1
// If target was not found, return -1
if (i == numSize || nums[i] != target) {
return -1;
}
// Found target, return index i
// Target was found; return index i
return i;
}
/* Binary search for the rightmost target */
/* Find the rightmost occurrence of target using binary search */
int binarySearchRightEdge(int *nums, int numSize, int target) {
// Convert to finding the leftmost target + 1
// Reduce the problem to finding the leftmost insertion point of target + 1
int i = binarySearchInsertion(nums, numSize, target + 1);
// j points to the rightmost target, i points to the first element greater than target
// j points to the rightmost target, while i points to the first element greater than target
int j = i - 1;
// Target not found, return -1
// If target was not found, return -1
if (j == -1 || nums[j] != target) {
return -1;
}
// Found target, return index j
// Target was found; return index j
return j;
}
/* Driver Code */
/* Driver code */
int main() {
// Array with duplicate elements
// Array containing duplicate elements
int nums[] = {1, 3, 6, 6, 6, 6, 6, 10, 12, 15};
printf("\nArray nums = ");
printArray(nums, sizeof(nums) / sizeof(nums[0]));
// Binary search left and right boundaries
// Find the left and right boundaries using binary search
int targets[] = {6, 7};
for (int i = 0; i < sizeof(targets) / sizeof(targets[0]); i++) {
int index = binarySearchLeftEdge(nums, sizeof(nums) / sizeof(nums[0]), targets[i]);
printf("Leftmost element %d index is %d\n", targets[i], index);
printf("Index of the leftmost occurrence of %d: %d\n", targets[i], index);
index = binarySearchRightEdge(nums, sizeof(nums) / sizeof(nums[0]), targets[i]);
printf("Rightmost element %d index is %d\n", targets[i], index);
printf("Index of the rightmost occurrence of %d: %d\n", targets[i], index);
}
return 0;

View File

@@ -6,62 +6,62 @@
#include "../utils/common.h"
/* Binary search for insertion point (no duplicate elements) */
/* Find an insertion point using binary search (no duplicates) */
int binarySearchInsertionSimple(int *nums, int numSize, int target) {
int i = 0, j = numSize - 1; // Initialize closed interval [0, n-1]
int i = 0, j = numSize - 1; // Initialize the closed interval [0, n-1]
while (i <= j) {
int m = i + (j - i) / 2; // Calculate the midpoint index m
if (nums[m] < target) {
i = m + 1; // target is in the interval [m+1, j]
i = m + 1; // Target must be in [m+1, j] if it exists
} else if (nums[m] > target) {
j = m - 1; // target is in the interval [i, m-1]
j = m - 1; // Target must be in [i, m-1] if it exists
} else {
return m; // Found target, return insertion point m
return m; // Target was found; return insertion point m
}
}
// Target not found, return insertion point i
// Target was not found; return insertion point i
return i;
}
/* Binary search for insertion point (with duplicate elements) */
/* Find an insertion point using binary search (with duplicates) */
int binarySearchInsertion(int *nums, int numSize, int target) {
int i = 0, j = numSize - 1; // Initialize closed interval [0, n-1]
int i = 0, j = numSize - 1; // Initialize the closed interval [0, n-1]
while (i <= j) {
int m = i + (j - i) / 2; // Calculate the midpoint index m
if (nums[m] < target) {
i = m + 1; // target is in the interval [m+1, j]
i = m + 1; // Target must be in [m+1, j] if it exists
} else if (nums[m] > target) {
j = m - 1; // target is in the interval [i, m-1]
j = m - 1; // Target must be in [i, m-1] if it exists
} else {
j = m - 1; // The rightmost element less than target is in the interval [i, m-1]
j = m - 1; // Continue in [i, m-1] to find the rightmost element smaller than target
}
}
// Return insertion point i
return i;
}
/* Driver Code */
/* Driver code */
int main() {
// Array without duplicate elements
// Array with no duplicate elements
int nums1[] = {1, 3, 6, 8, 12, 15, 23, 26, 31, 35};
printf("\nArray nums = ");
printArray(nums1, sizeof(nums1) / sizeof(nums1[0]));
// Binary search for insertion point
// Find an insertion point using binary search
int targets1[] = {6, 9};
for (int i = 0; i < sizeof(targets1) / sizeof(targets1[0]); i++) {
int index = binarySearchInsertionSimple(nums1, sizeof(nums1) / sizeof(nums1[0]), targets1[i]);
printf("Insertion point index for element %d is %d\n", targets1[i], index);
printf("Insertion index for element %d: %d\n", targets1[i], index);
}
// Array with duplicate elements
// Array containing duplicate elements
int nums2[] = {1, 3, 6, 6, 6, 6, 6, 10, 12, 15};
printf("\nArray nums = ");
printArray(nums2, sizeof(nums2) / sizeof(nums2[0]));
// Binary search for insertion point
// Find an insertion point using binary search
int targets2[] = {2, 6, 20};
for (int i = 0; i < sizeof(targets2) / sizeof(int); i++) {
int index = binarySearchInsertion(nums2, sizeof(nums2) / sizeof(nums2[0]), targets2[i]);
printf("Insertion point index for element %d is %d\n", targets2[i], index);
printf("Insertion index for element %d: %d\n", targets2[i], index);
}
return 0;

View File

@@ -6,7 +6,7 @@
#include "../utils/common.h"
/* Method 1: Brute force enumeration */
/* Method 1: brute-force enumeration */
int *twoSumBruteForce(int *nums, int numsSize, int target, int *returnSize) {
for (int i = 0; i < numsSize; ++i) {
for (int j = i + 1; j < numsSize; ++j) {
@@ -29,14 +29,14 @@ typedef struct {
UT_hash_handle hh; // Implemented using uthash.h
} HashTable;
/* Hash table lookup */
/* Look up a key in the hash table */
HashTable *find(HashTable *h, int key) {
HashTable *tmp;
HASH_FIND_INT(h, &key, tmp);
return tmp;
}
/* Hash table element insertion */
/* Insert an entry into the hash table */
void insert(HashTable **h, int key, int val) {
HashTable *t = find(*h, key);
if (t == NULL) {
@@ -48,7 +48,7 @@ void insert(HashTable **h, int key, int val) {
}
}
/* Method 2: Auxiliary hash table */
/* Method 2: auxiliary hash table */
int *twoSumHashTable(int *nums, int numsSize, int target, int *returnSize) {
HashTable *hashtable = NULL;
for (int i = 0; i < numsSize; i++) {
@@ -65,21 +65,21 @@ int *twoSumHashTable(int *nums, int numsSize, int target, int *returnSize) {
return NULL;
}
/* Driver Code */
/* Driver code */
int main() {
// ======= Test Case =======
// ======= Test case =======
int nums[] = {2, 7, 11, 15};
int target = 13;
// ====== Driver Code ======
// ====== Driver code ======
int returnSize;
int *res = twoSumBruteForce(nums, sizeof(nums) / sizeof(int), target, &returnSize);
// Method 1
printf("Method 1 res = ");
printf("Method 1: res = ");
printArray(res, returnSize);
// Method 2
res = twoSumHashTable(nums, sizeof(nums) / sizeof(int), target, &returnSize);
printf("Method 2 res = ");
printf("Method 2: res = ");
printArray(res, returnSize);
return 0;

View File

@@ -8,9 +8,9 @@
/* Bubble sort */
void bubbleSort(int nums[], int size) {
// Outer loop: unsorted range is [0, i]
// Outer loop: the unsorted range is [0, i]
for (int i = size - 1; i > 0; i--) {
// Inner loop: swap the largest element in the unsorted range [0, i] to the rightmost end of that range
// Inner loop: move the largest element in the unsorted range [0, i] to its right end through swaps
for (int j = 0; j < i; j++) {
if (nums[j] > nums[j + 1]) {
int temp = nums[j];
@@ -21,12 +21,12 @@ void bubbleSort(int nums[], int size) {
}
}
/* Bubble sort (flag optimization) */
/* Bubble sort (flag optimization)*/
void bubbleSortWithFlag(int nums[], int size) {
// Outer loop: unsorted range is [0, i]
// Outer loop: the unsorted range is [0, i]
for (int i = size - 1; i > 0; i--) {
bool flag = false;
// Inner loop: swap the largest element in the unsorted range [0, i] to the rightmost end of that range
// Inner loop: move the largest element in the unsorted range [0, i] to its right end through swaps
for (int j = 0; j < i; j++) {
if (nums[j] > nums[j + 1]) {
int temp = nums[j];
@@ -40,7 +40,7 @@ void bubbleSortWithFlag(int nums[], int size) {
}
}
/* Driver Code */
/* Driver code */
int main() {
int nums[6] = {4, 1, 3, 1, 5, 2};
printf("After bubble sort: ");

View File

@@ -18,14 +18,14 @@ int compare(const void *a, const void *b) {
/* Bucket sort */
void bucketSort(float nums[], int n) {
int k = n / 2; // Initialize k = n/2 buckets
int *sizes = malloc(k * sizeof(int)); // Record each bucket's size
int *sizes = malloc(k * sizeof(int)); // Record the size of each bucket
float **buckets = malloc(k * sizeof(float *)); // Array of dynamic arrays (buckets)
// Pre-allocate sufficient space for each bucket
// Preallocate enough space for each bucket
for (int i = 0; i < k; ++i) {
buckets[i] = (float *)malloc(n * sizeof(float));
sizes[i] = 0;
}
// 1. Distribute array elements into various buckets
// 1. Distribute the array elements among the buckets
for (int i = 0; i < n; ++i) {
int idx = (int)(nums[i] * k);
buckets[idx][sizes[idx]++] = nums[i];
@@ -34,7 +34,7 @@ void bucketSort(float nums[], int n) {
for (int i = 0; i < k; ++i) {
qsort(buckets[i], sizes[i], sizeof(float), compare);
}
// 3. Merge sorted buckets
// 3. Merge the sorted buckets
int idx = 0;
for (int i = 0; i < k; ++i) {
for (int j = 0; j < sizes[i]; ++j) {
@@ -45,12 +45,12 @@ void bucketSort(float nums[], int n) {
}
}
/* Driver Code */
/* Driver code */
int main() {
// Assume input data is floating point, interval [0, 1)
// Assume the input consists of floating-point numbers in [0, 1)
float nums[SIZE] = {0.49f, 0.96f, 0.82f, 0.09f, 0.57f, 0.43f, 0.91f, 0.75f, 0.15f, 0.37f};
bucketSort(nums, SIZE);
printf("After bucket sort completes, nums = ");
printf("After bucket sort, nums = ");
printArrayFloat(nums, SIZE);
return 0;

View File

@@ -7,22 +7,22 @@
#include "../utils/common.h"
/* Counting sort */
// Simple implementation, cannot be used for sorting objects
// Simple implementation; cannot be used to sort objects
void countingSortNaive(int nums[], int size) {
// 1. Count the maximum element m in the array
// 1. Find the maximum array element m
int m = 0;
for (int i = 0; i < size; i++) {
if (nums[i] > m) {
m = nums[i];
}
}
// 2. Count the occurrence of each number
// counter[num] represents the occurrence of num
// 2. Count the occurrences of each number
// counter[num] is the number of occurrences of num
int *counter = calloc(m + 1, sizeof(int));
for (int i = 0; i < size; i++) {
counter[nums[i]]++;
}
// 3. Traverse counter, filling each element back into the original array nums
// 3. Traverse counter and fill the original array nums with the elements
int i = 0;
for (int num = 0; num < m + 1; num++) {
for (int j = 0; j < counter[num]; j++, i++) {
@@ -34,53 +34,53 @@ void countingSortNaive(int nums[], int size) {
}
/* Counting sort */
// Complete implementation, can sort objects and is a stable sort
// Full, stable implementation; can be adapted to sort objects
void countingSort(int nums[], int size) {
// 1. Count the maximum element m in the array
// 1. Find the maximum array element m
int m = 0;
for (int i = 0; i < size; i++) {
if (nums[i] > m) {
m = nums[i];
}
}
// 2. Count the occurrence of each number
// counter[num] represents the occurrence of num
// 2. Count the occurrences of each number
// counter[num] is the number of occurrences of num
int *counter = calloc(m, sizeof(int));
for (int i = 0; i < size; i++) {
counter[nums[i]]++;
}
// 3. Calculate the prefix sum of counter, converting "occurrence count" to "tail index"
// counter[num]-1 is the last index where num appears in res
// 3. Compute prefix sums of counter to convert occurrence counts into end positions
// That is, counter[num]-1 is the index of the last occurrence of num in res
for (int i = 0; i < m; i++) {
counter[i + 1] += counter[i];
}
// 4. Traverse nums in reverse order, placing each element into the result array res
// Initialize the array res to record results
// 4. Traverse nums in reverse and place each element in the result array res
// Initialize array res to store the result
int *res = malloc(sizeof(int) * size);
for (int i = size - 1; i >= 0; i--) {
int num = nums[i];
res[counter[num] - 1] = num; // Place num at the corresponding index
counter[num]--; // Decrement the prefix sum by 1, getting the next index to place num
counter[num]--; // Decrement the prefix sum by 1 to determine where to place the next occurrence of num
}
// Use result array res to overwrite the original array nums
// Overwrite the original array nums with the result array res
memcpy(nums, res, size * sizeof(int));
// 5. Free memory
free(res);
free(counter);
}
/* Driver Code */
/* Driver code */
int main() {
int nums[] = {1, 0, 1, 2, 0, 4, 0, 2, 2, 4};
int size = sizeof(nums) / sizeof(int);
countingSortNaive(nums, size);
printf("After counting sort (cannot sort objects) completes, nums = ");
printf("After counting sort (without support for objects), nums = ");
printArray(nums, size);
int nums1[] = {1, 0, 1, 2, 0, 4, 0, 2, 2, 4};
int size1 = sizeof(nums1) / sizeof(int);
countingSort(nums1, size1);
printf("After counting sort completes, nums1 = ");
printf("After counting sort, nums1 = ");
printArray(nums1, size1);
return 0;

View File

@@ -6,10 +6,10 @@
#include "../utils/common.h"
/* Heap length is n, start heapifying node i, from top to bottom */
/* Sift down from node i in a heap of size n */
void siftDown(int nums[], int n, int i) {
while (1) {
// If node i is largest or indices l, r are out of bounds, no need to continue heapify, break
// Find the node with the largest value among i, l, and r, and store its index in ma
int l = 2 * i + 1;
int r = 2 * i + 2;
int ma = i;
@@ -17,43 +17,43 @@ void siftDown(int nums[], int n, int i) {
ma = l;
if (r < n && nums[r] > nums[ma])
ma = r;
// Swap two nodes
// Stop if node i is largest or both child indices l and r are out of bounds
if (ma == i) {
break;
}
// Swap two nodes
// Swap the two nodes
int temp = nums[i];
nums[i] = nums[ma];
nums[ma] = temp;
// Loop downwards heapification
// Continue sifting down
i = ma;
}
}
/* Heap sort */
void heapSort(int nums[], int n) {
// Build heap operation: heapify all nodes except leaves
// Build the heap by sifting down from every non-leaf node
for (int i = n / 2 - 1; i >= 0; --i) {
siftDown(nums, n, i);
}
// Extract the largest element from the heap and repeat for n-1 rounds
// Extract the largest element from the heap, repeating for n-1 rounds
for (int i = n - 1; i > 0; --i) {
// Delete node
// Swap the root with the rightmost leaf on the last level (the first and last elements of the current heap)
int tmp = nums[0];
nums[0] = nums[i];
nums[i] = tmp;
// Start heapifying the root node, from top to bottom
// Sift down starting at the root
siftDown(nums, i, 0);
}
}
/* Driver Code */
/* Driver code */
int main() {
int nums[] = {4, 1, 3, 1, 5, 2};
int n = sizeof(nums) / sizeof(nums[0]);
heapSort(nums, n);
printf("After heap sort completes, nums = ");
printf("After heap sort, nums = ");
printArray(nums, n);
return 0;

View File

@@ -8,25 +8,25 @@
/* Insertion sort */
void insertionSort(int nums[], int size) {
// Outer loop: sorted interval is [0, i-1]
// Outer loop: the sorted range is [0, i-1]
for (int i = 1; i < size; i++) {
int base = nums[i], j = i - 1;
// Inner loop: insert base into the correct position within the sorted interval [0, i-1]
// Inner loop: insert base at the correct position in the sorted range [0, i-1]
while (j >= 0 && nums[j] > base) {
// Move nums[j] to the right by one position
// Shift nums[j] one position to the right
nums[j + 1] = nums[j];
j--;
}
// Assign base to the correct position
// Place base at the correct position
nums[j + 1] = base;
}
}
/* Driver Code */
/* Driver code */
int main() {
int nums[] = {4, 1, 3, 1, 5, 2};
insertionSort(nums, 6);
printf("After insertion sort completes, nums = ");
printf("After insertion sort, nums = ");
for (int i = 0; i < 6; i++) {
printf("%d ", nums[i]);
}

View File

@@ -6,15 +6,15 @@
#include "../utils/common.h"
/* Merge left subarray and right subarray */
/* Merge the left and right subarrays */
void merge(int *nums, int left, int mid, int right) {
// Left subarray interval is [left, mid], right subarray interval is [mid+1, right]
// Create a temporary array tmp to store the merged results
// The left subarray spans [left, mid], and the right subarray spans [mid+1, right]
// Create a temporary array tmp to store the merged result
int tmpSize = right - left + 1;
int *tmp = (int *)malloc(tmpSize * sizeof(int));
// Initialize the start indices of the left and right subarrays
// Initialize the starting indices of the left and right subarrays
int i = left, j = mid + 1, k = 0;
// While both subarrays still have elements, compare and copy the smaller element into the temporary array
// While both subarrays have elements remaining, compare them and copy the smaller element into the temporary array
while (i <= mid && j <= right) {
if (nums[i] <= nums[j]) {
tmp[k++] = nums[i++];
@@ -29,7 +29,7 @@ void merge(int *nums, int left, int mid, int right) {
while (j <= right) {
tmp[k++] = nums[j++];
}
// Copy the elements from the temporary array tmp back to the original array nums at the corresponding interval
// Copy the elements of temporary array tmp back into the corresponding range of the original array nums
for (k = 0; k < tmpSize; ++k) {
nums[left + k] = tmp[k];
}
@@ -39,24 +39,24 @@ void merge(int *nums, int left, int mid, int right) {
/* Merge sort */
void mergeSort(int *nums, int left, int right) {
// Termination condition
// Base case
if (left >= right)
return; // Terminate recursion when subarray length is 1
// Divide and conquer stage
int mid = left + (right - left) / 2; // Calculate midpoint
mergeSort(nums, left, mid); // Recursively process the left subarray
mergeSort(nums, mid + 1, right); // Recursively process the right subarray
// Merge stage
return; // Stop recursing when the subarray has at most one element
// Divide phase
int mid = left + (right - left) / 2; // Calculate the midpoint
mergeSort(nums, left, mid); // Recurse on the left subarray
mergeSort(nums, mid + 1, right); // Recurse on the right subarray
// Merge phase
merge(nums, left, mid, right);
}
/* Driver Code */
/* Driver code */
int main() {
/* Merge sort */
int nums[] = {7, 3, 2, 6, 0, 1, 5, 4};
int size = sizeof(nums) / sizeof(int);
mergeSort(nums, 0, size - 1);
printf("After merge sort completes, nums = ");
printf("After merge sort, nums = ");
printArray(nums, size);
return 0;

View File

@@ -6,122 +6,122 @@
#include "../utils/common.h"
/* Swap elements */
/* Swap the elements */
void swap(int nums[], int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
/* Sentinel partition */
/* Two-pointer partitioning */
int partition(int nums[], int left, int right) {
// Use nums[left] as the pivot
int i = left, j = right;
while (i < j) {
while (i < j && nums[j] >= nums[left]) {
j--; // Search from right to left for the first element smaller than the pivot
j--; // Scan from right to left for the first element smaller than the pivot
}
while (i < j && nums[i] <= nums[left]) {
i++; // Search from left to right for the first element greater than the pivot
i++; // Scan from left to right for the first element larger than the pivot
}
// Swap these two elements
swap(nums, i, j);
}
// Swap the pivot to the boundary between the two subarrays
// Swap the pivot into the boundary position between the two subarrays
swap(nums, i, left);
// Return the index of the pivot
// Return the pivot index
return i;
}
/* Quick sort */
void quickSort(int nums[], int left, int right) {
// Terminate recursion when subarray length is 1
// Stop recursing when the subarray has at most one element
if (left >= right) {
return;
}
// Sentinel partition
// Two-pointer partitioning
int pivot = partition(nums, left, right);
// Recursively process the left subarray and right subarray
// Recurse on the left and right subarrays
quickSort(nums, left, pivot - 1);
quickSort(nums, pivot + 1, right);
}
// Quick sort with median-of-three optimization below
// Quick sort with median-of-three pivot optimization follows
/* Select the median of three candidate elements */
int medianThree(int nums[], int left, int mid, int right) {
int l = nums[left], m = nums[mid], r = nums[right];
if ((l <= m && m <= r) || (r <= m && m <= l))
return mid; // m is between l and r
return mid; // m lies between l and r
if ((m <= l && l <= r) || (r <= l && l <= m))
return left; // l is between m and r
return left; // l lies between m and r
return right;
}
/* Sentinel partition (median of three) */
/* Two-pointer partitioning (median of three) */
int partitionMedian(int nums[], int left, int right) {
// Select the median of three candidate elements
int med = medianThree(nums, left, (left + right) / 2, right);
// Swap the median to the array's leftmost position
// Swap the median into the leftmost position of the array
swap(nums, left, med);
// Use nums[left] as the pivot
int i = left, j = right;
while (i < j) {
while (i < j && nums[j] >= nums[left])
j--; // Search from right to left for the first element smaller than the pivot
j--; // Scan from right to left for the first element smaller than the pivot
while (i < j && nums[i] <= nums[left])
i++; // Search from left to right for the first element greater than the pivot
i++; // Scan from left to right for the first element larger than the pivot
swap(nums, i, j); // Swap these two elements
}
swap(nums, i, left); // Swap the pivot to the boundary between the two subarrays
return i; // Return the index of the pivot
swap(nums, i, left); // Swap the pivot into the boundary position between the two subarrays
return i; // Return the pivot index
}
/* Quick sort (median-of-three) */
/* Quick sort (median of three) */
void quickSortMedian(int nums[], int left, int right) {
// Terminate recursion when subarray length is 1
// Stop recursing when the subarray has at most one element
if (left >= right)
return;
// Sentinel partition
// Two-pointer partitioning
int pivot = partitionMedian(nums, left, right);
// Recursively process the left subarray and right subarray
// Recurse on the left and right subarrays
quickSortMedian(nums, left, pivot - 1);
quickSortMedian(nums, pivot + 1, right);
}
// Quick sort with recursion depth optimization below
// Quick sort with recursion depth optimization follows
/* Quick sort (recursion depth optimization) */
void quickSortTailCall(int nums[], int left, int right) {
// Terminate when subarray length is 1
// Stop when the subarray has at most one element
while (left < right) {
// Sentinel partition operation
// Perform two-pointer partitioning
int pivot = partition(nums, left, right);
// Perform quick sort on the shorter of the two subarrays
// Apply quick sort to the shorter of the two subarrays
if (pivot - left < right - pivot) {
// Recursively sort the left subarray
quickSortTailCall(nums, left, pivot - 1);
// Remaining unsorted interval is [pivot + 1, right]
// The remaining unsorted range is [pivot + 1, right]
left = pivot + 1;
} else {
// Recursively sort the right subarray
quickSortTailCall(nums, pivot + 1, right);
// Remaining unsorted interval is [left, pivot - 1]
// The remaining unsorted range is [left, pivot - 1]
right = pivot - 1;
}
}
}
/* Driver Code */
/* Driver code */
int main() {
/* Quick sort */
int nums[] = {2, 4, 1, 0, 3, 5};
int size = sizeof(nums) / sizeof(int);
quickSort(nums, 0, size - 1);
printf("After quick sort completes, nums = ");
printf("After quick sort, nums = ");
printArray(nums, size);
/* Quick sort (recursion depth optimization) */
/* Quick sort (median pivot optimization) */
int nums1[] = {2, 4, 1, 0, 3, 5};
quickSortMedian(nums1, 0, size - 1);
printf("After quick sort (median pivot optimization), nums = ");

View File

@@ -6,37 +6,37 @@
#include "../utils/common.h"
/* Get the k-th digit of element num, where exp = 10^(k-1) */
/* Get the k-th digit of num, where exp = 10^(k-1) */
int digit(int num, int exp) {
// Passing exp instead of k can avoid repeated expensive exponentiation here
// Passing exp instead of k avoids repeatedly performing expensive exponentiation here
return (num / exp) % 10;
}
/* Counting sort (based on nums k-th digit) */
/* Counting sort (sort nums by the k-th digit) */
void countingSortDigit(int nums[], int size, int exp) {
// Decimal digit range is 0~9, therefore need a bucket array of length 10
// Decimal digits range from 0 to 9, so the bucket array needs length 10
int *counter = (int *)malloc((sizeof(int) * 10));
memset(counter, 0, sizeof(int) * 10); // Initialize to 0 to support subsequent memory release
// Count the occurrence of digits 0~9
memset(counter, 0, sizeof(int) * 10); // Initialize the counts to 0
// Count the occurrences of each digit from 0 to 9
for (int i = 0; i < size; i++) {
// Get the k-th digit of nums[i], noted as d
// Get the k-th digit of nums[i] and store it in d
int d = digit(nums[i], exp);
// Count the occurrence of digit d
// Count the occurrences of digit d
counter[d]++;
}
// Calculate prefix sum, converting "occurrence count" into "array index"
// Compute prefix sums to convert occurrence counts into array positions
for (int i = 1; i < 10; i++) {
counter[i] += counter[i - 1];
}
// Traverse in reverse, based on bucket statistics, place each element into res
// Traverse in reverse and place each element into res according to the bucket counts
int *res = (int *)malloc(sizeof(int) * size);
for (int i = size - 1; i >= 0; i--) {
int d = digit(nums[i], exp);
int j = counter[d] - 1; // Get the index j for d in the array
int j = counter[d] - 1; // Get the destination index j for digit d in the array
res[j] = nums[i]; // Place the current element at index j
counter[d]--; // Decrease the count of d by 1
counter[d]--; // Decrease the count for d by 1
}
// Use result to overwrite the original array nums
// Overwrite the original array nums with the result
for (int i = 0; i < size; i++) {
nums[i] = res[i];
}
@@ -47,29 +47,29 @@ void countingSortDigit(int nums[], int size, int exp) {
/* Radix sort */
void radixSort(int nums[], int size) {
// Get the maximum element of the array, used to determine the maximum number of digits
// Get the largest array element to determine the maximum number of digits
int max = INT32_MIN;
for (int i = 0; i < size; i++) {
if (nums[i] > max) {
max = nums[i];
}
}
// Traverse from the lowest to the highest digit
// Process digits from least significant to most significant
for (int exp = 1; max >= exp; exp *= 10)
// Perform counting sort on the k-th digit of array elements
// Apply counting sort to the k-th digit of the array elements
// k = 1 -> exp = 1
// k = 2 -> exp = 10
// i.e., exp = 10^(k-1)
// That is, exp = 10^(k-1)
countingSortDigit(nums, size, exp);
}
/* Driver Code */
/* Driver code */
int main() {
// Radix sort
int nums[] = {10546151, 35663510, 42865989, 34862445, 81883077,
88906420, 72429244, 30524779, 82060337, 63832996};
int size = sizeof(nums) / sizeof(int);
radixSort(nums, size);
printf("After radix sort completes, nums = ");
printf("After radix sort, nums = ");
printArray(nums, size);
}

View File

@@ -8,29 +8,29 @@
/* Selection sort */
void selectionSort(int nums[], int n) {
// Outer loop: unsorted interval is [i, n-1]
// Outer loop: the unsorted range is [i, n-1]
for (int i = 0; i < n - 1; i++) {
// Inner loop: find the smallest element within the unsorted interval
// Inner loop: find the smallest element in the unsorted range
int k = i;
for (int j = i + 1; j < n; j++) {
if (nums[j] < nums[k])
k = j; // Record the index of the smallest element
}
// Swap the smallest element with the first element of the unsorted interval
// Swap the smallest element with the first element of the unsorted range
int temp = nums[i];
nums[i] = nums[k];
nums[k] = temp;
}
}
/* Driver Code */
/* Driver code */
int main() {
int nums[] = {4, 1, 3, 1, 5, 2};
int n = sizeof(nums) / sizeof(nums[0]);
selectionSort(nums, n);
printf("After selection sort completes, nums = ");
printf("After selection sort, nums = ");
printArray(nums, n);
return 0;

View File

@@ -6,18 +6,18 @@
#include "../utils/common.h"
/* Double-ended queue based on circular array implementation */
/* Deque implemented with a circular array */
typedef struct {
int *nums; // Array for storing queue elements
int front; // Front pointer, points to the front of the queue element
int queSize; // Rear pointer, points to rear + 1
int *nums; // Array that stores the queue elements
int front; // Front pointer, pointing to the first element
int queSize; // Current number of elements in the deque
int queCapacity; // Queue capacity
} ArrayDeque;
/* Constructor */
ArrayDeque *newArrayDeque(int capacity) {
ArrayDeque *deque = (ArrayDeque *)malloc(sizeof(ArrayDeque));
// Initialize array
// Initialize the array
deque->queCapacity = capacity;
deque->nums = (int *)malloc(sizeof(int) * deque->queCapacity);
deque->front = deque->queSize = 0;
@@ -30,88 +30,88 @@ void delArrayDeque(ArrayDeque *deque) {
free(deque);
}
/* Get the capacity of the double-ended queue */
/* Get the deque capacity */
int capacity(ArrayDeque *deque) {
return deque->queCapacity;
}
/* Get the length of the double-ended queue */
/* Get the deque size */
int size(ArrayDeque *deque) {
return deque->queSize;
}
/* Check if the double-ended queue is empty */
/* Check whether the deque is empty */
bool empty(ArrayDeque *deque) {
return deque->queSize == 0;
}
/* Calculate circular array index */
/* Calculate an index in the circular array */
int dequeIndex(ArrayDeque *deque, int i) {
// Use modulo operation to wrap the array head and tail together
// When i exceeds array end, wrap to head
// When i passes the head of the array, return to the tail
// Use modulo to connect the end of the array to its beginning
// When i passes the end of the array, wrap to the beginning
// When i passes the beginning of the array, wrap around to the end
return ((i + capacity(deque)) % capacity(deque));
}
/* Front of the queue enqueue */
/* Enqueue at the front */
void pushFirst(ArrayDeque *deque, int num) {
if (deque->queSize == capacity(deque)) {
printf("Deque is full\r\n");
return;
}
// Use modulo operation to wrap front around to the tail after passing the head of the array
// Use modulo to wrap front from array head to rear
// Move the front pointer one position to the left
// Use modulo to wrap front to the end when it passes the beginning
deque->front = dequeIndex(deque, deque->front - 1);
// Add num to queue front
// Add num to the front
deque->nums[deque->front] = num;
deque->queSize++;
}
/* Rear of the queue enqueue */
/* Enqueue at the rear */
void pushLast(ArrayDeque *deque, int num) {
if (deque->queSize == capacity(deque)) {
printf("Deque is full\r\n");
return;
}
// Use modulo operation to wrap rear around to the head after passing the tail of the array
// Calculate the rear pointer, which points one position past the last element
int rear = dequeIndex(deque, deque->front + deque->queSize);
// Front pointer moves one position backward
// Add num to the rear
deque->nums[rear] = num;
deque->queSize++;
}
/* Return list for printing */
/* Access the front element */
int peekFirst(ArrayDeque *deque) {
// Access error: Deque is empty
// Access error: the deque is empty
assert(empty(deque) == 0);
return deque->nums[deque->front];
}
/* Driver Code */
/* Access the rear element */
int peekLast(ArrayDeque *deque) {
// Access error: Deque is empty
// Access error: the deque is empty
assert(empty(deque) == 0);
int last = dequeIndex(deque, deque->front + deque->queSize - 1);
return deque->nums[last];
}
/* Rear of the queue dequeue */
/* Dequeue from the front */
int popFirst(ArrayDeque *deque) {
int num = peekFirst(deque);
// Move front pointer backward by one position
// Advance the front pointer by one position
deque->front = dequeIndex(deque, deque->front + 1);
deque->queSize--;
return num;
}
/* Access rear of the queue element */
/* Dequeue from the rear */
int popLast(ArrayDeque *deque) {
int num = peekLast(deque);
deque->queSize--;
return num;
}
/* Return array for printing */
/* Return an array for printing */
int *toArray(ArrayDeque *deque, int *queSize) {
*queSize = deque->queSize;
int *res = (int *)calloc(deque->queSize, sizeof(int));
@@ -123,47 +123,47 @@ int *toArray(ArrayDeque *deque, int *queSize) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
/* Access front of the queue element */
/* Initialize the queue */
int capacity = 10;
int queSize;
ArrayDeque *deque = newArrayDeque(capacity);
pushLast(deque, 3);
pushLast(deque, 2);
pushLast(deque, 5);
printf("Double-ended queue deque = ");
printf("Deque deque = ");
printArray(toArray(deque, &queSize), queSize);
/* Update element */
/* Access an element */
int peekFirstNum = peekFirst(deque);
printf("Front element peekFirst = %d\r\n", peekFirstNum);
int peekLastNum = peekLast(deque);
printf("Rear element peekLast = %d\r\n", peekLastNum);
/* Elements enqueue */
/* Enqueue elements */
pushLast(deque, 4);
printf("After element 4 enqueues at rear, deque = ");
printf("After enqueuing element 4 at the rear, deque = ");
printArray(toArray(deque, &queSize), queSize);
pushFirst(deque, 1);
printf("After element 1 enqueues at front, deque = ");
printf("After enqueuing element 1 at the front, deque = ");
printArray(toArray(deque, &queSize), queSize);
/* Element dequeue */
/* Dequeue an element */
int popLastNum = popLast(deque);
printf("Dequeue from rear = %d, deque after rear dequeue = ", popLastNum);
printf("Element removed from the rear = %d; after removal, deque= ", popLastNum);
printArray(toArray(deque, &queSize), queSize);
int popFirstNum = popFirst(deque);
printf("Dequeue from front = %d, deque after front dequeue = ", popFirstNum);
printf("Element removed from the front = %d; after removal, deque= ", popFirstNum);
printArray(toArray(deque, &queSize), queSize);
/* Get the length of the queue */
/* Get the queue size */
int dequeSize = size(deque);
printf("Deque size = %d\r\n", dequeSize);
/* Check if the queue is empty */
/* Check whether the queue is empty */
bool isEmpty = empty(deque);
printf("Is queue empty = %s\r\n", isEmpty ? "true" : "false");
printf("Is the queue empty = %s\r\n", isEmpty ? "true" : "false");
// Free memory
delArrayDeque(deque);

View File

@@ -6,10 +6,10 @@
#include "../utils/common.h"
/* Queue based on circular array implementation */
/* Queue implemented with a circular array */
typedef struct {
int *nums; // Array for storing queue elements
int front; // Front pointer, points to the front of the queue element
int *nums; // Array that stores the queue elements
int front; // Front pointer, pointing to the first element
int queSize; // Current number of elements in the queue
int queCapacity; // Queue capacity
} ArrayQueue;
@@ -17,7 +17,7 @@ typedef struct {
/* Constructor */
ArrayQueue *newArrayQueue(int capacity) {
ArrayQueue *queue = (ArrayQueue *)malloc(sizeof(ArrayQueue));
// Initialize array
// Initialize the array
queue->queCapacity = capacity;
queue->nums = (int *)malloc(sizeof(int) * queue->queCapacity);
queue->front = queue->queSize = 0;
@@ -30,22 +30,22 @@ void delArrayQueue(ArrayQueue *queue) {
free(queue);
}
/* Get the capacity of the queue */
/* Get the queue capacity */
int capacity(ArrayQueue *queue) {
return queue->queCapacity;
}
/* Get the length of the queue */
/* Get the queue size */
int size(ArrayQueue *queue) {
return queue->queSize;
}
/* Check if the queue is empty */
/* Check whether the queue is empty */
bool empty(ArrayQueue *queue) {
return queue->queSize == 0;
}
/* Return list for printing */
/* Access the front element */
int peek(ArrayQueue *queue) {
assert(size(queue) != 0);
return queue->nums[queue->front];
@@ -57,10 +57,10 @@ void push(ArrayQueue *queue, int num) {
printf("Queue is full\r\n");
return;
}
// Use modulo operation to wrap rear around to the head after passing the tail of the array
// Add num to the rear of the queue
// Calculate the rear pointer, which points one position past the last element
// Use modulo to wrap rear to the beginning when it passes the end of the array
int rear = (queue->front + queue->queSize) % queue->queCapacity;
// Front pointer moves one position backward
// Add num to the rear
queue->nums[rear] = num;
queue->queSize++;
}
@@ -68,13 +68,13 @@ void push(ArrayQueue *queue, int num) {
/* Dequeue */
int pop(ArrayQueue *queue) {
int num = peek(queue);
// Move front pointer backward by one position, if it passes the tail, return to array head
// Advance the front pointer by one position, wrapping to the beginning if it passes the end
queue->front = (queue->front + 1) % queue->queCapacity;
queue->queSize--;
return num;
}
/* Return array for printing */
/* Return an array for printing */
int *toArray(ArrayQueue *queue, int *queSize) {
*queSize = queue->queSize;
int *res = (int *)calloc(queue->queSize, sizeof(int));
@@ -86,14 +86,14 @@ int *toArray(ArrayQueue *queue, int *queSize) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
/* Access front of the queue element */
/* Initialize the queue */
int capacity = 10;
int queSize;
ArrayQueue *queue = newArrayQueue(capacity);
/* Elements enqueue */
/* Enqueue elements */
push(queue, 1);
push(queue, 3);
push(queue, 2);
@@ -102,28 +102,28 @@ int main() {
printf("Queue queue = ");
printArray(toArray(queue, &queSize), queSize);
/* Return list for printing */
/* Access the front element */
int peekNum = peek(queue);
printf("Front element peek = %d\r\n", peekNum);
/* Element dequeue */
/* Dequeue an element */
peekNum = pop(queue);
printf("Dequeue element pop = %d, queue after dequeue = ", peekNum);
printf("Dequeued element pop = %d; after dequeuing, queue = ", peekNum);
printArray(toArray(queue, &queSize), queSize);
/* Get the length of the queue */
/* Get the queue size */
int queueSize = size(queue);
printf("Queue size = %d\r\n", queueSize);
/* Check if the queue is empty */
/* Check whether the queue is empty */
bool isEmpty = empty(queue);
printf("Is queue empty = %s\r\n", isEmpty ? "true" : "false");
printf("Is the queue empty = %s\r\n", isEmpty ? "true" : "false");
/* Test circular array */
/* Test the circular array */
for (int i = 0; i < 10; i++) {
push(queue, i);
pop(queue);
printf("After round %d enqueue + dequeue, queue = ", i);
printf("After enqueueing and dequeueing in round %d, queue = ", i);
printArray(toArray(queue, &queSize), queSize);
}
@@ -131,4 +131,4 @@ int main() {
delArrayQueue(queue);
return 0;
}
}

View File

@@ -8,7 +8,7 @@
#define MAX_SIZE 5000
/* Stack based on array implementation */
/* Stack implemented with an array */
typedef struct {
int *data;
int size;
@@ -17,7 +17,7 @@ typedef struct {
/* Constructor */
ArrayStack *newArrayStack() {
ArrayStack *stack = malloc(sizeof(ArrayStack));
// Initialize with large capacity to avoid expansion
// Initialize with a large capacity to avoid resizing
stack->data = malloc(sizeof(int) * MAX_SIZE);
stack->size = 0;
return stack;
@@ -29,12 +29,12 @@ void delArrayStack(ArrayStack *stack) {
free(stack);
}
/* Get the length of the stack */
/* Get the stack size */
int size(ArrayStack *stack) {
return stack->size;
}
/* Check if the stack is empty */
/* Check whether the stack is empty */
bool isEmpty(ArrayStack *stack) {
return stack->size == 0;
}
@@ -49,7 +49,7 @@ void push(ArrayStack *stack, int num) {
stack->size++;
}
/* Return list for printing */
/* Access the top element */
int peek(ArrayStack *stack) {
if (stack->size == 0) {
printf("Stack is empty\n");
@@ -65,12 +65,12 @@ int pop(ArrayStack *stack) {
return val;
}
/* Driver Code */
/* Driver code */
int main() {
/* Access top of the stack element */
/* Initialize the stack */
ArrayStack *stack = newArrayStack();
/* Elements push onto stack */
/* Push elements onto the stack */
push(stack, 1);
push(stack, 3);
push(stack, 2);
@@ -79,22 +79,22 @@ int main() {
printf("Stack stack = ");
printArray(stack->data, stack->size);
/* Return list for printing */
/* Access the top element */
int val = peek(stack);
printf("Top element top = %d\n", val);
/* Element pop from stack */
/* Pop an element from the stack */
val = pop(stack);
printf("Pop element pop = %d, stack after pop = ", val);
printf("Popped element pop = %d; after popping, stack = ", val);
printArray(stack->data, stack->size);
/* Get the length of the stack */
/* Get the stack size */
int size = stack->size;
printf("Stack size = %d\n", size);
/* Check if empty */
/* Check whether it is empty */
bool empty = isEmpty(stack);
printf("Is stack empty = %s\n", empty ? "true" : "false");
printf("Is the stack empty = %s\n", empty ? "true" : "false");
// Free memory
delArrayStack(stack);

View File

@@ -9,8 +9,8 @@
/* Doubly linked list node */
typedef struct DoublyListNode {
int val; // Node value
struct DoublyListNode *next; // Successor node
struct DoublyListNode *prev; // Predecessor node
struct DoublyListNode *next; // Next node
struct DoublyListNode *prev; // Previous node
} DoublyListNode;
/* Constructor */
@@ -27,10 +27,10 @@ void delDoublyListNode(DoublyListNode *node) {
free(node);
}
/* Double-ended queue based on doubly linked list implementation */
/* Deque implemented with a doubly linked list */
typedef struct {
DoublyListNode *front, *rear; // Head node front, tail node rear
int queSize; // Length of the double-ended queue
DoublyListNode *front, *rear; // Head node front and tail node rear
int queSize; // Deque size
} LinkedListDeque;
/* Constructor */
@@ -50,16 +50,16 @@ void delLinkedListdeque(LinkedListDeque *deque) {
deque->front = deque->front->next;
free(tmp);
}
// Free deque structure
// Free the deque structure
free(deque);
}
/* Get the length of the queue */
/* Get the queue size */
int size(LinkedListDeque *deque) {
return deque->queSize;
}
/* Check if the queue is empty */
/* Check whether the queue is empty */
bool empty(LinkedListDeque *deque) {
return (size(deque) == 0);
}
@@ -67,44 +67,44 @@ bool empty(LinkedListDeque *deque) {
/* Enqueue */
void push(LinkedListDeque *deque, int num, bool isFront) {
DoublyListNode *node = newDoublyListNode(num);
// If list is empty, set both front and rear to node
// If the list is empty, make both front and rear point to node
if (empty(deque)) {
deque->front = deque->rear = node;
}
// Front of the queue enqueue operation
// Enqueue at the front
else if (isFront) {
// Add node to the head of the linked list
deque->front->prev = node;
node->next = deque->front;
deque->front = node; // Update head node
deque->front = node; // Update the head node
}
// Rear of the queue enqueue operation
// Enqueue at the rear
else {
// Add node to the tail of the linked list
deque->rear->next = node;
node->prev = deque->rear;
deque->rear = node;
}
deque->queSize++; // Update queue length
deque->queSize++; // Update the queue size
}
/* Front of the queue enqueue */
/* Enqueue at the front */
void pushFirst(LinkedListDeque *deque, int num) {
push(deque, num, true);
}
/* Rear of the queue enqueue */
/* Enqueue at the rear */
void pushLast(LinkedListDeque *deque, int num) {
push(deque, num, false);
}
/* Return list for printing */
/* Access the front element */
int peekFirst(LinkedListDeque *deque) {
assert(size(deque) && deque->front);
return deque->front->val;
}
/* Driver Code */
/* Access the rear element */
int peekLast(LinkedListDeque *deque) {
assert(size(deque) && deque->rear);
return deque->rear->val;
@@ -115,49 +115,49 @@ int pop(LinkedListDeque *deque, bool isFront) {
if (empty(deque))
return -1;
int val;
// When the deque has one element, front and rear point to the same node
// When the queue size is 1, the head and tail point to the same node
if (deque->queSize == 1) {
val = deque->front->val;
delDoublyListNode(deque->front); // Free the shared node once
delDoublyListNode(deque->front); // Both point to the same node, so free it only once
deque->front = NULL;
deque->rear = NULL;
}
// Temporarily store head node value
// Dequeue from the front
else if (isFront) {
val = peekFirst(deque); // Delete head node
val = peekFirst(deque); // Save the head node value
DoublyListNode *fNext = deque->front->next;
fNext->prev = NULL;
deque->front->next = NULL;
delDoublyListNode(deque->front);
deque->front = fNext; // Update head node
deque->front = fNext; // Update the head node
}
// Temporarily store tail node value
// Dequeue from the rear
else {
val = peekLast(deque); // Delete tail node
val = peekLast(deque); // Save the tail node value
DoublyListNode *rPrev = deque->rear->prev;
rPrev->next = NULL;
deque->rear->prev = NULL;
delDoublyListNode(deque->rear);
deque->rear = rPrev; // Update tail node
deque->rear = rPrev; // Update the tail node
}
deque->queSize--; // Update queue length
deque->queSize--; // Update the queue size
return val;
}
/* Rear of the queue dequeue */
/* Dequeue from the front */
int popFirst(LinkedListDeque *deque) {
return pop(deque, true);
}
/* Access rear of the queue element */
/* Dequeue from the rear */
int popLast(LinkedListDeque *deque) {
return pop(deque, false);
}
/* Print queue */
/* Print the queue */
void printLinkedListDeque(LinkedListDeque *deque) {
int *arr = malloc(sizeof(int) * deque->queSize);
// Copy data from list to array
// Copy the linked list data into an array
int i;
DoublyListNode *node;
for (i = 0, node = deque->front; i < deque->queSize; i++) {
@@ -168,45 +168,45 @@ void printLinkedListDeque(LinkedListDeque *deque) {
free(arr);
}
/* Driver Code */
/* Driver code */
int main() {
/* Get the length of the double-ended queue */
/* Initialize the deque */
LinkedListDeque *deque = newLinkedListDeque();
pushLast(deque, 3);
pushLast(deque, 2);
pushLast(deque, 5);
printf("Double-ended queue deque = ");
printf("Deque deque = ");
printLinkedListDeque(deque);
/* Update element */
/* Access an element */
int peekFirstNum = peekFirst(deque);
printf("Front element peekFirst = %d\r\n", peekFirstNum);
int peekLastNum = peekLast(deque);
printf("Front element peekLast = %d\r\n", peekLastNum);
printf("Rear element peekLast = %d\r\n", peekLastNum);
/* Elements enqueue */
/* Enqueue elements */
pushLast(deque, 4);
printf("After element 4 enqueues at back, deque =");
printf("After enqueuing element 4 at the rear, deque =");
printLinkedListDeque(deque);
pushFirst(deque, 1);
printf("After element 1 enqueues at front, deque =");
printf("After enqueuing element 1 at the front, deque =");
printLinkedListDeque(deque);
/* Element dequeue */
/* Dequeue an element */
int popLastNum = popLast(deque);
printf("Dequeue from rear popLast = %d, deque after rear dequeue = ", popLastNum);
printf("Element removed from the rear, popLast = %d; after removal, deque = ", popLastNum);
printLinkedListDeque(deque);
int popFirstNum = popFirst(deque);
printf("Dequeue from front popFirst = %d, deque after front dequeue = ", popFirstNum);
printf("Element removed from the front, popFirst = %d; after removal, deque = ", popFirstNum);
printLinkedListDeque(deque);
/* Get the length of the queue */
/* Get the queue size */
int dequeSize = size(deque);
printf("Deque size = %d\r\n", dequeSize);
/* Check if the queue is empty */
/* Check whether the queue is empty */
bool isEmpty = empty(deque);
printf("Is deque empty = %s\r\n", isEmpty ? "true" : "false");
printf("Is the deque empty = %s\r\n", isEmpty ? "true" : "false");
// Free memory
delLinkedListdeque(deque);

View File

@@ -6,7 +6,7 @@
#include "../utils/common.h"
/* Queue based on linked list implementation */
/* Queue implemented with a linked list */
typedef struct {
ListNode *front, *rear;
int queSize;
@@ -29,30 +29,30 @@ void delLinkedListQueue(LinkedListQueue *queue) {
queue->front = queue->front->next;
free(tmp);
}
// Free queue structure
// Free the queue structure
free(queue);
}
/* Get the length of the queue */
/* Get the queue size */
int size(LinkedListQueue *queue) {
return queue->queSize;
}
/* Check if the queue is empty */
/* Check whether the queue is empty */
bool empty(LinkedListQueue *queue) {
return (size(queue) == 0);
}
/* Enqueue */
void push(LinkedListQueue *queue, int num) {
// Add node at tail
// Add node at the tail
ListNode *node = newListNode(num);
// If the queue is empty, make both front and rear point to the node
// If the queue is empty, make both the head and tail point to this node
if (queue->front == NULL) {
queue->front = node;
queue->rear = node;
}
// If the queue is not empty, add the node after the tail node
// If the queue is not empty, add this node after the tail node
else {
queue->rear->next = node;
queue->rear = node;
@@ -60,7 +60,7 @@ void push(LinkedListQueue *queue, int num) {
queue->queSize++;
}
/* Return list for printing */
/* Access the front element */
int peek(LinkedListQueue *queue) {
assert(size(queue) && queue->front);
return queue->front->val;
@@ -76,10 +76,10 @@ int pop(LinkedListQueue *queue) {
return num;
}
/* Print queue */
/* Print the queue */
void printLinkedListQueue(LinkedListQueue *queue) {
int *arr = malloc(sizeof(int) * queue->queSize);
// Copy data from list to array
// Copy the linked list data into an array
int i;
ListNode *node;
for (i = 0, node = queue->front; i < queue->queSize; i++) {
@@ -90,12 +90,12 @@ void printLinkedListQueue(LinkedListQueue *queue) {
free(arr);
}
/* Driver Code */
/* Driver code */
int main() {
/* Access front of the queue element */
/* Initialize the queue */
LinkedListQueue *queue = newLinkedListQueue();
/* Elements enqueue */
/* Enqueue elements */
push(queue, 1);
push(queue, 3);
push(queue, 2);
@@ -104,22 +104,22 @@ int main() {
printf("Queue queue = ");
printLinkedListQueue(queue);
/* Return list for printing */
/* Access the front element */
int peekNum = peek(queue);
printf("Front element peek = %d\r\n", peekNum);
/* Element dequeue */
/* Dequeue an element */
peekNum = pop(queue);
printf("Dequeue element pop = %d, queue after dequeue = ", peekNum);
printf("Dequeued element pop = %d; after dequeuing, queue = ", peekNum);
printLinkedListQueue(queue);
/* Get the length of the queue */
/* Get the queue size */
int queueSize = size(queue);
printf("Queue size = %d\r\n", queueSize);
/* Check if the queue is empty */
/* Check whether the queue is empty */
bool isEmpty = empty(queue);
printf("Is queue empty = %s\r\n", isEmpty ? "true" : "false");
printf("Is the queue empty = %s\r\n", isEmpty ? "true" : "false");
// Free memory
delLinkedListQueue(queue);

View File

@@ -6,10 +6,10 @@
#include "../utils/common.h"
/* Stack based on linked list implementation */
/* Stack implemented with a linked list */
typedef struct {
ListNode *top; // Use head node as stack top
int size; // Stack length
ListNode *top; // Use the head node as the stack top
int size; // Stack size
} LinkedListStack;
/* Constructor */
@@ -30,12 +30,12 @@ void delLinkedListStack(LinkedListStack *s) {
free(s);
}
/* Get the length of the stack */
/* Get the stack size */
int size(LinkedListStack *s) {
return s->size;
}
/* Check if the stack is empty */
/* Check whether the stack is empty */
bool isEmpty(LinkedListStack *s) {
return size(s) == 0;
}
@@ -43,13 +43,13 @@ bool isEmpty(LinkedListStack *s) {
/* Push */
void push(LinkedListStack *s, int num) {
ListNode *node = (ListNode *)malloc(sizeof(ListNode));
node->next = s->top; // Update new node's pointer field
node->val = num; // Update new node's data field
s->top = node; // Update stack top
s->size++; // Update stack size
node->next = s->top; // Set the new node's pointer field
node->val = num; // Set the new node's data field
s->top = node; // Update the stack top
s->size++; // Update the stack size
}
/* Return list for printing */
/* Access the top element */
int peek(LinkedListStack *s) {
if (s->size == 0) {
printf("Stack is empty\n");
@@ -69,12 +69,12 @@ int pop(LinkedListStack *s) {
return val;
}
/* Driver Code */
/* Driver code */
int main() {
/* Access top of the stack element */
/* Initialize the stack */
LinkedListStack *stack = newLinkedListStack();
/* Elements push onto stack */
/* Push elements onto the stack */
push(stack, 1);
push(stack, 3);
push(stack, 2);
@@ -84,21 +84,21 @@ int main() {
printf("Stack stack = ");
printLinkedList(stack->top);
/* Return list for printing */
/* Access the top element */
int val = peek(stack);
printf("Top element top = %d\r\n", val);
/* Element pop from stack */
/* Pop an element from the stack */
val = pop(stack);
printf("Pop element pop = %d, stack after pop = ", val);
printf("Popped element pop = %d; after popping, stack = ", val);
printLinkedList(stack->top);
/* Get the length of the stack */
/* Get the stack size */
printf("Stack size = %d\n", size(stack));
/* Check if empty */
/* Check whether it is empty */
bool empty = isEmpty(stack);
printf("Is stack empty = %s\n", empty ? "true" : "false");
printf("Is the stack empty = %s\n", empty ? "true" : "false");
// Free memory
delLinkedListStack(stack);

View File

@@ -6,7 +6,7 @@
#include "../utils/common.h"
/* Binary tree structure in array representation */
/* Binary tree structure represented by an array */
typedef struct {
int *tree;
int size;
@@ -27,30 +27,30 @@ void delArrayBinaryTree(ArrayBinaryTree *abt) {
free(abt);
}
/* List capacity */
/* Array length */
int size(ArrayBinaryTree *abt) {
return abt->size;
}
/* Get value of node at index i */
/* Get the value of the node at index i */
int val(ArrayBinaryTree *abt, int i) {
// Return INT_MAX if index out of bounds, representing empty position
// If the index is out of bounds, return INT_MAX to represent an empty position
if (i < 0 || i >= size(abt))
return INT_MAX;
return abt->tree[i];
}
/* Get index of left child node of node at index i */
/* Get the left child index of the node at index i */
int left(int i) {
return 2 * i + 1;
}
/* Get index of right child node of node at index i */
/* Get the right child index of the node at index i */
int right(int i) {
return 2 * i + 2;
}
/* Get index of parent node of node at index i */
/* Get the parent index of the node at index i */
int parent(int i) {
return (i - 1) / 2;
}
@@ -59,7 +59,7 @@ int parent(int i) {
int *levelOrder(ArrayBinaryTree *abt, int *returnSize) {
int *res = (int *)malloc(sizeof(int) * size(abt));
int index = 0;
// Traverse array directly
// Traverse the array directly
for (int i = 0; i < size(abt); i++) {
if (val(abt, i) != INT_MAX)
res[index++] = val(abt, i);
@@ -70,7 +70,7 @@ int *levelOrder(ArrayBinaryTree *abt, int *returnSize) {
/* Depth-first traversal */
void dfs(ArrayBinaryTree *abt, int i, char *order, int *res, int *index) {
// If empty position, return
// Return if this position is empty
if (val(abt, i) == INT_MAX)
return;
// Preorder traversal
@@ -113,30 +113,30 @@ int *postOrder(ArrayBinaryTree *abt, int *returnSize) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
// Initialize binary tree
// Use INT_MAX to represent NULL
// Initialize the binary tree
// Use INT_MAX to represent an empty position (NULL)
int arr[] = {1, 2, 3, 4, INT_MAX, 6, 7, 8, 9, INT_MAX, INT_MAX, 12, INT_MAX, INT_MAX, 15};
int arrSize = sizeof(arr) / sizeof(arr[0]);
TreeNode *root = arrayToTree(arr, arrSize);
printf("\nInitialize binary tree\n");
printf("Array representation of binary tree:\n");
printf("\nInitialize the binary tree\n");
printf("Array representation of the binary tree:\n");
printArray(arr, arrSize);
printf("Linked list representation of binary tree:\n");
printf("Linked representation of the binary tree:\n");
printTree(root);
ArrayBinaryTree *abt = newArrayBinaryTree(arr, arrSize);
// Access node
// Access a node
int i = 1;
int l = left(i), r = right(i), p = parent(i);
printf("\nCurrent node index is %d, value is %d\n", i, val(abt, i));
printf("Its left child index is %d, value is %d\n", l, l < arrSize ? val(abt, l) : INT_MAX);
printf("Its right child index is %d, value is %d\n", r, r < arrSize ? val(abt, r) : INT_MAX);
printf("Its parent node index is %d, value is %d\n", p, p < arrSize ? val(abt, p) : INT_MAX);
printf("\nCurrent node: index %d, value %d\n", i, val(abt, i));
printf("Its left child: index %d, value %d\n", l, l < arrSize ? val(abt, l) : INT_MAX);
printf("Its right child: index %d, value %d\n", r, r < arrSize ? val(abt, r) : INT_MAX);
printf("Its parent: index %d, value %d\n", p, p < arrSize ? val(abt, p) : INT_MAX);
// Traverse tree
// Traverse the tree
int returnSize;
int *res;
@@ -146,17 +146,17 @@ int main() {
free(res);
res = preOrder(abt, &returnSize);
printf("Pre-order traversal: ");
printf("Preorder traversal: ");
printArray(res, returnSize);
free(res);
res = inOrder(abt, &returnSize);
printf("In-order traversal: ");
printf("Inorder traversal: ");
printArray(res, returnSize);
free(res);
res = postOrder(abt, &returnSize);
printf("Post-order traversal: ");
printf("Postorder traversal: ");
printArray(res, returnSize);
free(res);

View File

@@ -24,20 +24,20 @@ void delAVLTree(AVLTree *tree) {
free(tree);
}
/* Get node height */
/* Get the node height */
int height(TreeNode *node) {
// Empty node height is -1, leaf node height is 0
// A null node has height -1; a leaf has height 0
if (node != NULL) {
return node->height;
}
return -1;
}
/* Update node height */
/* Update the node height */
void updateHeight(TreeNode *node) {
int lh = height(node->left);
int rh = height(node->right);
// Node height equals the height of the tallest subtree + 1
// The node height equals the height of its taller subtree + 1
if (lh > rh) {
node->height = lh + 1;
} else {
@@ -45,9 +45,9 @@ void updateHeight(TreeNode *node) {
}
}
/* Get balance factor */
/* Get the balance factor */
int balanceFactor(TreeNode *node) {
// Empty node balance factor is 0
// A null node has balance factor 0
if (node == NULL) {
return 0;
}
@@ -55,100 +55,100 @@ int balanceFactor(TreeNode *node) {
return height(node->left) - height(node->right);
}
/* Right rotation operation */
/* Right rotation */
TreeNode *rightRotate(TreeNode *node) {
TreeNode *child, *grandChild;
child = node->left;
grandChild = child->right;
// Using child as pivot, rotate node to the right
// Rotate node to the right around child
child->right = node;
node->left = grandChild;
// Update node height
// Update the node height
updateHeight(node);
updateHeight(child);
// Return root node of subtree after rotation
// Return the root of the rotated subtree
return child;
}
/* Left rotation operation */
/* Left rotation */
TreeNode *leftRotate(TreeNode *node) {
TreeNode *child, *grandChild;
child = node->right;
grandChild = child->left;
// Using child as pivot, rotate node to the left
// Rotate node to the left around child
child->left = node;
node->right = grandChild;
// Update node height
// Update the node height
updateHeight(node);
updateHeight(child);
// Return root node of subtree after rotation
// Return the root of the rotated subtree
return child;
}
/* Perform rotation operation to restore balance to this subtree */
/* Perform rotations to restore balance in this subtree */
TreeNode *rotate(TreeNode *node) {
// Get balance factor of node
// Get the balance factor of node
int bf = balanceFactor(node);
// Left-leaning tree
// Left-heavy tree
if (bf > 1) {
if (balanceFactor(node->left) >= 0) {
// Right rotation
// Rotate right
return rightRotate(node);
} else {
// First left rotation then right rotation
// Rotate left, then right
node->left = leftRotate(node->left);
return rightRotate(node);
}
}
// Right-leaning tree
// Right-heavy tree
if (bf < -1) {
if (balanceFactor(node->right) <= 0) {
// Left rotation
// Rotate left
return leftRotate(node);
} else {
// First right rotation then left rotation
// Rotate right, then left
node->right = rightRotate(node->right);
return leftRotate(node);
}
}
// Balanced tree, no rotation needed, return directly
// The tree is balanced; return without rotating
return node;
}
/* Recursively insert node (helper function) */
/* Recursively insert a node (helper function) */
TreeNode *insertHelper(TreeNode *node, int val) {
if (node == NULL) {
return newTreeNode(val);
}
/* 1. Find insertion position and insert node */
/* 1. Find the insertion position and insert the node */
if (val < node->val) {
node->left = insertHelper(node->left, val);
} else if (val > node->val) {
node->right = insertHelper(node->right, val);
} else {
// Duplicate node not inserted, return directly
// Return without inserting a duplicate node
return node;
}
// Update node height
// Update the node height
updateHeight(node);
/* 2. Perform rotation operation to restore balance to this subtree */
/* 2. Perform rotations to restore balance in this subtree */
node = rotate(node);
// Return root node of subtree
// Return the root of the subtree
return node;
}
/* Insert node */
/* Insert a node */
void insert(AVLTree *tree, int val) {
tree->root = insertHelper(tree->root, val);
}
/* Recursively remove node (helper function) */
/* Recursively remove a node (helper function) */
TreeNode *removeHelper(TreeNode *node, int val) {
TreeNode *child, *grandChild;
if (node == NULL) {
return NULL;
}
/* 1. Find node and delete */
/* 1. Find and remove the node */
if (val < node->val) {
node->left = removeHelper(node->left, val);
} else if (val > node->val) {
@@ -159,15 +159,15 @@ TreeNode *removeHelper(TreeNode *node, int val) {
if (node->right != NULL) {
child = node->right;
}
// Number of child nodes = 0, delete node directly and return
// Number of children = 0: remove node and return
if (child == NULL) {
return NULL;
} else {
// Number of child nodes = 1, delete node directly
// Number of children = 1: remove node directly
node = child;
}
} else {
// Number of child nodes = 2, delete the next node in inorder traversal and replace current node with it
// Number of children = 2: remove the inorder successor and use its value to replace the current node value
TreeNode *temp = node->right;
while (temp->left != NULL) {
temp = temp->left;
@@ -177,58 +177,58 @@ TreeNode *removeHelper(TreeNode *node, int val) {
node->val = tempVal;
}
}
// Update node height
// Update the node height
updateHeight(node);
/* 2. Perform rotation operation to restore balance to this subtree */
/* 2. Perform rotations to restore balance in this subtree */
node = rotate(node);
// Return root node of subtree
// Return the root of the subtree
return node;
}
/* Remove node */
// Cannot use remove keyword here due to stdio.h inclusion
/* Remove a node */
// The name remove conflicts with the function declared in stdio.h
void removeItem(AVLTree *tree, int val) {
TreeNode *root = removeHelper(tree->root, val);
}
/* Search node */
/* Find a node */
TreeNode *search(AVLTree *tree, int val) {
TreeNode *cur = tree->root;
// Loop search, exit after passing leaf node
// Search in a loop until reaching a null reference beyond a leaf
while (cur != NULL) {
if (cur->val < val) {
// Target node is in cur's right subtree
// The target node lies in the right subtree of cur
cur = cur->right;
} else if (cur->val > val) {
// Target node is in cur's left subtree
// The target node lies in the left subtree of cur
cur = cur->left;
} else {
// Found target node, exit loop
// The target node was found; exit the loop
break;
}
}
// Found target node, exit loop
// Return the matching node, or NULL if no match was found
return cur;
}
void testInsert(AVLTree *tree, int val) {
insert(tree, val);
printf("\nAfter inserting node %d, AVL tree is \n", val);
printf("\nAVL tree after inserting node %d: \n", val);
printTree(tree->root);
}
void testRemove(AVLTree *tree, int val) {
removeItem(tree, val);
printf("\nAfter removing node %d, AVL tree is \n", val);
printf("\nAVL tree after removing node %d: \n", val);
printTree(tree->root);
}
/* Driver Code */
/* Driver code */
int main() {
/* Please pay attention to how the AVL tree maintains balance after inserting nodes */
/* Initialize an empty AVL tree */
AVLTree *tree = (AVLTree *)newAVLTree();
/* Insert node */
// Delete nodes
/* Insert a node */
// Observe how the AVL tree maintains balance after a node is inserted
testInsert(tree, 1);
testInsert(tree, 2);
testInsert(tree, 3);
@@ -240,18 +240,18 @@ int main() {
testInsert(tree, 10);
testInsert(tree, 6);
/* Please pay attention to how the AVL tree maintains balance after deleting nodes */
/* Insert a duplicate node */
testInsert(tree, 7);
/* Remove node */
// Delete node with degree 1
testRemove(tree, 8); // Delete node with degree 2
testRemove(tree, 5); // Remove node with degree 1
testRemove(tree, 4); // Remove node with degree 2
/* Remove a node */
// Observe how the AVL tree maintains balance after a node is removed
testRemove(tree, 8); // Remove a node with 0 children
testRemove(tree, 5); // Remove a node with 1 child
testRemove(tree, 4); // Remove a node with 2 children
/* Search node */
/* Look up a node */
TreeNode *node = search(tree, 7);
printf("\nFound node object value = %d \n", node->val);
printf("\nValue of the node found = %d \n", node->val);
// Free memory
delAVLTree(tree);

View File

@@ -13,7 +13,7 @@ typedef struct {
/* Constructor */
BinarySearchTree *newBinarySearchTree() {
// Initialize empty tree
// Initialize an empty tree
BinarySearchTree *bst = (BinarySearchTree *)malloc(sizeof(BinarySearchTree));
bst->root = NULL;
return bst;
@@ -25,55 +25,55 @@ void delBinarySearchTree(BinarySearchTree *bst) {
free(bst);
}
/* Get binary tree root node */
/* Get the root of the binary tree */
TreeNode *getRoot(BinarySearchTree *bst) {
return bst->root;
}
/* Search node */
/* Find a node */
TreeNode *search(BinarySearchTree *bst, int num) {
TreeNode *cur = bst->root;
// Loop search, exit after passing leaf node
// Search in a loop until reaching a null reference beyond a leaf
while (cur != NULL) {
if (cur->val < num) {
// Target node is in cur's right subtree
// The target node lies in the right subtree of cur
cur = cur->right;
} else if (cur->val > num) {
// Target node is in cur's left subtree
// The target node lies in the left subtree of cur
cur = cur->left;
} else {
// Found target node, exit loop
// The target node was found; exit the loop
break;
}
}
// Return target node
// Return the target node
return cur;
}
/* Insert node */
/* Insert a node */
void insert(BinarySearchTree *bst, int num) {
// If tree is empty, initialize root node
// If the tree is empty, initialize the root node
if (bst->root == NULL) {
bst->root = newTreeNode(num);
return;
}
TreeNode *cur = bst->root, *pre = NULL;
// Loop search, exit after passing leaf node
// Search in a loop until reaching a null reference beyond a leaf
while (cur != NULL) {
// Found duplicate node, return directly
// Return immediately if a duplicate node is found
if (cur->val == num) {
return;
}
pre = cur;
if (cur->val < num) {
// Insertion position is in cur's right subtree
// The insertion position lies in the right subtree of cur
cur = cur->right;
} else {
// Insertion position is in cur's left subtree
// The insertion position lies in the left subtree of cur
cur = cur->left;
}
}
// Insert node
// Insert a node
TreeNode *node = newTreeNode(num);
if (pre->val < num) {
pre->right = node;
@@ -82,36 +82,36 @@ void insert(BinarySearchTree *bst, int num) {
}
}
/* Remove node */
// Cannot use remove keyword here due to stdio.h inclusion
/* Remove a node */
// The name remove conflicts with the function declared in stdio.h
void removeItem(BinarySearchTree *bst, int num) {
// If tree is empty, return directly
// Return immediately if the tree is empty
if (bst->root == NULL)
return;
TreeNode *cur = bst->root, *pre = NULL;
// Loop search, exit after passing leaf node
// Search in a loop until reaching a null reference beyond a leaf
while (cur != NULL) {
// Found node to delete, exit loop
// The node to remove was found; exit the loop
if (cur->val == num)
break;
pre = cur;
if (cur->val < num) {
// Node to delete is in right subtree of root
// The node to remove is in cur's right subtree
cur = cur->right;
} else {
// Node to delete is in left subtree of root
// The node to remove is in cur's left subtree
cur = cur->left;
}
}
// If no node to delete, return directly
// Return immediately if the node to remove does not exist
if (cur == NULL)
return;
// Check if node to delete has children
// Check whether the node to remove has children
if (cur->left == NULL || cur->right == NULL) {
/* Number of child nodes = 0 or 1 */
// When number of child nodes = 0 / 1, child = nullptr / that child node
/* Number of children = 0 or 1 */
// With 0 or 1 child, child is NULL or that child, respectively
TreeNode *child = cur->left != NULL ? cur->left : cur->right;
// Delete node cur
// Remove node cur
if (pre->left == cur) {
pre->left = child;
} else {
@@ -120,49 +120,49 @@ void removeItem(BinarySearchTree *bst, int num) {
// Free memory
free(cur);
} else {
/* Number of child nodes = 2 */
// Get next node of cur in inorder traversal
/* Number of children = 2 */
// Get the inorder successor of cur
TreeNode *tmp = cur->right;
while (tmp->left != NULL) {
tmp = tmp->left;
}
int tmpVal = tmp->val;
// Recursively delete node tmp
// Recursively remove node tmp
removeItem(bst, tmp->val);
// Replace cur with tmp
// Replace the value of cur with the value of tmp
cur->val = tmpVal;
}
}
/* Driver Code */
/* Driver code */
int main() {
/* Initialize binary search tree */
/* Initialize the binary search tree */
int nums[] = {8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15};
BinarySearchTree *bst = newBinarySearchTree();
for (int i = 0; i < sizeof(nums) / sizeof(int); i++) {
insert(bst, nums[i]);
}
printf("Initialized binary tree is\n");
printf("Binary tree after initialization:\n");
printTree(getRoot(bst));
/* Search node */
/* Find a node */
TreeNode *node = search(bst, 7);
printf("Found node object value = %d\n", node->val);
printf("Value of the node found = %d\n", node->val);
/* Insert node */
/* Insert a node */
insert(bst, 16);
printf("After inserting node 16, binary tree is\n");
printf("Binary tree after inserting node 16:\n");
printTree(getRoot(bst));
/* Remove node */
/* Remove a node */
removeItem(bst, 1);
printf("After removing node 1, binary tree is\n");
printf("Binary tree after removing node 1:\n");
printTree(getRoot(bst));
removeItem(bst, 2);
printf("After removing node 2, binary tree is\n");
printf("Binary tree after removing node 2:\n");
printTree(getRoot(bst));
removeItem(bst, 4);
printf("After removing node 4, binary tree is\n");
printf("Binary tree after removing node 4:\n");
printTree(getRoot(bst));
// Free memory

View File

@@ -6,36 +6,36 @@
#include "../utils/common.h"
/* Driver Code */
/* Driver code */
int main() {
/* Initialize binary tree */
// Initialize nodes
/* Initialize the binary tree */
// Initialize the nodes
TreeNode *n1 = newTreeNode(1);
TreeNode *n2 = newTreeNode(2);
TreeNode *n3 = newTreeNode(3);
TreeNode *n4 = newTreeNode(4);
TreeNode *n5 = newTreeNode(5);
// Build references (pointers) between nodes
// Set up references (pointers) between the nodes
n1->left = n2;
n1->right = n3;
n2->left = n4;
n2->right = n5;
printf("Initialize binary tree\n");
printf("Initialize the binary tree\n");
printTree(n1);
/* Insert node P between n1 -> n2 */
/* Insert and remove nodes */
TreeNode *P = newTreeNode(0);
// Delete node
// Insert node P between n1 and n2 in n1 -> n2
n1->left = P;
P->left = n2;
printf("After inserting node P\n");
printf("After inserting node P:\n");
printTree(n1);
// Remove node P
n1->left = n2;
// Free memory
free(P);
printf("After removing node P\n");
printf("After removing node P:\n");
printTree(n1);
freeMemoryTree(n1);

View File

@@ -18,52 +18,52 @@ int *levelOrder(TreeNode *root, int *size) {
/* Auxiliary queue */
queue = (TreeNode **)malloc(sizeof(TreeNode *) * MAX_SIZE);
// Queue pointer
// Queue indices
front = 0, rear = 0;
// Add root node
// Enqueue the root node
queue[rear++] = root;
// Initialize a list to save the traversal sequence
// Initialize a list to store the traversal sequence
/* Auxiliary array */
arr = (int *)malloc(sizeof(int) * MAX_SIZE);
// Array pointer
// Array index
index = 0;
while (front < rear) {
// Dequeue
// Dequeue from the queue
node = queue[front++];
// Save node value
// Store the node value
arr[index++] = node->val;
if (node->left != NULL) {
// Left child node enqueue
// Enqueue the left child
queue[rear++] = node->left;
}
if (node->right != NULL) {
// Right child node enqueue
// Enqueue the right child
queue[rear++] = node->right;
}
}
// Update array length value
// Update the array length
*size = index;
arr = realloc(arr, sizeof(int) * (*size));
// Free auxiliary array space
// Free the auxiliary queue array
free(queue);
return arr;
}
/* Driver Code */
/* Driver code */
int main() {
/* Initialize binary tree */
// Here we use a function to generate a binary tree directly from an array
/* Initialize the binary tree */
// Use a helper function that builds a binary tree directly from an array
int nums[] = {1, 2, 3, 4, 5, 6, 7};
int size = sizeof(nums) / sizeof(int);
TreeNode *root = arrayToTree(nums, size);
printf("Initialize binary tree\n");
printf("Initialize the binary tree\n");
printTree(root);
/* Level-order traversal */
// Need to pass array length
// Pass a pointer to receive the array length
int *arr = levelOrder(root, &size);
printf("Level-order traversal node print sequence = ");
printf("Node sequence from level-order traversal = ");
printArray(arr, size);
// Free memory

View File

@@ -8,14 +8,14 @@
#define MAX_SIZE 100
// Auxiliary array for storing traversal sequence
// Auxiliary array for storing the traversal sequence
int arr[MAX_SIZE];
/* Preorder traversal */
void preOrder(TreeNode *root, int *size) {
if (root == NULL)
return;
// Visit priority: root node -> left subtree -> right subtree
// Visit order: root -> left subtree -> right subtree
arr[(*size)++] = root->val;
preOrder(root->left, size);
preOrder(root->right, size);
@@ -25,7 +25,7 @@ void preOrder(TreeNode *root, int *size) {
void inOrder(TreeNode *root, int *size) {
if (root == NULL)
return;
// Visit priority: left subtree -> root node -> right subtree
// Visit order: left subtree -> root -> right subtree
inOrder(root->left, size);
arr[(*size)++] = root->val;
inOrder(root->right, size);
@@ -35,39 +35,39 @@ void inOrder(TreeNode *root, int *size) {
void postOrder(TreeNode *root, int *size) {
if (root == NULL)
return;
// Visit priority: left subtree -> right subtree -> root node
// Visit order: left subtree -> right subtree -> root
postOrder(root->left, size);
postOrder(root->right, size);
arr[(*size)++] = root->val;
}
/* Driver Code */
/* Driver code */
int main() {
/* Initialize binary tree */
// Here we use a function to generate a binary tree directly from an array
/* Initialize the binary tree */
// Use a helper function that builds a binary tree directly from an array
int nums[] = {1, 2, 3, 4, 5, 6, 7};
int size = sizeof(nums) / sizeof(int);
TreeNode *root = arrayToTree(nums, size);
printf("Initialize binary tree\n");
printf("Initialize the binary tree\n");
printTree(root);
/* Preorder traversal */
// Initialize auxiliary array
// Initialize the auxiliary array's element count
size = 0;
preOrder(root, &size);
printf("Pre-order traversal node print sequence = ");
printf("Node sequence from preorder traversal = ");
printArray(arr, size);
/* Inorder traversal */
size = 0;
inOrder(root, &size);
printf("In-order traversal node print sequence = ");
printf("Node sequence from inorder traversal = ");
printArray(arr, size);
/* Postorder traversal */
size = 0;
postOrder(root, &size);
printf("Post-order traversal node print sequence = ");
printf("Node sequence from postorder traversal = ");
printArray(arr, size);
freeMemoryTree(root);

View File

@@ -20,7 +20,7 @@
#include "tree_node.h"
#include "vertex.h"
// hash table lib
// Hash table library
#include "uthash.h"
#include "vector.h"

View File

@@ -18,10 +18,10 @@ void testTreeNode() {
int size = sizeof(nums) / sizeof(int);
TreeNode *root = arrayToTree(nums, size);
// print tree
// Print the tree
printTree(root);
// tree to arr
// Convert the tree to an array
int *arr = treeToArray(root, &size);
printArray(arr, size);
}

View File

@@ -14,10 +14,10 @@ extern "C" {
/* Linked list node structure */
typedef struct ListNode {
int val; // Node value
struct ListNode *next; // Reference to next node
struct ListNode *next; // Reference to the next node
} ListNode;
/* Constructor, initialize a new node */
/* Constructor: initialize a new node */
ListNode *newListNode(int val) {
ListNode *node;
node = (ListNode *)malloc(sizeof(ListNode));
@@ -26,7 +26,7 @@ ListNode *newListNode(int val) {
return node;
}
/* Deserialize array to linked list */
/* Deserialize an array into a linked list */
ListNode *arrToLinkedList(const int *arr, size_t size) {
if (size <= 0) {
return NULL;
@@ -41,7 +41,7 @@ ListNode *arrToLinkedList(const int *arr, size_t size) {
return dummy->next;
}
/* Free memory allocated to linked list */
/* Free the memory allocated to the linked list */
void freeMemoryLinkedList(ListNode *cur) {
// Free memory
ListNode *pre;

View File

@@ -18,7 +18,7 @@
extern "C" {
#endif
/* Print array */
/* Print an array */
void printArray(int arr[], int size) {
if (arr == NULL || size == 0) {
printf("[]");
@@ -31,7 +31,7 @@ void printArray(int arr[], int size) {
printf("%d]\n", arr[size - 1]);
}
/* Print array */
/* Print an array */
void printArrayFloat(float arr[], int size) {
if (arr == NULL || size == 0) {
printf("[]");
@@ -44,7 +44,7 @@ void printArrayFloat(float arr[], int size) {
printf("%.2f]\n", arr[size - 1]);
}
/* Print linked list */
/* Print a linked list */
void printLinkedList(ListNode *node) {
if (node == NULL) {
return;
@@ -78,7 +78,7 @@ void showTrunks(Trunk *trunk) {
}
/**
* Print binary tree
* Print a binary tree
* This tree printer is borrowed from TECHIE DELIGHT
* https://www.techiedelight.com/c-program-print-binary-tree/
*/
@@ -109,17 +109,17 @@ void printTreeHelper(TreeNode *node, Trunk *prev, bool isRight) {
printTreeHelper(node->left, trunk, false);
}
/* Print binary tree */
/* Print a binary tree */
void printTree(TreeNode *root) {
printTreeHelper(root, NULL, false);
}
/* Print heap */
/* Print a heap */
void printHeap(int arr[], int size) {
TreeNode *root;
printf("Heap array representation:");
printf("Array representation of the heap:");
printArray(arr, size);
printf("Heap tree representation:\n");
printf("Tree representation of the heap:\n");
root = arrayToTree(arr, size);
printTree(root);
}

View File

@@ -19,8 +19,8 @@ extern "C" {
typedef struct TreeNode {
int val; // Node value
int height; // Node height
struct TreeNode *left; // Left child pointer
struct TreeNode *right; // Right child pointer
struct TreeNode *left; // Pointer to the left child
struct TreeNode *right; // Pointer to the right child
} TreeNode;
/* Constructor */
@@ -35,11 +35,11 @@ TreeNode *newTreeNode(int val) {
return node;
}
// For the serialization encoding rules, please refer to:
// https://www.hello-algo.com/chapter_tree/array_representation_of_tree/
// Array representation of binary tree:
// For the serialization rules, see:
// https://www.hello-algo.com/en/chapter_tree/array_representation_of_tree/
// Array representation of the binary tree:
// [1, 2, 3, 4, None, 6, 7, 8, 9, None, None, 12, None, None, 15]
// Linked list representation of binary tree:
// Linked representation of the binary tree:
// /——— 15
// /——— 7
// /——— 3
@@ -91,7 +91,7 @@ int *treeToArray(TreeNode *root, int *size) {
return res;
}
/* Free binary tree memory */
/* Free the binary tree memory */
void freeMemoryTree(TreeNode *root) {
if (root == NULL)
return;

View File

@@ -11,15 +11,15 @@
extern "C" {
#endif
/* Define vector type */
/* Define the vector type */
typedef struct vector {
int size; // Current vector size
int capacity; // Current vector capacity
int depth; // Current vector depth
void **data; // Pointer array to data
void **data; // Array of pointers to the data
} vector;
/* Construct vector */
/* Construct a vector */
vector *newVector() {
vector *v = malloc(sizeof(vector));
v->size = 0;
@@ -29,7 +29,7 @@ vector *newVector() {
return v;
}
/* Construct vector with specified size and default value */
/* Construct a vector with the specified size and default element value */
vector *_newVector(int size, void *elem, int elemSize) {
vector *v = malloc(sizeof(vector));
v->size = size;
@@ -44,7 +44,7 @@ vector *_newVector(int size, void *elem, int elemSize) {
return v;
}
/* Destruct vector */
/* Destroy the vector */
void delVector(vector *v) {
if (v) {
if (v->depth == 0) {
@@ -63,7 +63,7 @@ void delVector(vector *v) {
}
}
/* Add element (by copy) to vector tail */
/* Append a copy of an element to the vector */
void vectorPushback(vector *v, void *elem, int elemSize) {
if (v->size == v->capacity) {
v->capacity *= 2;
@@ -74,7 +74,7 @@ void vectorPushback(vector *v, void *elem, int elemSize) {
v->data[v->size++] = tmp;
}
/* Pop element from vector tail */
/* Pop the last element from the vector */
void vectorPopback(vector *v) {
if (v->size != 0) {
free(v->data[v->size - 1]);
@@ -82,7 +82,7 @@ void vectorPopback(vector *v) {
}
}
/* Clear vector */
/* Clear the vector */
void vectorClear(vector *v) {
delVector(v);
v->size = 0;
@@ -91,23 +91,23 @@ void vectorClear(vector *v) {
v->data = malloc(v->capacity * sizeof(void *));
}
/* Get vector size */
/* Get the vector size */
int vectorSize(vector *v) {
return v->size;
}
/* Get vector tail element */
/* Get the last element of the vector */
void *vectorBack(vector *v) {
int n = v->size;
return n > 0 ? v->data[n - 1] : NULL;
}
/* Get vector head element */
/* Get the first element of the vector */
void *vectorFront(vector *v) {
return v->size > 0 ? v->data[0] : NULL;
}
/* Get vector element at index pos */
/* Get the vector element at index pos */
void *vectorAt(vector *v, int pos) {
if (pos < 0 || pos >= v->size) {
printf("vectorAt: out of range\n");
@@ -116,7 +116,7 @@ void *vectorAt(vector *v, int pos) {
return v->data[pos];
}
/* Set vector element at index pos */
/* Set the vector element at index pos */
void vectorSet(vector *v, int pos, void *elem, int elemSize) {
if (pos < 0 || pos >= v->size) {
printf("vectorSet: out of range\n");
@@ -128,19 +128,19 @@ void vectorSet(vector *v, int pos, void *elem, int elemSize) {
v->data[pos] = tmp;
}
/* Expand vector capacity */
/* Grow the vector capacity */
void vectorExpand(vector *v) {
v->capacity *= 2;
v->data = realloc(v->data, v->capacity * sizeof(void *));
}
/* Shrink vector capacity */
/* Shrink the vector capacity */
void vectorShrink(vector *v) {
v->capacity /= 2;
v->data = realloc(v->data, v->capacity * sizeof(void *));
}
/* Insert element at vector index pos */
/* Insert an element at vector index pos */
void vectorInsert(vector *v, int pos, void *elem, int elemSize) {
if (v->size == v->capacity) {
vectorExpand(v);
@@ -154,7 +154,7 @@ void vectorInsert(vector *v, int pos, void *elem, int elemSize) {
v->size++;
}
/* Delete element at vector index pos */
/* Remove the element at vector index pos */
void vectorErase(vector *v, int pos) {
if (v->size != 0) {
free(v->data[pos]);
@@ -172,40 +172,40 @@ void vectorSwap(vector *v, int i, int j) {
v->data[j] = tmp;
}
/* Is vector empty */
/* Check whether the vector is empty */
bool vectorEmpty(vector *v) {
return v->size == 0;
}
/* Is vector full */
/* Check whether the vector is full */
bool vectorFull(vector *v) {
return v->size == v->capacity;
}
/* Are vectors equal */
/* Check whether the vectors are equal */
bool vectorEqual(vector *v1, vector *v2) {
if (v1->size != v2->size) {
printf("size not equal\n");
printf("Sizes are not equal\n");
return false;
}
for (int i = 0; i < v1->size; i++) {
void *a = v1->data[i];
void *b = v2->data[i];
if (memcmp(a, b, sizeof(a)) != 0) {
printf("data %d not equal\n", i);
printf("Data at index %d are not equal\n", i);
return false;
}
}
return true;
}
/* Sort vector internally */
/* Sort the elements within the vector */
void vectorSort(vector *v, int (*cmp)(const void *, const void *)) {
qsort(v->data, v->size, sizeof(void *), cmp);
}
/* Print function, need to pass a function to print variables */
/* Currently only supports printing vector with depth 1 */
/* Print the vector using a supplied element-printing function */
/* Currently supports printing only vectors of depth 1 */
void printVector(vector *v, void (*printFunc)(vector *v, void *p)) {
if (v) {
if (v->depth == 0) {
@@ -235,7 +235,7 @@ void printVector(vector *v, void (*printFunc)(vector *v, void *p)) {
}
}
/* Currently only supports printing vector with depth 2 */
/* Currently supports printing only vectors of depth 2 */
void printVectorMatrix(vector *vv, void (*printFunc)(vector *v, void *p)) {
printf("[\n");
for (int i = 0; i < vv->size; i++) {

View File

@@ -16,7 +16,7 @@ typedef struct {
int val;
} Vertex;
/* Constructor, initialize a new node */
/* Constructor: initialize a new vertex */
Vertex *newVertex(int val) {
Vertex *vet;
vet = (Vertex *)malloc(sizeof(Vertex));
@@ -24,7 +24,7 @@ Vertex *newVertex(int val) {
return vet;
}
/* Convert value array to vertex array */
/* Convert an array of values to an array of vertices */
Vertex **valsToVets(int *vals, int size) {
Vertex **vertices = (Vertex **)malloc(size * sizeof(Vertex *));
for (int i = 0; i < size; ++i) {
@@ -33,7 +33,7 @@ Vertex **valsToVets(int *vals, int size) {
return vertices;
}
/* Convert vertex array to value array */
/* Convert an array of vertices to an array of values */
int *vetsToVals(Vertex **vertices, int size) {
int *vals = (int *)malloc(size * sizeof(int));
for (int i = 0; i < size; ++i) {

View File

@@ -1,8 +1,8 @@
# Ignore all
*
# Unignore all with extensions
# Unignore all files with extensions
!*.*
# Unignore all dirs
# Unignore all directories
!*/
*.dSYM/

View File

@@ -6,18 +6,18 @@
#include "../utils/common.hpp"
/* Random access to element */
/* Access an element at a random index */
int randomAccess(int *nums, int size) {
// Randomly select a number from interval [0, size)
// Choose a random number in [0, size)
int randomIndex = rand() % size;
// Retrieve and return the random element
// Get and return the randomly selected element
int randomNum = nums[randomIndex];
return randomNum;
}
/* Extend array length */
/* Extend the array length */
int *extend(int *nums, int size, int enlarge) {
// Initialize an array with extended length
// Initialize an array with the extended length
int *res = new int[size + enlarge];
// Copy all elements from the original array to the new array
for (int i = 0; i < size; i++) {
@@ -25,38 +25,38 @@ int *extend(int *nums, int size, int enlarge) {
}
// Free memory
delete[] nums;
// Return the extended new array
// Return the new, extended array
return res;
}
/* Insert element num at index index in the array */
/* Insert element num at index `index` in the array */
void insert(int *nums, int size, int num, int index) {
// Move all elements at and after index index backward by one position
// Shift all elements at and after index `index` one position to the right
for (int i = size - 1; i > index; i--) {
nums[i] = nums[i - 1];
}
// Assign num to the element at index index
// Assign num to the element at index `index`
nums[index] = num;
}
/* Remove the element at index index */
/* Remove the element at index `index` */
void remove(int *nums, int size, int index) {
// Move all elements after index index forward by one position
// Shift all elements after index `index` one position to the left
for (int i = index; i < size - 1; i++) {
nums[i] = nums[i + 1];
}
}
/* Traverse array */
/* Traverse the array */
void traverse(int *nums, int size) {
int count = 0;
// Traverse array by index
// Traverse the array by index
for (int i = 0; i < size; i++) {
count += nums[i];
}
}
/* Find the specified element in the array */
/* Find a specified element in the array */
int find(int *nums, int size, int target) {
for (int i = 0; i < size; i++) {
if (nums[i] == target)
@@ -65,9 +65,9 @@ int find(int *nums, int size, int target) {
return -1;
}
/* Driver Code */
/* Driver code */
int main() {
/* Initialize array */
/* Initialize the array */
int size = 5;
int *arr = new int[size];
cout << "Array arr = ";
@@ -77,33 +77,33 @@ int main() {
cout << "Array nums = ";
printArray(nums, size);
/* Insert element */
/* Random access */
int randomNum = randomAccess(nums, size);
cout << "Get random element in nums " << randomNum << endl;
cout << "Randomly selected element from nums: " << randomNum << endl;
/* Traverse array */
/* Extend the length */
int enlarge = 3;
nums = extend(nums, size, enlarge);
size += enlarge;
cout << "Extend array length to 8, resulting in nums = ";
cout << "Extend the array length to 8, giving nums = ";
printArray(nums, size);
/* Insert element */
/* Insert an element */
insert(nums, size, 6, 3);
cout << "Insert number 6 at index 3, resulting in nums = ";
cout << "Insert the number 6 at index 3, giving nums = ";
printArray(nums, size);
/* Remove element */
/* Remove an element */
remove(nums, size, 2);
cout << "Remove element at index 2, resulting in nums = ";
cout << "Remove the element at index 2, giving nums = ";
printArray(nums, size);
/* Traverse array */
/* Traverse the array */
traverse(nums, size);
/* Find element */
/* Find an element */
int index = find(nums, size, 3);
cout << "Find element 3 in nums, get index = " << index << endl;
cout << "Find element 3 in nums, giving index = " << index << endl;
// Free memory
delete[] arr;

View File

@@ -25,7 +25,7 @@ void remove(ListNode *n0) {
delete P;
}
/* Access the node at index index in the linked list */
/* Access the node at index `index` in the linked list */
ListNode *access(ListNode *head, int index) {
for (int i = 0; i < index; i++) {
if (head == nullptr)
@@ -47,40 +47,40 @@ int find(ListNode *head, int target) {
return -1;
}
/* Driver Code */
/* Driver code */
int main() {
/* Initialize linked list */
// Initialize each node
/* Initialize the linked list */
// Initialize the individual nodes
ListNode *n0 = new ListNode(1);
ListNode *n1 = new ListNode(3);
ListNode *n2 = new ListNode(2);
ListNode *n3 = new ListNode(5);
ListNode *n4 = new ListNode(4);
// Build references between nodes
// Set up references between the nodes
n0->next = n1;
n1->next = n2;
n2->next = n3;
n3->next = n4;
cout << "Initialized linked list is" << endl;
cout << "The initialized linked list is" << endl;
printLinkedList(n0);
/* Insert node */
/* Insert a node */
insert(n0, new ListNode(0));
cout << "Linked list after inserting node is" << endl;
cout << "The linked list after inserting a node is" << endl;
printLinkedList(n0);
/* Remove node */
/* Remove a node */
remove(n0);
cout << "Linked list after removing node is" << endl;
cout << "The linked list after removing a node is" << endl;
printLinkedList(n0);
/* Access node */
/* Access a node */
ListNode *node = access(n0, 3);
cout << "Value of node at index 3 in linked list = " << node->val << endl;
cout << "Value of the linked list node at index 3 = " << node->val << endl;
/* Search node */
/* Find a node */
int index = find(n0, 2);
cout << "Index of node with value 2 in linked list = " << index << endl;
cout << "Index of the linked list node with value 2 = " << index << endl;
// Free memory
freeMemoryLinkedList(n0);

View File

@@ -6,28 +6,28 @@
#include "../utils/common.hpp"
/* Driver Code */
/* Driver code */
int main() {
/* Initialize list */
/* Initialize the list */
vector<int> nums = {1, 3, 2, 5, 4};
cout << "List nums = ";
printVector(nums);
/* Update element */
/* Access an element */
int num = nums[1];
cout << "Access element at index 1, get num = " << num << endl;
cout << "Access the element at index 1, giving num = " << num << endl;
/* Add elements at the end */
/* Update an element */
nums[1] = 0;
cout << "Update element at index 1 to 0, resulting in nums = ";
cout << "Update the element at index 1 to 0, giving nums = ";
printVector(nums);
/* Remove element */
/* Clear the list */
nums.clear();
cout << "After clearing list, nums = ";
cout << "After clearing the list, nums = ";
printVector(nums);
/* Direct traversal of list elements */
/* Append an element at the end */
nums.push_back(1);
nums.push_back(3);
nums.push_back(2);
@@ -36,22 +36,22 @@ int main() {
cout << "After adding elements, nums = ";
printVector(nums);
/* Sort list */
/* Insert an element in the middle */
nums.insert(nums.begin() + 3, 6);
cout << "Insert number 6 at index 3, resulting in nums = ";
cout << "Insert the number 6 at index 3, giving nums = ";
printVector(nums);
/* Remove element */
/* Remove an element */
nums.erase(nums.begin() + 3);
cout << "Remove element at index 3, resulting in nums = ";
cout << "Remove the element at index 3, giving nums = ";
printVector(nums);
/* Traverse list by index */
/* Traverse the list by index */
int count = 0;
for (int i = 0; i < nums.size(); i++) {
count += nums[i];
}
/* Directly traverse list elements */
/* Iterate directly over the list elements */
count = 0;
for (int x : nums) {
count += x;
@@ -60,12 +60,12 @@ int main() {
/* Concatenate two lists */
vector<int> nums1 = {6, 8, 7, 10, 9};
nums.insert(nums.end(), nums1.begin(), nums1.end());
cout << "Concatenate list nums1 to nums, resulting in nums = ";
cout << "After appending list nums1 to nums, nums = ";
printVector(nums);
/* Sort list */
/* Sort the list */
sort(nums.begin(), nums.end());
cout << "After sorting list, nums = ";
cout << "After sorting the list, nums = ";
printVector(nums);
return 0;

View File

@@ -9,10 +9,10 @@
/* List class */
class MyList {
private:
int *arr; // Array (stores list elements)
int *arr; // Array (stores the list elements)
int arrCapacity = 10; // List capacity
int arrSize = 0; // List length (current number of elements)
int extendRatio = 2; // Multiple by which the list capacity is extended each time
int extendRatio = 2; // Factor by which the list capacity grows each time
public:
/* Constructor */
@@ -25,34 +25,34 @@ class MyList {
delete[] arr;
}
/* Get list length (current number of elements)*/
/* Get the list length (current number of elements)*/
int size() {
return arrSize;
}
/* Get list capacity */
/* Get the list capacity */
int capacity() {
return arrCapacity;
}
/* Update element */
/* Access an element */
int get(int index) {
// If the index is out of bounds, throw an exception, as below
// Raise an exception if the index is out of bounds; the same applies below
if (index < 0 || index >= size())
throw out_of_range("Index out of bounds");
return arr[index];
}
/* Add elements at the end */
/* Update an element */
void set(int index, int num) {
if (index < 0 || index >= size())
throw out_of_range("Index out of bounds");
arr[index] = num;
}
/* Direct traversal of list elements */
/* Append an element at the end */
void add(int num) {
// When the number of elements exceeds capacity, trigger the extension mechanism
// Grow the capacity when adding an element would exceed it
if (size() == capacity())
extendCapacity();
arr[size()] = num;
@@ -60,14 +60,14 @@ class MyList {
arrSize++;
}
/* Sort list */
/* Insert an element in the middle */
void insert(int index, int num) {
if (index < 0 || index >= size())
throw out_of_range("Index out of bounds");
// When the number of elements exceeds capacity, trigger the extension mechanism
// Grow the capacity when adding an element would exceed it
if (size() == capacity())
extendCapacity();
// Move all elements after index index forward by one position
// Shift all elements at and after index `index` one position to the right
for (int j = size() - 1; j >= index; j--) {
arr[j + 1] = arr[j];
}
@@ -76,12 +76,12 @@ class MyList {
arrSize++;
}
/* Remove element */
/* Remove an element */
int remove(int index) {
if (index < 0 || index >= size())
throw out_of_range("Index out of bounds");
int num = arr[index];
// Create a new array with length _extend_ratio times the original array, and copy the original array to the new array
// Shift all elements after index `index` one position to the left
for (int j = index; j < size() - 1; j++) {
arr[j] = arr[j + 1];
}
@@ -91,9 +91,9 @@ class MyList {
return num;
}
/* Driver Code */
/* Grow the list capacity */
void extendCapacity() {
// Create a new array with length extendRatio times the original array
// Create a new array with extendRatio times the original array's length
int newCapacity = capacity() * extendRatio;
int *tmp = arr;
arr = new int[newCapacity];
@@ -106,9 +106,9 @@ class MyList {
arrCapacity = newCapacity;
}
/* Convert list to Vector for printing */
/* Convert the list to a vector for printing */
vector<int> toVector() {
// Elements enqueue
// Convert only the list elements within the occupied range
vector<int> vec(size());
for (int i = 0; i < size(); i++) {
vec[i] = arr[i];
@@ -117,11 +117,11 @@ class MyList {
}
};
/* Driver Code */
/* Driver code */
int main() {
/* Initialize list */
/* Initialize the list */
MyList *nums = new MyList();
/* Direct traversal of list elements */
/* Append an element at the end */
nums->add(1);
nums->add(3);
nums->add(2);
@@ -130,39 +130,39 @@ int main() {
cout << "List nums = ";
vector<int> vec = nums->toVector();
printVector(vec);
cout << "Capacity = " << nums->capacity() << ", length = " << nums->size() << endl;
cout << "Capacity = " << nums->capacity() << " , size = " << nums->size() << endl;
/* Sort list */
/* Insert an element in the middle */
nums->insert(3, 6);
cout << "Insert number 6 at index 3, resulting in nums = ";
cout << "Insert the number 6 at index 3, giving nums = ";
vec = nums->toVector();
printVector(vec);
/* Remove element */
/* Remove an element */
nums->remove(3);
cout << "Remove element at index 3, resulting in nums = ";
cout << "Remove the element at index 3, giving nums = ";
vec = nums->toVector();
printVector(vec);
/* Update element */
/* Access an element */
int num = nums->get(1);
cout << "Access element at index 1, get num = " << num << endl;
cout << "Access the element at index 1, giving num = " << num << endl;
/* Add elements at the end */
/* Update an element */
nums->set(1, 0);
cout << "Update element at index 1 to 0, resulting in nums = ";
cout << "Update the element at index 1 to 0, giving nums = ";
vec = nums->toVector();
printVector(vec);
/* Test capacity expansion mechanism */
/* Test capacity growth */
for (int i = 0; i < 10; i++) {
// At i = 5, the list length will exceed the list capacity, triggering the expansion mechanism
// When i = 5, the list length would exceed its capacity, triggering capacity growth
nums->add(i);
}
cout << "List nums after expansion = ";
cout << "List after capacity growth, nums = ";
vec = nums->toVector();
printVector(vec);
cout << "Capacity = " << nums->capacity() << ", length = " << nums->size() << endl;
cout << "Capacity = " << nums->capacity() << " , size = " << nums->size() << endl;
// Free memory
delete nums;

View File

@@ -6,40 +6,40 @@
#include "../utils/common.hpp"
/* Backtracking algorithm: N queens */
/* Backtracking: n-queens */
void backtrack(int row, int n, vector<vector<string>> &state, vector<vector<vector<string>>> &res, vector<bool> &cols,
vector<bool> &diags1, vector<bool> &diags2) {
// When all rows are placed, record the solution
// Record a solution when a queen has been placed in every row
if (row == n) {
res.push_back(state);
return;
}
// Traverse all columns
// Iterate over all columns
for (int col = 0; col < n; col++) {
// Calculate the main diagonal and anti-diagonal corresponding to this cell
// Calculate the main-diagonal and anti-diagonal indices for this square
int diag1 = row - col + n - 1;
int diag2 = row + col;
// Pruning: do not allow queens to exist in the column, main diagonal, and anti-diagonal of this cell
// Prune: the square must have no queen in its column, main diagonal, or anti-diagonal
if (!cols[col] && !diags1[diag1] && !diags2[diag2]) {
// Attempt: place the queen in this cell
// Try: place a queen on this square
state[row][col] = "Q";
cols[col] = diags1[diag1] = diags2[diag2] = true;
// Place the next row
// Place a queen in the next row
backtrack(row + 1, n, state, res, cols, diags1, diags2);
// Backtrack: restore this cell to an empty cell
// Backtrack: restore this square to empty
state[row][col] = "#";
cols[col] = diags1[diag1] = diags2[diag2] = false;
}
}
}
/* Solve N queens */
/* Solve the n-queens problem */
vector<vector<vector<string>>> nQueens(int n) {
// Initialize an n*n chessboard, where 'Q' represents a queen and '#' represents an empty cell
// Initialize an n*n board, where 'Q' represents a queen and '#' represents an empty square
vector<vector<string>> state(n, vector<string>(n, "#"));
vector<bool> cols(n, false); // Record whether there is a queen in the column
vector<bool> diags1(2 * n - 1, false); // Record whether there is a queen on the main diagonal
vector<bool> diags2(2 * n - 1, false); // Record whether there is a queen on the anti-diagonal
vector<bool> cols(n, false); // Track whether a column contains a queen
vector<bool> diags1(2 * n - 1, false); // Track whether a main diagonal contains a queen
vector<bool> diags2(2 * n - 1, false); // Track whether an anti-diagonal contains a queen
vector<vector<vector<string>>> res;
backtrack(0, n, state, res, cols, diags1, diags2);
@@ -47,13 +47,13 @@ vector<vector<vector<string>>> nQueens(int n) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
int n = 4;
vector<vector<vector<string>>> res = nQueens(n);
cout << "Input board size is " << n << endl;
cout << "Total queen placement solutions: " << res.size() << endl;
cout << "Board width and height: " << n << endl;
cout << "Queen placements: " << res.size() << " solutions" << endl;
for (const vector<vector<string>> &state : res) {
cout << "--------------------" << endl;
for (const vector<string> &row : state) {

View File

@@ -6,24 +6,24 @@
#include "../utils/common.hpp"
/* Backtracking algorithm: Permutations I */
/* Backtracking: permutations I */
void backtrack(vector<int> &state, const vector<int> &choices, vector<bool> &selected, vector<vector<int>> &res) {
// When the state length equals the number of elements, record the solution
// Record a solution when the state length equals the number of elements
if (state.size() == choices.size()) {
res.push_back(state);
return;
}
// Traverse all choices
// Iterate over all choices
for (int i = 0; i < choices.size(); i++) {
int choice = choices[i];
// Pruning: do not allow repeated selection of elements
// Prune: do not choose an element more than once
if (!selected[i]) {
// Attempt: make choice, update state
// Try: make a choice and update the state
selected[i] = true;
state.push_back(choice);
// Proceed to the next round of selection
// Proceed to the next choice
backtrack(state, choices, selected, res);
// Backtrack: undo choice, restore to previous state
// Backtrack: undo the choice and restore the previous state
selected[i] = false;
state.pop_back();
}
@@ -39,7 +39,7 @@ vector<vector<int>> permutationsI(vector<int> nums) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
vector<int> nums = {1, 2, 3};

View File

@@ -6,26 +6,26 @@
#include "../utils/common.hpp"
/* Backtracking algorithm: Permutations II */
/* Backtracking: permutations II */
void backtrack(vector<int> &state, const vector<int> &choices, vector<bool> &selected, vector<vector<int>> &res) {
// When the state length equals the number of elements, record the solution
// Record a solution when the state length equals the number of elements
if (state.size() == choices.size()) {
res.push_back(state);
return;
}
// Traverse all choices
// Iterate over all choices
unordered_set<int> duplicated;
for (int i = 0; i < choices.size(); i++) {
int choice = choices[i];
// Pruning: do not allow repeated selection of elements and do not allow repeated selection of equal elements
// Prune: do not reuse an element or choose the same value again at this depth
if (!selected[i] && duplicated.find(choice) == duplicated.end()) {
// Attempt: make choice, update state
duplicated.emplace(choice); // Record the selected element value
// Try: make a choice and update the state
duplicated.emplace(choice); // Record the chosen value
selected[i] = true;
state.push_back(choice);
// Proceed to the next round of selection
// Proceed to the next choice
backtrack(state, choices, selected, res);
// Backtrack: undo choice, restore to previous state
// Backtrack: undo the choice and restore the previous state
selected[i] = false;
state.pop_back();
}
@@ -41,7 +41,7 @@ vector<vector<int>> permutationsII(vector<int> nums) {
return res;
}
/* Driver Code */
/* Driver code */
int main() {
vector<int> nums = {1, 1, 2};

View File

@@ -8,23 +8,23 @@
vector<TreeNode *> res;
/* Preorder traversal: Example 1 */
/* Preorder traversal: example 1 */
void preOrder(TreeNode *root) {
if (root == nullptr) {
return;
}
if (root->val == 7) {
// Record solution
// Record the solution
res.push_back(root);
}
preOrder(root->left);
preOrder(root->right);
}
/* Driver Code */
/* Driver code */
int main() {
TreeNode *root = vectorToTree(vector<int>{1, 7, 3, 4, 5, 6, 7});
cout << "\nInitialize binary tree" << endl;
cout << "\nInitialize the binary tree" << endl;
printTree(root);
// Preorder traversal

View File

@@ -9,15 +9,15 @@
vector<TreeNode *> path;
vector<vector<TreeNode *>> res;
/* Preorder traversal: Example 2 */
/* Preorder traversal: example 2 */
void preOrder(TreeNode *root) {
if (root == nullptr) {
return;
}
// Attempt
// Try
path.push_back(root);
if (root->val == 7) {
// Record solution
// Record the solution
res.push_back(path);
}
preOrder(root->left);
@@ -26,16 +26,16 @@ void preOrder(TreeNode *root) {
path.pop_back();
}
/* Driver Code */
/* Driver code */
int main() {
TreeNode *root = vectorToTree(vector<int>{1, 7, 3, 4, 5, 6, 7});
cout << "\nInitialize binary tree" << endl;
cout << "\nInitialize the binary tree" << endl;
printTree(root);
// Preorder traversal
preOrder(root);
cout << "\nOutput all paths from root node to node 7" << endl;
cout << "\nOutput all paths from the root to nodes with value 7" << endl;
for (vector<TreeNode *> &path : res) {
vector<int> vals;
for (TreeNode *node : path) {

View File

@@ -9,16 +9,16 @@
vector<TreeNode *> path;
vector<vector<TreeNode *>> res;
/* Preorder traversal: Example 3 */
/* Preorder traversal: example 3 */
void preOrder(TreeNode *root) {
// Pruning
// Prune
if (root == nullptr || root->val == 3) {
return;
}
// Attempt
// Try
path.push_back(root);
if (root->val == 7) {
// Record solution
// Record the solution
res.push_back(path);
}
preOrder(root->left);
@@ -27,16 +27,16 @@ void preOrder(TreeNode *root) {
path.pop_back();
}
/* Driver Code */
/* Driver code */
int main() {
TreeNode *root = vectorToTree(vector<int>{1, 7, 3, 4, 5, 6, 7});
cout << "\nInitialize binary tree" << endl;
cout << "\nInitialize the binary tree" << endl;
printTree(root);
// Preorder traversal
preOrder(root);
cout << "\nOutput all paths from root node to node 7, requiring paths do not include nodes with value 3" << endl;
cout << "\nOutput all paths from the root to nodes with value 7, requiring that no node on the path has value 3" << endl;
for (vector<TreeNode *> &path : res) {
vector<int> vals;
for (TreeNode *node : path) {

View File

@@ -6,57 +6,57 @@
#include "../utils/common.hpp"
/* Check if the current state is a solution */
/* Check whether the current state is a solution */
bool isSolution(vector<TreeNode *> &state) {
return !state.empty() && state.back()->val == 7;
}
/* Record solution */
/* Record the solution */
void recordSolution(vector<TreeNode *> &state, vector<vector<TreeNode *>> &res) {
res.push_back(state);
}
/* Check if the choice is valid under the current state */
/* Check whether the choice is valid in the current state */
bool isValid(vector<TreeNode *> &state, TreeNode *choice) {
return choice != nullptr && choice->val != 3;
}
/* Update state */
/* Update the state */
void makeChoice(vector<TreeNode *> &state, TreeNode *choice) {
state.push_back(choice);
}
/* Restore state */
/* Restore the state */
void undoChoice(vector<TreeNode *> &state, TreeNode *choice) {
state.pop_back();
}
/* Backtracking algorithm: Example 3 */
/* Backtracking: example 3 */
void backtrack(vector<TreeNode *> &state, vector<TreeNode *> &choices, vector<vector<TreeNode *>> &res) {
// Check if it is a solution
// Check whether this is a solution
if (isSolution(state)) {
// Record solution
// Record the solution
recordSolution(state, res);
}
// Traverse all choices
// Iterate over all choices
for (TreeNode *choice : choices) {
// Pruning: check if the choice is valid
// Prune: check whether the choice is valid
if (isValid(state, choice)) {
// Attempt: make choice, update state
// Try: make a choice and update the state
makeChoice(state, choice);
// Proceed to the next round of selection
// Proceed to the next choice
vector<TreeNode *> nextChoices{choice->left, choice->right};
backtrack(state, nextChoices, res);
// Backtrack: undo choice, restore to previous state
// Backtrack: undo the choice and restore the previous state
undoChoice(state, choice);
}
}
}
/* Driver Code */
/* Driver code */
int main() {
TreeNode *root = vectorToTree(vector<int>{1, 7, 3, 4, 5, 6, 7});
cout << "\nInitialize binary tree" << endl;
cout << "\nInitialize the binary tree" << endl;
printTree(root);
// Backtracking algorithm
@@ -65,7 +65,7 @@ int main() {
vector<vector<TreeNode *>> res;
backtrack(state, choices, res);
cout << "\nOutput all paths from root node to node 7, requiring paths do not include nodes with value 3" << endl;
cout << "\nOutput all paths from the root to nodes with value 7, requiring that no node on the path has value 3" << endl;
for (vector<TreeNode *> &path : res) {
vector<int> vals;
for (TreeNode *node : path) {

View File

@@ -6,26 +6,26 @@
#include "../utils/common.hpp"
/* Backtracking algorithm: Subset sum I */
/* Backtracking: subset sum I */
void backtrack(vector<int> &state, int target, vector<int> &choices, int start, vector<vector<int>> &res) {
// When the subset sum equals target, record the solution
// Record a solution when the remaining target reaches 0
if (target == 0) {
res.push_back(state);
return;
}
// Traverse all choices
// Pruning 2: start traversing from start to avoid generating duplicate subsets
// Iterate over all choices
// Pruning 2: iterate from start to avoid generating duplicate subsets
for (int i = start; i < choices.size(); i++) {
// Pruning 1: if the subset sum exceeds target, end the loop directly
// This is because the array is sorted, and later elements are larger, so the subset sum will definitely exceed target
// Pruning 1: exit the loop if this choice exceeds the remaining target
// The array is sorted, so later elements are at least as large and also exceed the remaining target
if (target - choices[i] < 0) {
break;
}
// Attempt: make choice, update target, start
// Try: make a choice and update target and start
state.push_back(choices[i]);
// Proceed to the next round of selection
// Proceed to the next choice
backtrack(state, target - choices[i], choices, i, res);
// Backtrack: undo choice, restore to previous state
// Backtrack: undo the choice and restore the previous state
state.pop_back();
}
}
@@ -34,13 +34,13 @@ void backtrack(vector<int> &state, int target, vector<int> &choices, int start,
vector<vector<int>> subsetSumI(vector<int> &nums, int target) {
vector<int> state; // State (subset)
sort(nums.begin(), nums.end()); // Sort nums
int start = 0; // Start point for traversal
vector<vector<int>> res; // Result list (subset list)
int start = 0; // Starting index for iteration
vector<vector<int>> res; // Result list (list of subsets)
backtrack(state, target, nums, start, res);
return res;
}
/* Driver Code */
/* Driver code */
int main() {
vector<int> nums = {3, 4, 5};
int target = 9;
@@ -50,7 +50,7 @@ int main() {
cout << "Input array nums = ";
printVector(nums);
cout << "target = " << target << endl;
cout << "All subsets with sum equal to " << target << " are res = " << endl;
cout << "All subsets with sum " << target << " , res = " << endl;
printVectorMatrix(res);
return 0;

Some files were not shown because too many files have changed in this diff Show More