数据结构习题
题目描述
有一个单链表(不同结点的数据域值可能相同),其头指针为head,编写一个函数计算数据域为x的结点个数。
运行代码
#include <stdio.h>#include <stdlib.h>// 定义链表节点结构体typedef struct ListNode {int data;struct ListNode *next;} ListNode;// 创建新节点的辅助函数ListNode* createNode(int val) {ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));newNode->data = val;newNode->next = NULL;return newNode;}// 计算数据域为 x 的结点个数int countOccurrences(ListNode* head, int x) {int count = 0;ListNode* current = head;while (current != NULL) {if (current->data == x) {count++;}current = current->next;}return count;}// 打印链表的辅助函数void printList(ListNode* head) {ListNode* current = head;while (current != NULL) {printf("%d ", current->data);current = current->next;}printf("\n");}// 释放链表内存的辅助函数void freeList(ListNode* head) {ListNode* current = head;while (current != NULL) {ListNode* next = current->next;free(current);current = next;}}int main() {// 创建一个单链表示例ListNode* head = createNode(1);head->next = createNode(2);head->next->next = createNode(3);head->next->next->next = createNode(2);head->next->next->next->next = createNode(5);head->next->next->next->next->next = createNode(2);int x = 2;int count = countOccurrences(head, x);// 输出结果printf("链表:");printList(head);printf("数据域为 %d 的结点个数: %d\n", x, count);// 释放链表内存freeList(head);return 0;}
代码思路
-
结构体
ListNode
:定义了一个链表节点结构体,包含数据成员data
和指针成员next
。 -
函数
createNode
:用于创建一个新的链表节点,并初始化其数据和指针。 -
函数
countOccurrences
:- 接受两个参数:链表的头节点
head
和要计数的数据x
。 - 初始化一个计数器
count
为 0。 - 遍历链表,如果当前节点的数据等于
x
,则计数器加 1。 - 返回计数器的值。
- 接受两个参数:链表的头节点
-
函数
printList
:用于打印链表的内容。 -
函数
freeList
:用于释放链表的内存,避免内存泄漏。 -
主函数
main
:- 创建一个单链表示例。
- 调用
countOccurrences
函数计算数据域为x
的结点个数。 - 输出链表的内容和计数结果。
- 释放链表内存,避免内存泄漏。
题目描述
有一个有序单链表(从小到大排序),表头指针为head,编写一个函数向该单链表中插入一个元素为x的结点,使插入后该链表仍然有序。
运行代码
#include <stdio.h>#include <stdlib.h>// 定义链表节点结构体typedef struct ListNode {int data;struct ListNode *next;} ListNode;// 创建新节点的辅助函数ListNode* createNode(int val) {ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));newNode->data = val;newNode->next = NULL;return newNode;}// 将元素 x 插入到有序链表中ListNode* insertSorted(ListNode* head, int x) {ListNode* newNode = createNode(x);if (head == NULL || x <= head->data) {newNode->next = head;return newNode;}ListNode* current = head;while (current->next != NULL && current->next->data < x) {current = current->next;}newNode->next = current->next;current->next = newNode;return head;}// 打印链表的辅助函数void printList(ListNode* head) {ListNode* current = head;while (current != NULL) {printf("%d ", current->data);current = current->next;}printf("\n");}// 释放链表内存的辅助函数void freeList(ListNode* head) {ListNode* current = head;while (current != NULL) {ListNode* next = current->next;free(current);current = next;}}int main() {// 创建一个有序单链表示例ListNode* head = createNode(1);head->next = createNode(3);head->next->next = createNode(4);head->next->next->next = createNode(7);int x = 5;head = insertSorted(head, x);// 输出链表printf("链表:");printList(head);// 释放链表内存freeList(head);return 0;}
代码思路
-
结构体
ListNode
:定义了一个链表节点结构体,包含数据成员data
和指针成员next
。 -
函数
createNode
:用于创建一个新的链表节点,并初始化其数据和指针。 -
函数
insertSorted
:- 接受两个参数:有序链表的头节点
head
和要插入的元素x
。 - 创建一个新节点
newNode
并初始化其数据为x
。 - 如果链表为空或
x
小于等于头节点的数据,则将新节点插入到链表头部。 - 否则,遍历链表,找到合适的位置插入新节点,确保链表仍然有序。
- 返回新的头节点。
- 接受两个参数:有序链表的头节点
-
函数
printList
:用于打印链表的内容。 -
函数
freeList
:用于释放链表的内存,避免内存泄漏。 -
主函数
main
:- 创建一个有序单链表示例。
- 调用
insertSorted
函数将元素x
插入到链表中。 - 输出链表的内容。
- 释放链表内存,避免内存泄漏。
题目描述
编写一个函数将一个头指针为a的单链表A分解成两个单链表A和B,其头指针分别为a和b,使得A链表中含有原链表A中序号为奇数的元素,而B链表中含有原链表A中序号为偶数的元素,且保持原来的相对顺序。
运行代码
#include <stdio.h>#include <stdlib.h>// 定义链表节点结构体typedef struct ListNode {int data;struct ListNode *next;} ListNode;// 创建新节点的辅助函数ListNode* createNode(int val) {ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));newNode->data = val;newNode->next = NULL;return newNode;}// 将一个链表分解成两个链表void splitList(ListNode* a, ListNode** b) {if (a == NULL) {*b = NULL;return;}ListNode* odd = a; // 奇数链表的头节点ListNode* even = a->next; // 偶数链表的头节点*b = even; // 将偶数链表的头节点赋值给 b// 遍历链表,将奇数和偶数节点分开while (even != NULL && even->next != NULL) {odd->next = even->next; // 连接奇数节点odd = odd->next;even->next = odd->next; // 连接偶数节点even = even->next;}odd->next = NULL; // 结束奇数链表}// 打印链表的辅助函数void printList(ListNode* head) {ListNode* current = head;while (current != NULL) {printf("%d ", current->data);current = current->next;}printf("\n");}// 释放链表内存的辅助函数void freeList(ListNode* head) {ListNode* current = head;while (current != NULL) {ListNode* next = current->next;free(current);current = next;}}int main() {// 创建一个单链表示例ListNode* a = createNode(1);a->next = createNode(2);a->next->next = createNode(3);a->next->next->next = createNode(4);a->next->next->next->next = createNode(5);ListNode* b = NULL;splitList(a, &b);// 输出 A 链表printf("A 链表:");printList(a);// 输出 B 链表printf("B 链表:");printList(b);// 释放链表内存freeList(a);freeList(b);return 0;}
代码思路
-
结构体
ListNode
:定义了一个链表节点结构体,包含数据成员data
和指针成员next
。 -
函数
createNode
:用于创建一个新的链表节点,并初始化其数据和指针。 -
函数
splitList
:- 接受两个参数:原始链表的头节点
a
和一个指向指针的指针b
,用于存储拆分后的偶数位置链表的头节点。 - 使用两个指针
odd
和even
分别指向奇数位置和偶数位置的节点。 - 通过遍历链表,将奇数位置和偶数位置的节点分别连接起来。
- 最后,将
odd
的next
指针设为NULL
,结束奇数链表。
- 接受两个参数:原始链表的头节点
-
函数
printList
:用于打印链表的内容。 -
函数
freeList
:用于释放链表的内存,避免内存泄漏。 -
主函数
main
:- 创建一个示例链表
a
。 - 调用
splitList
函数将链表a
拆分为两个链表a
和b
。 - 输出两个链表的内容。
- 释放链表内存,避免内存泄漏。
- 创建一个示例链表
题目描述
已知两个顺序表A和B分别表示两个集合,其元素递增排列,编写一个函数求出A和B的交集C,要求C同样以元素递增的顺序表形式存储。
运行代码
#include <stdio.h>#include <stdlib.h>// 函数原型声明int* intersect(int A[], int sizeA, int B[], int sizeB, int *returnSize);int main() {int A[] = {1, 2, 3, 4, 5};int B[] = {3, 4, 5, 6, 7};int sizeA = sizeof(A) / sizeof(A[0]);int sizeB = sizeof(B) / sizeof(B[0]);int returnSize;int *C = intersect(A, sizeA, B, sizeB, &returnSize);// 打印交集printf("Intersection: ");for (int i = 0; i < returnSize; i++) {printf("%d ", C[i]);}printf("\n");// 释放分配的内存free(C);return 0;}int* intersect(int A[], int sizeA, int B[], int sizeB, int *returnSize) {int *C = (int *)malloc((sizeA < sizeB ? sizeA : sizeB) * sizeof(int));int i = 0, j = 0, k = 0;while (i < sizeA && j < sizeB) {if (A[i] < B[j]) {i++;} else if (B[j] < A[i]) {j++;} else {if (k == 0 || C[k-1] != A[i]) { // 避免添加重复的元素C[k++] = A[i];}i++;j++;}}*returnSize = k;return C;}
代码思路
-
结构体
ListNode
:- 定义了一个链表节点结构体,包含数据成员
data
和指针成员next
。 - 构造函数用于初始化节点的数据和指针。
- 定义了一个链表节点结构体,包含数据成员
-
函数
splitList
:- 接受两个参数:原始链表的头节点
a
和一个引用参数b
,用于存储拆分后的偶数位置链表的头节点。 - 使用两个指针
odd
和even
分别指向奇数位置和偶数位置的节点。 - 通过遍历链表,将奇数位置和偶数位置的节点分别连接起来。
- 最后,将
odd
的next
指针设为nullptr
,并更新b
为evenHead
。
- 接受两个参数:原始链表的头节点
-
主函数
main
:- 创建一个示例链表
a
。 - 调用
splitList
函数将链表a
拆分为两个链表a
和b
。 - 输出两个链表的内容。
- 释放链表内存,避免内存泄漏。
- 创建一个示例链表