mirror of
https://github.com/krahets/hello-algo.git
synced 2026-11-01 21:24:27 +08:00
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:
@@ -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.
|
||||
|
||||
42
en/README.md
42
en/README.md
@@ -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¢er=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¢er=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
35
en/codes/Dockerfile
Normal 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"]
|
||||
4
en/codes/c/.gitignore
vendored
4
en/codes/c/.gitignore
vendored
@@ -1,8 +1,8 @@
|
||||
# Ignore all
|
||||
*
|
||||
# Unignore all with extensions
|
||||
# Unignore all files with extensions
|
||||
!*.*
|
||||
# Unignore all dirs
|
||||
# Unignore all directories
|
||||
!*/
|
||||
*.dSYM/
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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("[");
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/* Exponentiation by squaring */
|
||||
/* Fast exponentiation */
|
||||
int fastPow(int x, int n) {
|
||||
if (n == 0) {
|
||||
return 1;
|
||||
|
||||
@@ -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 = ");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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: ");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = ");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "tree_node.h"
|
||||
#include "vertex.h"
|
||||
|
||||
// hash table lib
|
||||
// Hash table library
|
||||
#include "uthash.h"
|
||||
|
||||
#include "vector.h"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
4
en/codes/cpp/.gitignore
vendored
4
en/codes/cpp/.gitignore
vendored
@@ -1,8 +1,8 @@
|
||||
# Ignore all
|
||||
*
|
||||
# Unignore all with extensions
|
||||
# Unignore all files with extensions
|
||||
!*.*
|
||||
# Unignore all dirs
|
||||
# Unignore all directories
|
||||
!*/
|
||||
|
||||
*.dSYM/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user