1.设单向链表的结点是按关键字从小到大排列的,试写出对此链表进行查找的算
如果查找成功,则返回指向关键字为 的结点的指针,否则返回NUIl
思路:
1. 定义链表节点的结构体
typedef struct Node {
int key; // 节点中存储的数据
struct Node* next; // 指向下一个节点的指针
} Node;
key
:节点中存储的数据,这里是一个int
类型的值。next
:指向下一个节点的指针,用于连接链表中的节点。
2. 查找特定值的函数 FindList
Node* FindList(Node* head, int target) {
Node* cur = head; // 当前节点指针,初始化为链表头节点
while (cur != NULL) { // 遍历链表直到结束
// 如果找到目标值,返回该节点
if (cur->key == target) {
return cur;
}
// 如果当前节点的值大于目标值,说明目标值不在链表中,返回 NULL
else if (cur->key > target) {
return NULL;
}
cur = cur->next; // 移动到下一个节点
}
return NULL; // 如果遍历完链表未找到目标值,返回 NULL
}
- 功能:在有序链表中查找特定值
target
。 - 流程:
- 从链表的头节点开始遍历。
- 如果当前节点的值等于目标值,返回该节点。
- 如果当前节点的值大于目标值,说明目标值不在链表中,返回
NULL
。 - 继续遍历下一个节点,直到链表结束。
- 如果遍历完链表未找到目标值,返回
NULL
。
3. 创建新节点的函数 createNode
Node* createNode(int key) {
Node* newNode = (Node*)malloc(sizeof(Node)); // 分配内存给新节点
if (newNode == NULL) { // 检查内存分配是否成功
printf("内存分配失败\n");
exit(1);
}
newNode->key = key; // 设置新节点的值
newNode->next = NULL; // 新节点的下一个节点指针初始化为 NULL
return newNode; // 返回新节点
}
- 功能:创建一个新节点,并初始化其值为
key
。 - 流程:
- 使用
malloc
分配内存给新节点。 - 检查内存分配是否成功,如果失败则输出错误信息并退出程序。
- 设置新节点的值为
key
。 - 初始化新节点的下一个节点指针为
NULL
。 - 返回新节点。
- 使用
4. 向链表中插入节点并保持链表有序的函数 insetNode
void insetNode(Node** head, int key) {
Node* newNode = createNode(key); // 创建新节点
if (*head == NULL || key < (*head)->key) {
// 如果链表为空或者新节点的值小于头节点的值,将新节点插入到链表头部
newNode->next = *head; // 新节点的下一个节点指针指向当前头节点
*head = newNode; // 更新头节点为新节点
} else {
Node* cur = *head; // 当前节点指针,初始化为链表头节点
while (cur->next != NULL && key > cur->next->key) {
// 找到合适的位置插入新节点
cur = cur->next; // 移动到下一个节点
}
newNode->next = cur->next; // 新节点的下一个节点指针指向当前节点的下一个节点
cur->next = newNode; // 当前节点的下一个节点指针指向新节点
}
}
- 功能:将新节点插入到有序链表中,并保持链表有序。
- 流程:
- 创建新节点。
- 如果链表为空或者新节点的值小于头节点的值,将新节点插入到链表头部。
- 否则,从链表头部开始遍历,找到合适的位置插入新节点(即新节点的值大于当前节点的值但小于下一个节点的值)。
- 更新节点的指针,将新节点插入到链表中。
5. 释放链表内存的函数 freeList
void freeList(Node* head) {
Node* current = head; // 当前节点指针,初始化为链表头节点
while (current != NULL) { // 遍历链表直到结束
Node* next = current->next; // 保存下一个节点的指针
free(current); // 释放当前节点的内存
current = next; // 移动到下一个节点
}
}
- 功能:释放链表中所有节点的内存。
- 流程:
- 从链表的头节点开始遍历。
- 保存当前节点的下一个节点的指针。
- 释放当前节点的内存。
- 移动到下一个节点,继续遍历直到链表结束。
6. 主函数 main
int main() {
Node* head = NULL; // 初始化链表头指针为 NULL
// 向链表中插入一些有序的值
insetNode(&head, 2);
insetNode(&head, 4);
insetNode(&head, 9);
insetNode(&head, 6);
insetNode(&head, 8);
insetNode(&head, 10);
int target = 6; // 要查找的目标值
Node* result = FindList(head, target); // 在链表中查找目标值
if (result != NULL) {
// 如果找到目标值,输出提示信息
printf("找到链表关键字 %d\n", target);
} else {
// 如果未找到目标值,输出提示信息
printf("没有找到链表关键字 %d\n", target);
}
// 释放链表内存
freeList(head);
return 0;
}
- 功能:初始化链表,插入一些有序的值,查找特定值,释放链表内存。
- 流程:
- 初始化链表头指针为
NULL
。 - 调用
insetNode
函数向链表中插入一些有序的值。 - 设定要查找的目标值。
- 调用
FindList
函数在链表中查找目标值,并根据查找结果输出提示信息。 - 调用
freeList
函数释放链表内存。 - 返回
0
,表示程序正常结束。
- 初始化链表头指针为
代码:
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点的结构体
typedef struct Node {
int key; // 节点中存储的数据
struct Node* next; // 指向下一个节点的指针
} Node;
// 在链表中查找特定值的函数
Node* FindList(Node* head, int target) {
Node* cur = head; // 当前节点指针,初始化为链表头节点
while (cur != NULL) { // 遍历链表直到结束
// 如果找到目标值,返回该节点
if (cur->key == target) {
return cur;
}
// 如果当前节点的值大于目标值,说明目标值不在链表中,返回 NULL
else if (cur->key > target) {
return NULL;
}
cur = cur->next; // 移动到下一个节点
}
return NULL; // 如果遍历完链表未找到目标值,返回 NULL
}
// 创建新节点的函数
Node* createNode(int key) {
Node* newNode = (Node*)malloc(sizeof(Node)); // 分配内存给新节点
if (newNode == NULL) { // 检查内存分配是否成功
printf("内存分配失败\n");
exit(1);
}
newNode->key = key; // 设置新节点的值
newNode->next = NULL; // 新节点的下一个节点指针初始化为 NULL
return newNode; // 返回新节点
}
// 向链表中插入节点并保持链表有序的函数
void insetNode(Node** head, int key) {
Node* newNode = createNode(key); // 创建新节点
if (*head == NULL || key < (*head)->key) {
// 如果链表为空或者新节点的值小于头节点的值,将新节点插入到链表头部
newNode->next = *head; // 新节点的下一个节点指针指向当前头节点
*head = newNode; // 更新头节点为新节点
} else {
Node* cur = *head; // 当前节点指针,初始化为链表头节点
while (cur->next != NULL && key > cur->next->key) {
// 找到合适的位置插入新节点
cur = cur->next; // 移动到下一个节点
}
newNode->next = cur->next; // 新节点的下一个节点指针指向当前节点的下一个节点
cur->next = newNode; // 当前节点的下一个节点指针指向新节点
}
}
// 释放链表内存的函数
void freeList(Node* head) {
Node* current = head; // 当前节点指针,初始化为链表头节点
while (current != NULL) { // 遍历链表直到结束
Node* next = current->next; // 保存下一个节点的指针
free(current); // 释放当前节点的内存
current = next; // 移动到下一个节点
}
}
int main() {
Node* head = NULL; // 初始化链表头指针为 NULL
// 向链表中插入一些有序的值
insetNode(&head, 2);
insetNode(&head, 4);
insetNode(&head, 9);
insetNode(&head, 6);
insetNode(&head, 8);
insetNode(&head, 10);
int target = 6; // 要查找的目标值
Node* result = FindList(head, target); // 在链表中查找目标值
if (result != NULL) {
// 如果找到目标值,输出提示信息
printf("找到链表关键字 %d\n", target);
} else {
// 如果未找到目标值,输出提示信息
printf("没有找到链表关键字 %d\n", target);
}
// 释放链表内存
freeList(head);
return 0;
}
2.试设计一个算法,求出指定结点在给定的二叉搜索树中所在的层次。
下面题目建立的二叉搜索树结构
50
/ \
30 70
/ \ / \
20 40 60 80
思路:
1. 定义二叉树结点
首先,我们需要定义一个表示二叉树结点的结构体TreeNode
,包含以下成员:
int val
:结点的值。TreeNode* left
:指向左子树的指针。TreeNode* right
:指向右子树的指针。
typedef struct TreeNode {
int val;
struct TreeNode* left;
struct TreeNode* right;
} TreeNode;
2. 创建新结点
为了在二叉搜索树中插入新结点,我们需要一个函数createNode
来创建新的结点并初始化其值和左右子树指针。
TreeNode* createNode(int val) {
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
newNode->val = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
3. 插入结点到二叉搜索树
插入操作是二叉搜索树的核心操作之一。我们需要根据结点的值来决定将其插入到左子树还是右子树。递归是实现插入操作的一种常见方式。
TreeNode* insert(TreeNode* root, int val) {
if (root == NULL) {
return createNode(val);
}
if (val < root->val) {
root->left = insert(root->left, val);
} else if (val > root->val) {
root->right = insert(root->right, val);
}
return root;
}
4. 查找结点的层次
查找结点的层次也是通过递归实现的。我们从根结点开始,逐层向下查找,直到找到目标结点或者确定结点不存在。
int findLevel(TreeNode* root, int key, int level) {
if (root == NULL) {
return -1;
}
if (root->val == key) {
return level;
}
int leftLevel = findLevel(root->left, key, level + 1);
if (leftLevel != -1) {
return leftLevel;
}
return findLevel(root->right, key, level + 1);
}
5. 打印二叉树(中序遍历)
中序遍历是一种常见的二叉树遍历方式,输出结果是有序的。我们通过递归实现中序遍历。
void inorderTraversal(TreeNode* root) {
if (root != NULL) {
inorderTraversal(root->left);
printf("%d ", root->val);
inorderTraversal(root->right);
}
}
6. 释放二叉树内存
为了避免内存泄漏,我们需要在程序结束前释放二叉树的所有结点。同样,我们通过递归实现。
void freeTree(TreeNode* root) {
if (root != NULL) {
freeTree(root->left);
freeTree(root->right);
free(root);
}
}
7. 主函数
在主函数中,我们完成以下操作:
- 初始化根结点。
- 插入一系列结点。
- 打印二叉搜索树的中序遍历结果。
- 查找指定结点的层次并输出结果。
- 释放二叉树的内存。
int main() {
TreeNode* root = NULL;
// 插入元素
root = insert(root, 50);
root = insert(root, 30);
root = insert(root, 20);
root = insert(root, 40);
root = insert(root, 70);
root = insert(root, 60);
root = insert(root, 80);
printf("二叉搜索树的中序遍历结果:\n");
inorderTraversal(root);
printf("\n");
// 查找指定结点的层次
int key = 60;
int level = findLevel(root, key, 1);
if (level != -1) {
printf("结点 %d 在第 %d 层\n", key, level);
} else {
printf("结点 %d 未找到\n", key);
}
// 释放二叉树内存
freeTree(root);
return 0;
}
代码:
#include <stdio.h>
#include <stdlib.h>
// 定义二叉树结点
typedef struct TreeNode {
int val; // 结点值
struct TreeNode* left; // 左子树指针
struct TreeNode* right; // 右子树指针
} TreeNode;
// 创建新结点
TreeNode* createNode(int val) {
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode)); // 分配内存
newNode->val = val; // 设置结点值
newNode->left = NULL; // 初始化左子树为空
newNode->right = NULL; // 初始化右子树为空
return newNode; // 返回新结点
}
// 插入结点到二叉搜索树
TreeNode* insert(TreeNode* root, int val) {
if (root == NULL) { // 如果树为空
return createNode(val); // 创建并返回新结点
}
if (val < root->val) { // 如果插入值小于当前结点值
root->left = insert(root->left, val); // 插入到左子树
} else if (val > root->val) { // 如果插入值大于当前结点值
root->right = insert(root->right, val); // 插入到右子树
}
return root; // 返回根结点
}
// 查找结点在二叉搜索树中的层次
int findLevel(TreeNode* root, int key, int level) {
if (root == NULL) { // 如果树为空
return -1; // 结点不存在
}
if (root->val == key) { // 如果找到结点
return level; // 返回当前层次
}
int leftLevel = findLevel(root->left, key, level + 1); // 在左子树中查找
if (leftLevel != -1) { // 如果在左子树中找到结点
return leftLevel; // 返回左子树中的层次
}
return findLevel(root->right, key, level + 1); // 在右子树中查找
}
// 打印二叉树(中序遍历)
void inorderTraversal(TreeNode* root) {
if (root != NULL) { // 如果结点不为空
inorderTraversal(root->left); // 遍历左子树
printf("%d ", root->val); // 打印当前结点值
inorderTraversal(root->right); // 遍历右子树
}
}
// 释放二叉树内存
void freeTree(TreeNode* root) {
if (root != NULL) { // 如果结点不为空
freeTree(root->left); // 释放左子树
freeTree(root->right); // 释放右子树
free(root); // 释放当前结点
}
}
int main() {
TreeNode* root = NULL; // 初始化根结点为空
// 插入元素
root = insert(root, 50);
root = insert(root, 30);
root = insert(root, 20);
root = insert(root, 40);
root = insert(root, 70);
root = insert(root, 60);
root = insert(root, 80);
printf("二叉搜索树的中序遍历结果:\n");
inorderTraversal(root);
printf("\n");
// 查找指定结点的层次
int key = 60;
int level = findLevel(root, key, 1); // 从根结点开始,层次为1
if (level != -1) {
printf("结点 %d 在第 %d 层\n", key, level);
} else {
printf("结点 %d 未找到\n", key);
}
// 释放二叉树内存
freeTree(root);
return 0;
}
3.利用二分查找算法,编写一个在有序表中插入一个元素X,并保持表仍然有序的
思路:
-
二分查找函数
binarySearch
:- 使用二分查找算法在有序表中查找元素
x
。 - 如果找到元素
x
,返回该元素的索引。 - 如果没有找到元素
x
,返回插入位置的索引(即left
)。
- 使用二分查找算法在有序表中查找元素
-
插入元素函数
insertElement
:- 调用
binarySearch
函数找到插入位置insertPos
。 - 从插入位置开始,将后续元素依次后移一位,为新元素腾出空间。
- 将新元素插入到
insertPos
位置。 - 增加表的大小
*size
。
- 调用
-
主函数
main
:- 初始化一个有序表
arr
和当前表的大小size
。 - 打印初始有序表。
- 调用
insertElement
函数插入新元素。 - 打印插入新元素后的有序表。
- 初始化一个有序表
代码:
#include <stdio.h>
#include <stdlib.h>
// 二分查找算法,返回插入位置的索引
int binarySearch(int arr[], int left, int right, int x) {
while (left <= right) {
int mid = left + (right - left) / 2; // 计算中间位置
if (arr[mid] == x) {
return mid; // 如果找到了元素,返回该位置
} else if (arr[mid] < x) {
left = mid + 1; // 目标元素在右半部分
} else {
right = mid - 1; // 目标元素在左半部分
}
}
return left; // 如果没有找到元素,返回插入位置
}
// 插入元素到有序表中
void insertElement(int arr[], int *size, int x) {
int insertPos = binarySearch(arr, 0, *size - 1, x); // 找到插入位置
for (int i = *size; i > insertPos; i--) {
arr[i] = arr[i - 1]; // 从插入位置开始,将后续元素依次后移一位
}
arr[insertPos] = x; // 将新元素插入到插入位置
(*size)++; // 增加表的大小
}
int main() {
int arr[100] = {10, 20, 30, 40, 50, 60, 70, 80}; // 初始有序表
int size = 8; // 当前表的大小
printf("初始有序表: ");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]); // 打印初始有序表
}
printf("\n");
int x = 45; // 需要插入的元素
insertElement(arr, &size, x); // 插入新元素
printf("插入元素 %d 后的有序表: ", x);
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]); // 打印插入新元素后的有序表
}
printf("\n");
return 0;
}