链表
两个链表合并成为一个
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构
typedef struct Node {
int data; // 节点数据
struct Node* next; // 指向下一个节点
} Node;
// 创建新节点
Node* createNode(int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
// 在链表末尾插入节点
void insertEnd(Node** head, int data) {
Node* newNode = createNode(data);
if (*head == NULL) {
*head = newNode; // 如果链表为空,新节点为头节点
} else {
Node* temp = *head;
while (temp->next != NULL) {
temp = temp->next; // 找到链表的最后一个节点
}
temp->next = newNode; // 将新节点插入到末尾
}
}
// 检查链表中是否包含某个值
int contains(Node* head, int data) {
Node* temp = head;
while (temp != NULL) {
if (temp->data == data) {
return 1; // 找到重复值
}
temp = temp->next;
}
return 0; // 未找到重复值
}
// 合并两个链表,去重
Node* mergeLists(Node* list1, Node* list2) {
Node* mergedList = NULL; // 合并后的链表
// 将第一个链表的节点加入合并链表
Node* temp = list1;
while (temp != NULL) {
if (!contains(mergedList, temp->data)) {
insertEnd(&mergedList, temp->data); // 如果不重复,加入合并链表
}
temp = temp->next;
}
// 将第二个链表的节点加入合并链表
temp = list2;
while (temp != NULL) {
if (!contains(mergedList, temp->data)) {
insertEnd(&mergedList, temp->data); // 如果不重复,加入合并链表
}
temp = temp->next;
}
return mergedList;
}
// 打印链表
void printList(Node* head) {
Node* temp = head;
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
// 释放链表内存
void freeList(Node* head) {
Node* temp;
while (head != NULL) {
temp = head;
head = head->next;
free(temp);
}
}
int main() {
Node* list1 = NULL; // 第一个链表
Node* list2 = NULL; // 第二个链表
int n, value;
// 输入第一个链表
printf("请输入第一个链表的节点个数:");
scanf("%d", &n);
for (int i = 0; i < n; i++) {
printf("请输入第一个链表的第 %d 个节点的值:", i + 1);
scanf("%d", &value);
insertEnd(&list1, value); // 将节点插入链表末尾
}
// 输入第二个链表
printf("请输入第二个链表的节点个数:");
scanf("%d", &n);
for (int i = 0; i < n; i++) {
printf("请输入第二个链表的第 %d 个节点的值:", i + 1);
scanf("%d", &value);
insertEnd(&list2, value); // 将节点插入链表末尾
}
// 打印原始链表
printf("\n第一个链表:");
printList(list1);
printf("第二个链表:");
printList(list2);
// 合并链表
Node* mergedList = mergeLists(list1, list2);
printf("合并后的链表(去重):");
printList(mergedList);
// 释放链表内存
freeList(list1);
freeList(list2);
freeList(mergedList);
return 0;
}
删除指定值的结点
#include <stdio.h>
#include <stdlib.h>
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
//初始化链表
LinkList initList(){
LinkList L = (LinkList)malloc(sizeof(LNode));
//头节点的数据域存放链表的长度
L->data = 0;
L->next = NULL;
return L;
}
//尾插
LinkList tailInsert(LinkList L){
LNode *r = L;
int data;
//以输入-1作为结束标志
while(scanf("%d",&data)==1 && data!=-1){
LNode *newNode = (LNode*)malloc(sizeof(LNode));
newNode->data = data;
newNode->next = NULL;
r->next = newNode;
r = newNode;
L->data+=1;
}
return L;
}
//删除值为x的节点
LinkList deleteNode(LinkList L,int x){
LNode *p = L,*r = p->next;
while(r){
if(r->data == x){
p->next = r->next;
free(r);
r = p->next;
}else{
p = r;
r = r->next;
}
}
return L;
}
//打印
void printList(LinkList L){
LNode *p = L->next;
while(p){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int main()
{
int x;
LinkList L = initList();
printf("输入链表:");
L = tailInsert(L);
printList(L);
printf("输入需要删除的值:");
scanf("%d",&x);
L = deleteNode(L,x);
printList(L);
return 0;
}
删除最小的值
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构
typedef struct Node {
int data; // 节点数据
struct Node* next; // 指向下一个节点
} Node;
// 创建新节点
Node* createNode(int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
// 在链表末尾插入节点
void insertEnd(Node** head, int data) {
Node* newNode = createNode(data);
if (*head == NULL) {
*head = newNode; // 如果链表为空,新节点为头节点
} else {
Node* temp = *head;
while (temp->next != NULL) {
temp = temp->next; // 找到链表的最后一个节点
}
temp->next = newNode; // 将新节点插入到末尾
}
}
// 在链表中删除最小值节点
void deleteMinNode(Node** head) {
if (*head == NULL) {
printf("链表为空,无法删除最小值节点\n");
return;
}
Node* prevMin = NULL; // 最小值节点的前驱节点
Node* minNode = *head; // 最小值节点
Node* prev = NULL; // 当前节点的前驱节点
Node* curr = *head; // 当前节点
// 遍历链表,找到最小值节点及其前驱节点
while (curr != NULL) {
if (curr->data < minNode->data) {
minNode = curr;
prevMin = prev;
}
prev = curr;
curr = curr->next;
}
// 删除最小值节点
if (prevMin == NULL) {
// 最小值节点是头节点
*head = minNode->next;
} else {
// 最小值节点不是头节点
prevMin->next = minNode->next;
}
// 释放最小值节点的内存
free(minNode);
printf("最小值节点已删除\n");
}
// 打印链表
void printList(Node* head) {
Node* temp = head;
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
int main() {
Node* head = NULL; // 初始化链表为空
int n, value;
// 输入链表节点个数
printf("请输入链表的节点个数:");
scanf("%d", &n);
// 输入链表节点值
for (int i = 0; i < n; i++) {
printf("请输入第 %d 个节点的值:", i + 1);
scanf("%d", &value);
insertEnd(&head, value); // 将节点插入链表末尾
}
// 打印原始链表
printf("原始链表:");
printList(head);
// 删除最小值节点
deleteMinNode(&head);
printf("删除最小值节点后:");
printList(head);
return 0;
}
找两个链表的地址相同
#include <stdio.h>
#include <stdlib.h>
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
//初始化链表
LinkList initList(){
LinkList L = (LinkList)malloc(sizeof(LNode));
//头节点的数据域存放链表的长度
L->data = 0;
L->next = NULL;
return L;
}
//尾插
LinkList tailInsert(LinkList L){
LNode *r = L;
int data;
//以输入-1作为结束标志
while(scanf("%d",&data)==1 && data!=-1){
LNode *newNode = (LNode*)malloc(sizeof(LNode));
newNode->data = data;
newNode->next = NULL;
r->next = newNode;
r = newNode;
L->data+=1;
}
return L;
}
//注意这里是找公共结点(即结点地址相同)而不是值相同的结点
LinkList mergeList(LinkList La,LinkList Lb){
int len_La = La->data,len_Lb = Lb->data;
LNode *p = La->next,*q = Lb->next;
//较长的先遍历
if(len_La > len_Lb){
int step= len_La-len_Lb;
while(step != 0){
p = p->next;
step --;
}
}else if(len_La < len_Lb){
int step= len_Lb-len_La;
while(step != 0){
q = q->next;
step --;
}
}
while(p&&q){
if(p==q){
return p;
}else{
p = p->next;
q = q->next;
}
}
return NULL;
}
//打印
void printList(LinkList L){
LNode *p = L->next;
while(p){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int main()
{
LinkList L = initList();
L = tailInsert(L);
printList(L);
//测试寻找公共点
//L->next作为公共结点
//而front1作为La的独有序列,front2作为Lb的独有序列
LinkList front1 = initList();
front1 = tailInsert(front1);
LinkList front2 = initList();
front2 = tailInsert(front2);
//序列拼接
LNode *r = front1;
while(r->next) r = r->next;
r->next = L->next;
r = front2;
while(r->next) r = r->next;
r->next = L->next;
L->next = NULL;
free(L);
LNode *sameNode = mergeList(front1,front2);
while(sameNode){
printf("%d ",sameNode->data);
sameNode = sameNode->next;
}
printf("\n");
return 0;
}
树和二叉树
判断是否是满二叉树或者完全二叉树
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
// 定义二叉树节点结构
typedef struct TreeNode {
char data; // 节点数据
struct TreeNode *left; // 左子树
struct TreeNode *right; // 右子树
} TreeNode;
// 创建新节点
TreeNode* createNode(char data) {
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// 根据先序和中序遍历重建二叉树
TreeNode* buildTree(char preorder[], char inorder[], int preStart, int preEnd, int inStart, int inEnd) {
if (preStart > preEnd || inStart > inEnd) {
return NULL; // 递归终止条件
}
// 先序遍历的第一个节点是根节点
char rootValue = preorder[preStart];
TreeNode* root = createNode(rootValue);
// 在中序遍历中找到根节点的位置
int rootIndex;
for (rootIndex = inStart; rootIndex <= inEnd; rootIndex++) {
if (inorder[rootIndex] == rootValue) {
break;
}
}
// 计算左子树的大小
int leftSize = rootIndex - inStart;
// 递归构建左子树和右子树
root->left = buildTree(preorder, inorder, preStart + 1, preStart + leftSize, inStart, rootIndex - 1);
root->right = buildTree(preorder, inorder, preStart + leftSize + 1, preEnd, rootIndex + 1, inEnd);
return root;
}
// 计算二叉树的高度
int calculateHeight(TreeNode* root) {
if (root == NULL) {
return 0; // 空树的高度为0
}
int leftHeight = calculateHeight(root->left);
int rightHeight = calculateHeight(root->right);
return (leftHeight > rightHeight) ? leftHeight + 1 : rightHeight + 1;
}
// 判断是否是满二叉树
bool isFullTree(TreeNode* root) {
if (root == NULL) {
return true; // 空树是满二叉树
}
if (root->left == NULL && root->right == NULL) {
return true; // 叶子节点
}
if (root->left != NULL && root->right != NULL) {
return isFullTree(root->left) && isFullTree(root->right); // 递归检查左右子树
}
return false; // 只有一个子节点
}
// 判断是否是完全二叉树
bool isCompleteTree(TreeNode* root) {
if (root == NULL) {
return true; // 空树是完全二叉树
}
// 使用队列进行层次遍历
TreeNode* queue[1000];
int front = 0, rear = 0;
queue[rear++] = root;
bool mustBeLeaf = false; // 标记是否必须为叶子节点
while (front < rear) {
TreeNode* node = queue[front++];
// 如果当前节点必须为叶子节点,但它有子节点,则不是完全二叉树
if (mustBeLeaf && (node->left != NULL || node->right != NULL)) {
return false;
}
// 如果左子节点为空但右子节点不为空,则不是完全二叉树
if (node->left == NULL && node->right != NULL) {
return false;
}
// 如果左子节点不为空,加入队列
if (node->left != NULL) {
queue[rear++] = node->left;
} else {
mustBeLeaf = true; // 左子节点为空,后续节点必须为叶子节点
}
// 如果右子节点不为空,加入队列
if (node->right != NULL) {
queue[rear++] = node->right;
} else {
mustBeLeaf = true; // 右子节点为空,后续节点必须为叶子节点
}
}
return true;
}
int main() {
char preorder[100], inorder[100];
// 输入先序遍历
printf("请输入二叉树的先序遍历:");
scanf("%s", preorder);
// 输入中序遍历
printf("请输入二叉树的中序遍历:");
scanf("%s", inorder);
// 检查输入长度是否一致
int preLen = strlen(preorder);
int inLen = strlen(inorder);
if (preLen != inLen) {
printf("输入的先序和中序遍历长度不一致,无法构建二叉树!\n");
return 1;
}
// 重建二叉树
TreeNode* root = buildTree(preorder, inorder, 0, preLen - 1, 0, inLen - 1);
// 判断是否是满二叉树
if (isFullTree(root)) {
printf("该二叉树是满二叉树。\n");
} else {
printf("该二叉树不是满二叉树。\n");
}
// 判断是否是完全二叉树
if (isCompleteTree(root)) {
printf("该二叉树是完全二叉树。\n");
} else {
printf("该二叉树不是完全二叉树。\n");
}
return 0;
}
求高度
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义二叉树节点结构
typedef struct TreeNode {
char data; // 节点数据
struct TreeNode *left; // 左子树
struct TreeNode *right; // 右子树
} TreeNode;
// 创建新节点
TreeNode* createNode(char data) {
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// 根据先序和中序遍历重建二叉树
TreeNode* buildTree(char preorder[], char inorder[], int preStart, int preEnd, int inStart, int inEnd) {
if (preStart > preEnd || inStart > inEnd) {
return NULL; // 递归终止条件
}
// 先序遍历的第一个节点是根节点
char rootValue = preorder[preStart];
TreeNode* root = createNode(rootValue);
// 在中序遍历中找到根节点的位置
int rootIndex;
for (rootIndex = inStart; rootIndex <= inEnd; rootIndex++) {
if (inorder[rootIndex] == rootValue) {
break;
}
}
// 计算左子树的大小
int leftSize = rootIndex - inStart;
// 递归构建左子树和右子树
root->left = buildTree(preorder, inorder, preStart + 1, preStart + leftSize, inStart, rootIndex - 1);
root->right = buildTree(preorder, inorder, preStart + leftSize + 1, preEnd, rootIndex + 1, inEnd);
return root;
}
// 计算二叉树的高度
int calculateHeight(TreeNode* root) {
if (root == NULL) {
return 0; // 空树的高度为0
}
// 递归计算左子树和右子树的高度
int leftHeight = calculateHeight(root->left);
int rightHeight = calculateHeight(root->right);
// 返回较大的子树高度加1(当前节点)
return (leftHeight > rightHeight) ? leftHeight + 1 : rightHeight + 1;
}
int main() {
char preorder[100], inorder[100];
// 输入先序遍历
printf("请输入二叉树的先序遍历:");
scanf("%s", preorder);
// 输入中序遍历
printf("请输入二叉树的中序遍历:");
scanf("%s", inorder);
// 检查输入长度是否一致
int preLen = strlen(preorder);
int inLen = strlen(inorder);
if (preLen != inLen) {
printf("输入的先序和中序遍历长度不一致,无法构建二叉树!\n");
return 1;
}
// 重建二叉树
TreeNode* root = buildTree(preorder, inorder, 0, preLen - 1, 0, inLen - 1);
// 计算二叉树的高度
int height = calculateHeight(root);
printf("二叉树的高度为:%d\n", height);
return 0;
}
输出后续遍历和层次遍历
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义二叉树节点结构
typedef struct TreeNode {
char data; // 节点数据
struct TreeNode *left; // 左子树
struct TreeNode *right; // 右子树
} TreeNode;
// 创建新节点
TreeNode* createNode(char data) {
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// 根据先序和中序遍历重建二叉树
TreeNode* buildTree(char preorder[], char inorder[], int preStart, int preEnd, int inStart, int inEnd) {
if (preStart > preEnd || inStart > inEnd) {
return NULL; // 递归终止条件
}
// 先序遍历的第一个节点是根节点
char rootValue = preorder[preStart];
TreeNode* root = createNode(rootValue);
// 在中序遍历中找到根节点的位置
int rootIndex;
for (rootIndex = inStart; rootIndex <= inEnd; rootIndex++) {
if (inorder[rootIndex] == rootValue) {
break;
}
}
// 计算左子树的大小
int leftSize = rootIndex - inStart;
// 递归构建左子树和右子树
root->left = buildTree(preorder, inorder, preStart + 1, preStart + leftSize, inStart, rootIndex - 1);
root->right = buildTree(preorder, inorder, preStart + leftSize + 1, preEnd, rootIndex + 1, inEnd);
return root;
}
// 后序遍历
void postorderTraversal(TreeNode* root) {
if (root == NULL) {
return;
}
postorderTraversal(root->left);
postorderTraversal(root->right);
printf("%c ", root->data);
}
// 层次遍历
void levelOrderTraversal(TreeNode* root) {
if (root == NULL) {
return;
}
// 使用队列实现层次遍历
TreeNode* queue[1000];
int front = 0, rear = 0;
queue[rear++] = root; // 根节点入队
while (front < rear) {
TreeNode* node = queue[front++]; // 出队
printf("%c ", node->data);
// 左子节点入队
if (node->left != NULL) {
queue[rear++] = node->left;
}
// 右子节点入队
if (node->right != NULL) {
queue[rear++] = node->right;
}
}
}
int main() {
char preorder[100], inorder[100];
// 输入先序遍历
printf("请输入二叉树的先序遍历:");
scanf("%s", preorder);
// 输入中序遍历
printf("请输入二叉树的中序遍历:");
scanf("%s", inorder);
// 检查输入长度是否一致
int preLen = strlen(preorder);
int inLen = strlen(inorder);
if (preLen != inLen) {
printf("输入的先序和中序遍历长度不一致,无法构建二叉树!\n");
return 1;
}
// 重建二叉树
TreeNode* root = buildTree(preorder, inorder, 0, preLen - 1, 0, inLen - 1);
// 输出后序遍历
printf("后序遍历:");
postorderTraversal(root);
printf("\n");
// 输出层次遍历
printf("层次遍历:");
levelOrderTraversal(root);
printf("\n");
return 0;
}
统计叶子结点个数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义二叉树节点结构
typedef struct TreeNode {
char data; // 节点数据
struct TreeNode *left; // 左子树
struct TreeNode *right; // 右子树
} TreeNode;
// 创建新节点
TreeNode* createNode(char data) {
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// 根据先序和中序遍历重建二叉树
TreeNode* buildTree(char preorder[], char inorder[], int preStart, int preEnd, int inStart, int inEnd) {
if (preStart > preEnd || inStart > inEnd) {
return NULL; // 递归终止条件
}
// 先序遍历的第一个节点是根节点
char rootValue = preorder[preStart];
TreeNode* root = createNode(rootValue);
// 在中序遍历中找到根节点的位置
int rootIndex;
for (rootIndex = inStart; rootIndex <= inEnd; rootIndex++) {
if (inorder[rootIndex] == rootValue) {
break;
}
}
// 计算左子树的大小
int leftSize = rootIndex - inStart;
// 递归构建左子树和右子树
root->left = buildTree(preorder, inorder, preStart + 1, preStart + leftSize, inStart, rootIndex - 1);
root->right = buildTree(preorder, inorder, preStart + leftSize + 1, preEnd, rootIndex + 1, inEnd);
return root;
}
// 统计叶子节点数
int countLeafNodes(TreeNode* root) {
if (root == NULL) {
return 0; // 空树没有叶子节点
}
if (root->left == NULL && root->right == NULL) {
return 1; // 当前节点是叶子节点
}
// 递归统计左子树和右子树的叶子节点数
return countLeafNodes(root->left) + countLeafNodes(root->right);
}
int main() {
char preorder[100], inorder[100];
// 输入先序遍历
printf("请输入二叉树的先序遍历:");
scanf("%s", preorder);
// 输入中序遍历
printf("请输入二叉树的中序遍历:");
scanf("%s", inorder);
// 检查输入长度是否一致
int preLen = strlen(preorder);
int inLen = strlen(inorder);
if (preLen != inLen) {
printf("输入的先序和中序遍历长度不一致,无法构建二叉树!\n");
return 1;
}
// 重建二叉树
TreeNode* root = buildTree(preorder, inorder, 0, preLen - 1, 0, inLen - 1);
// 统计叶子节点数
int leafCount = countLeafNodes(root);
printf("二叉树的叶子节点数为:%d\n", leafCount);
return 0;
}
栈和队列
10进制转8进制
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100 // 定义栈的最大容量
// 定义栈结构
typedef struct {
int data[MAX_SIZE]; // 存储栈元素的数组
int top; // 栈顶指针
} Stack;
// 初始化栈
void initStack(Stack *s) {
s->top = -1; // 栈顶指针初始化为-1,表示空栈
}
// 判断栈是否为空
int isEmpty(Stack *s) {
return s->top == -1;
}
// 判断栈是否已满
int isFull(Stack *s) {
return s->top == MAX_SIZE - 1;
}
// 入栈操作
void push(Stack *s, int value) {
if (isFull(s)) {
printf("栈已满,无法入栈!\n");
return;
}
s->data[++(s->top)] = value; // 栈顶指针加1,存入数据
}
// 出栈操作
int pop(Stack *s) {
if (isEmpty(s)) {
printf("栈为空,无法出栈!\n");
return -1; // 返回-1表示栈为空
}
return s->data[(s->top)--]; // 取出栈顶元素,栈顶指针减1
}
// 将十进制数转换为任意进制
void decimalToBase(int decimal, int base) {
Stack s;
initStack(&s); // 初始化栈
// 处理0的特殊情况
if (decimal == 0) {
printf("转换结果为:0\n");
return;
}
// 除base取余,将余数压入栈中
while (decimal > 0) {
push(&s, decimal % base); // 将余数压入栈
decimal /= base; // 更新十进制数
}
// 出栈得到转换结果
printf("转换结果为:");
while (!isEmpty(&s)) {
int remainder = pop(&s); // 取出栈顶元素
if (remainder < 10) {
printf("%d", remainder); // 直接输出数字
} else {
printf("%c", 'A' + (remainder - 10)); // 转换为字母(A-F)
}
}
printf("\n");
}
int main() {
int decimal, base;
// 输入十进制数和目标进制
printf("请输入一个十进制数:");
scanf("%d", &decimal);
printf("请输入目标进制(2-16):");
scanf("%d", &base);
// 检查进制范围是否合法
if (base < 2 || base > 16) {
printf("进制不合法,请输入2到16之间的整数!\n");
return 1;
}
// 转换为目标进制并输出
decimalToBase(decimal, base);
return 0;
}
队列1
#include <stdio.h>
#include <stdlib.h>
//队列的应用:设有n个人站成一排,从左向右有1-n,报数1,2,1,2 1的出列 2的立即到最右边 直到n个都出列 求他们的出列顺序
#define MAX_SIZE 1000 // 定义队列的最大容量
// 定义队列结构
typedef struct {
int data[MAX_SIZE]; // 存储队列元素的数组
int front; // 队头指针
int rear; // 队尾指针
} Queue;
// 初始化队列
void initQueue(Queue *q) {
q->front = -1;
q->rear = -1;
}
// 判断队列是否为空
int isEmpty(Queue *q) {
return q->front == -1 && q->rear == -1;
}
// 判断队列是否已满
int isFull(Queue *q) {
return q->rear == MAX_SIZE - 1;
}
// 入队操作
void enqueue(Queue *q, int value) {
if (isFull(q)) {
printf("队列已满,无法入队!\n");
return;
}
if (isEmpty(q)) {
q->front = 0; // 如果队列为空,初始化队头指针
}
q->data[++(q->rear)] = value; // 队尾指针加1,存入数据
}
// 出队操作
int dequeue(Queue *q) {
if (isEmpty(q)) {
printf("队列为空,无法出队!\n");
return -1; // 返回-1表示队列为空
}
int value = q->data[q->front]; // 取出队头元素
if (q->front == q->rear) {
// 如果队列中只有一个元素,出队后重置队列
q->front = -1;
q->rear = -1;
} else {
q->front++; // 队头指针加1
}
return value;
}
// 模拟报数过程并输出出列顺序
void simulateQueue(int n) {
Queue q;
initQueue(&q); // 初始化队列
// 将1到n的人加入队列
for (int i = 1; i <= n; i++) {
enqueue(&q, i);
}
int count = 0; // 报数计数器
printf("出列顺序:");
while (!isEmpty(&q)) {
int person = dequeue(&q); // 出队一个人
count++; // 报数
if (count == 1) {
printf("%d ", person); // 报1的人出列
} else if (count == 2) {
enqueue(&q, person); // 报2的人移动到队尾
count = 0; // 重置报数计数器
}
}
printf("\n");
}
int main() {
int n;
// 输入人数
printf("请输入人数n:");
scanf("%d", &n);
// 模拟报数过程并输出出列顺序
simulateQueue(n);
return 0;
}
括号匹配
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_SIZE 100 // 定义栈的最大容量
// 定义栈结构
typedef struct {
char data[MAX_SIZE]; // 存储栈元素的数组
int top; // 栈顶指针
} Stack;
// 初始化栈
void initStack(Stack *s) {
s->top = -1; // 栈顶指针初始化为-1,表示空栈
}
// 判断栈是否为空
bool isEmpty(Stack *s) {
return s->top == -1;
}
// 判断栈是否已满
bool isFull(Stack *s) {
return s->top == MAX_SIZE - 1;
}
// 入栈操作
void push(Stack *s, char value) {
if (isFull(s)) {
printf("栈已满,无法入栈!\n");
return;
}
s->data[++(s->top)] = value; // 栈顶指针加1,存入数据
}
// 出栈操作
char pop(Stack *s) {
if (isEmpty(s)) {
printf("栈为空,无法出栈!\n");
return '\0'; // 返回空字符表示栈为空
}
return s->data[(s->top)--]; // 取出栈顶元素,栈顶指针减1
}
// 获取栈顶元素
char peek(Stack *s) {
if (isEmpty(s)) {
return '\0'; // 返回空字符表示栈为空
}
return s->data[s->top]; // 返回栈顶元素
}
// 判断括号是否匹配
bool isMatchingPair(char left, char right) {
return (left == '(' && right == ')') ||
(left == '[' && right == ']') ||
(left == '{' && right == '}');
}
// 检查表达式中的括号是否匹配
bool areParenthesesBalanced(char *expression) {
Stack s;
initStack(&s); // 初始化栈
// 遍历表达式
for (int i = 0; expression[i] != '\0'; i++) {
char ch = expression[i];
// 如果是左括号,压入栈中
if (ch == '(' || ch == '[' || ch == '{') {
push(&s, ch);
}
// 如果是右括号,检查是否匹配
else if (ch == ')' || ch == ']' || ch == '}') {
if (isEmpty(&s)){
return false; // 栈为空,没有匹配的左括号
}
char topChar = pop(&s); // 弹出栈顶元素
if (!isMatchingPair(topChar, ch)) {
return false; // 括号不匹配
}
}
}
// 如果栈为空,说明所有括号都匹配
return isEmpty(&s);
}
int main() {
char expression[MAX_SIZE];
// 输入表达式
printf("请输入一个包含括号的表达式:");
fgets(expression, MAX_SIZE, stdin);
// 检查括号是否匹配
if (areParenthesesBalanced(expression)) {
printf("括号匹配!\n");
} else {
printf("括号不匹配!\n");
}
return 0;
}
入栈和出栈 求最大值和最小值
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MAX_SIZE 100 // 定义栈的最大容量
// 定义栈结构
typedef struct {
int data[MAX_SIZE]; // 存储栈元素的数组
int top; // 栈顶指针
int maxStack[MAX_SIZE]; // 辅助栈,记录最大值
int minStack[MAX_SIZE]; // 辅助栈,记录最小值
} Stack;
// 初始化栈
void initStack(Stack *s) {
s->top = -1; // 栈顶指针初始化为-1,表示空栈
}
// 判断栈是否为空
int isEmpty(Stack *s) {
return s->top == -1;
}
// 判断栈是否已满
int isFull(Stack *s) {
return s->top == MAX_SIZE - 1;
}
// 入栈操作
void push(Stack *s, int value) {
if (isFull(s)) {
printf("栈已满,无法入栈!\n");
return;
}
// 入栈
s->data[++(s->top)] = value;
// 更新最大值栈
if (s->top == 0 || value > s->maxStack[s->top - 1]) {
s->maxStack[s->top] = value;
} else {
s->maxStack[s->top] = s->maxStack[s->top - 1];
}
// 更新最小值栈
if (s->top == 0 || value < s->minStack[s->top - 1]) {
s->minStack[s->top] = value;
} else {
s->minStack[s->top] = s->minStack[s->top - 1];
}
printf("入栈成功:%d\n", value);
}
// 出栈操作
int pop(Stack *s) {
if (isEmpty(s)) {
printf("栈为空,无法出栈!\n");
return INT_MIN; // 返回最小值表示栈为空
}
int value = s->data[(s->top)--]; // 出栈
printf("出栈成功:%d\n", value);
return value;
}
// 获取当前栈中的最大值
int getMax(Stack *s) {
if (isEmpty(s)) {
printf("栈为空,无最大值!\n");
return INT_MIN;
}
return s->maxStack[s->top];
}
// 获取当前栈中的最小值
int getMin(Stack *s) {
if (isEmpty(s)) {
printf("栈为空,无最小值!\n");
return INT_MAX;
}
return s->minStack[s->top];
}
// 打印栈内容
void printStack(Stack *s) {
if (isEmpty(s)) {
printf("栈为空!\n");
return;
}
printf("当前栈内容:");
for (int i = 0; i <= s->top; i++) {
printf("%d ", s->data[i]);
}
printf("\n");
}
int main() {
Stack s;
initStack(&s); // 初始化栈
int choice, value;
while (1) {
printf("\n请选择操作:\n");
printf("1. 入栈\n");
printf("2. 出栈\n");
printf("3. 获取最大值\n");
printf("4. 获取最小值\n");
printf("5. 打印栈内容\n");
printf("6. 退出\n");
printf("请输入选项:");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("请输入要入栈的值:");
scanf("%d", &value);
push(&s, value);
break;
case 2:
value = pop(&s);
if (value != INT_MIN) {
printf("出栈的值:%d\n", value);
}
break;
case 3:
printf("当前栈中的最大值:%d\n", getMax(&s));
break;
case 4:
printf("当前栈中的最小值:%d\n", getMin(&s));
break;
case 5:
printStack(&s);
break;
case 6:
printf("程序退出。\n");
exit(0);
default:
printf("无效选项,请重新选择!\n");
}
}
return 0;
}
循环队列1
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_SIZE 5 // 定义循环队列的最大容量
// 定义循环队列结构
typedef struct {
int data[MAX_SIZE]; // 存储队列元素的数组
int front; // 队头指针
int rear; // 队尾指针
} CircularQueue;
// 初始化循环队列
void initQueue(CircularQueue *q) {
q->front = -1;
q->rear = -1;
}
// 判断循环队列是否为空
bool isEmpty(CircularQueue *q) {
return q->front == -1 && q->rear == -1;
}
// 判断循环队列是否已满
bool isFull(CircularQueue *q) {
return (q->rear + 1) % MAX_SIZE == q->front;
}
// 入队操作
void enqueue(CircularQueue *q, int value) {
if (isFull(q)) {
printf("队列已满,无法入队!\n");
return;
}
if (isEmpty(q)) {
q->front = 0; // 如果队列为空,初始化队头指针
}
q->rear = (q->rear + 1) % MAX_SIZE; // 队尾指针循环移动
q->data[q->rear] = value; // 存入数据
printf("入队成功:%d\n", value);
}
// 出队操作
int dequeue(CircularQueue *q) {
if (isEmpty(q)) {
printf("队列为空,无法出队!\n");
return -1; // 返回-1表示队列为空
}
int value = q->data[q->front]; // 取出队头元素
if (q->front == q->rear) {
// 如果队列中只有一个元素,出队后重置队列
q->front = -1;
q->rear = -1;
} else {
q->front = (q->front + 1) % MAX_SIZE; // 队头指针循环移动
}
printf("出队成功:%d\n", value);
return value;
}
// 打印队列内容
void printQueue(CircularQueue *q) {
if (isEmpty(q)) {
printf("队列为空!\n");
return;
}
printf("当前队列内容:");
int i = q->front;
while (i != q->rear) {
printf("%d ", q->data[i]);
i = (i + 1) % MAX_SIZE;
}
printf("%d\n", q->data[i]); // 打印最后一个元素
}
int main() {
CircularQueue q;
initQueue(&q); // 初始化循环队列
int choice, value;
while (1) {
printf("\n请选择操作:\n");
printf("1. 入队\n");
printf("2. 出队\n");
printf("3. 打印队列内容\n");
printf("4. 退出\n");
printf("请输入选项:");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("请输入要入队的值:");
scanf("%d", &value);
enqueue(&q, value);
break;
case 2:
value = dequeue(&q);
if (value != -1) {
printf("出队的值:%d\n", value);
}
break;
case 3:
printQueue(&q);
break;
case 4:
printf("程序退出。\n");
exit(0);
default:
printf("无效选项,请重新选择!\n");
}
}
return 0;
}
循环队列2
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h> // 添加 strtok 函数的头文件
#define MAX_SIZE 1000 // 定义队列的最大容量
// 定义队列结构
typedef struct {
int data[MAX_SIZE]; // 存储队列元素的数组
int front; // 队头指针
int rear; // 队尾指针
} Queue;
// 初始化队列
void initQueue(Queue *q) {
q->front = -1;
q->rear = -1;
}
// 判断队列是否为空
bool isEmpty(Queue *q) {
return q->front == -1 && q->rear == -1;
}
// 判断队列是否已满
bool isFull(Queue *q) {
return q->rear == MAX_SIZE - 1;
}
// 入队操作
void enqueue(Queue *q, int value) {
if (isFull(q)) {
printf("队列已满,无法入队!\n");
return;
}
if (isEmpty(q)) {
q->front = 0; // 如果队列为空,初始化队头指针
}
q->data[++(q->rear)] = value; // 队尾指针加1,存入数据
printf("入队:%d\n", value);
}
// 出队操作
int dequeue(Queue *q) {
if (isEmpty(q)) {
printf("队列为空,无法出队!\n");
return -1; // 返回-1表示队列为空
}
int value = q->data[q->front]; // 取出队头元素
if (q->front == q->rear) {
// 如果队列中只有一个元素,出队后重置队列
q->front = -1;
q->rear = -1;
} else {
q->front++; // 队头指针加1
}
printf("出队:%d\n", value);
return value;
}
int main() {
Queue q;
initQueue(&q); // 初始化队列
char input[MAX_SIZE];
printf("请输入一串数字(以空格分隔,回车结束):");
fgets(input, MAX_SIZE, stdin); // 读取用户输入
// 解析输入的数字并入队
char *token = strtok(input, " "); // 使用空格分隔输入
while (token != NULL) {
int value = atoi(token); // 将字符串转换为整数
enqueue(&q, value); // 入队
token = strtok(NULL, " ");
}
// 依次出队并输出
printf("\n出队顺序:\n");
while (!isEmpty(&q)) {
dequeue(&q);
}
return 0;
}
查找和排序
二叉排序树不小于k的算法
#include <stdio.h>
#include <stdlib.h>
// 定义二叉树节点结构
typedef struct TreeNode {
int key; // 节点值
struct TreeNode* left; // 左子树
struct TreeNode* right; // 右子树
} TreeNode;
// 创建新节点
TreeNode* createNode(int key) {
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
newNode->key = key;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// 插入节点到二叉排序树
TreeNode* insert(TreeNode* root, int key) {
if (root == NULL) {
return createNode(key);
}
if (key < root->key) {
root->left = insert(root->left, key);
} else if (key > root->key) {
root->right = insert(root->right, key);
}
return root;
}
// 逆中序遍历并输出不小于 k 的关键字
void reverseInorder(TreeNode* root, int k) {
if (root == NULL) {
return;
}
// 先遍历右子树
reverseInorder(root->right, k);
// 如果当前节点的值小于 k,停止遍历
if (root->key < k) {
return;
}
// 输出当前节点的值
printf("%d ", root->key);
// 再遍历左子树
reverseInorder(root->left, k);
}
int main() {
TreeNode* root = NULL;
// 插入节点构建二叉排序树
root = insert(root, 50);
root = insert(root, 30);
root = insert(root, 70);
root = insert(root, 20);
root = insert(root, 40);
root = insert(root, 60);
root = insert(root, 80);
root = insert(root, 100);
// 输入 k
int k;
printf("请输入 k 的值:");
scanf("%d", &k);
// 输出不小于 k 的关键字
printf("不小于 %d 的关键字(从大到小):\n", k);
reverseInorder(root, k);
printf("\n");
return 0;
}
基数排序
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100 // 最大输入数字个数
// 输出数组
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// 获取数组中的最大值
int getMax(int arr[], int n) {
int max = arr[0];
for (int i = 1; i < n; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
// 基数排序的计数排序部分
void countingSort(int arr[], int n, int exp) {
int output[n]; // 存储排序结果的数组
int count[10] = {0}; // 计数数组,初始化为0
// 统计每个数字出现的次数
for (int i = 0; i < n; i++) {
count[(arr[i] / exp) % 10]++;
}
// 计算累加次数
for (int i = 1; i < 10; i++) {
count[i] += count[i - 1];
}
// 从后向前遍历原数组,将元素放入输出数组中
for (int i = n - 1; i >= 0; i--) {
output[count[(arr[i] / exp) % 10] - 1] = arr[i];
count[(arr[i] / exp) % 10]--;
}
// 将排序结果复制回原数组
for (int i = 0; i < n; i++) {
arr[i] = output[i];
}
}
// 基数排序
void radixSort(int arr[], int n) {
// 获取数组中的最大值
int max = getMax(arr, n);
// 对每一位进行计数排序
for (int exp = 1; max / exp > 0; exp *= 10) {
countingSort(arr, n, exp);
// 输出当前趟的结果
printf("当前趟排序结果(按位 %d):", exp);
printArray(arr, n);
}
}
int main() {
int arr[MAX_SIZE];
int n = 0; // 实际输入的数字个数
// 输入数字
printf("请输入一串数字(以空格分隔,回车结束):");
char ch;
while (scanf("%d", &arr[n]) == 1) {
n++;
if ((ch = getchar()) == '\n') {
break; // 输入结束
}
}
// 输出原始数组
printf("原始数组:");
printArray(arr, n);
// 基数排序并输出每一趟结果
radixSort(arr, n);
// 输出最终排序结果
printf("最终排序结果:");
printArray(arr, n);
return 0;
}
简单选择排序
#include <stdio.h>
#define MAX_SIZE 100 // 最大输入数字个数
// 输出数组
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// 简单选择排序并输出每一趟结果
void selectionSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
// 找到待排序部分的最小元素
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// 交换最小元素与待排序部分的第一个元素
if (minIndex != i) {
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
// 输出当前趟的结果
printf("第 %d 趟排序结果:", i + 1);
printArray(arr, n);
}
}
int main() {
int arr[MAX_SIZE];
int n = 0; // 实际输入的数字个数
// 输入数字
printf("请输入一串数字(以空格分隔,回车结束):");
char ch;
while (scanf("%d", &arr[n]) == 1) {
n++;
if ((ch = getchar()) == '\n') {
break; // 输入结束
}
}
// 输出原始数组
printf("原始数组:");
printArray(arr, n);
// 简单选择排序并输出每一趟结果
selectionSort(arr, n);
return 0;
}
快速排序
#include <stdio.h>
#define MAX_SIZE 100 // 最大输入数字个数
// 输出数组
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// 分区函数
int partition(int arr[], int low, int high) {
int pivot = arr[low]; // 选择第一个元素作为基准
int i = low + 1;
int j = high;
while (1) {
// 找到第一个大于基准的元素
while (i <= j && arr[i] <= pivot) {
i++;
}
// 找到第一个小于基准的元素
while (i <= j && arr[j] >= pivot) {
j--;
}
// 如果 i 和 j 相遇,退出循环
if (i > j) {
break;
}
// 交换 arr[i] 和 arr[j]
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 将基准元素放到正确的位置
int temp = arr[low];
arr[low] = arr[j];
arr[j] = temp;
return j; // 返回基准元素的位置
}
// 快速排序并输出每一趟结果
void quickSort(int arr[], int low, int high, int n) {
if (low < high) {
// 分区并获取基准元素的位置
int pivotIndex = partition(arr, low, high);
// 输出当前趟的结果
printf("基准元素:%d,排序结果:", arr[pivotIndex]);
printArray(arr, n);
// 递归排序左半部分
quickSort(arr, low, pivotIndex - 1, n);
// 递归排序右半部分
quickSort(arr, pivotIndex + 1, high, n);
}
}
int main() {
int arr[MAX_SIZE];
int n = 0; // 实际输入的数字个数
// 输入数字
printf("请输入一串数字(以空格分隔,回车结束):");
char ch;
while (scanf("%d", &arr[n]) == 1) {
n++;
if ((ch = getchar()) == '\n') {
break; // 输入结束
}
}
// 输出原始数组
printf("原始数组:");
printArray(arr, n);
// 快速排序并输出每一趟结果
quickSort(arr, 0, n - 1, n);
return 0;
}
冒泡排序
#include <stdio.h>
#include <stdbool.h>
#define MAX_SIZE 100 // 最大输入数字个数
// 交换两个数
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 冒泡排序并输出每一趟结果
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
bool swapped = false; // 标记是否发生交换
// 一趟冒泡排序
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
swap(&arr[j], &arr[j + 1]);
swapped = true;
}
}
// 输出当前趟的结果
printf("第 %d 趟排序结果:", i + 1);
for (int k = 0; k < n; k++) {
printf("%d ", arr[k]);
}
printf("\n");
// 如果未发生交换,说明数组已经有序,提前结束
if (!swapped) {
break;
}
}
}
int main() {
int arr[MAX_SIZE];
int n = 0; // 实际输入的数字个数
// 输入数字
printf("请输入一串数字(以空格分隔,回车结束):");
char ch;
while (scanf("%d", &arr[n]) == 1) {
n++;
if ((ch = getchar()) == '\n') {
break; // 输入结束
}
}
// 输出原始数组
printf("原始数组:");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// 冒泡排序并输出每一趟结果
bubbleSort(arr, n);
return 0;
}
平衡二叉树
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 定义二叉树节点结构
typedef struct TreeNode {
int key; // 节点值
struct TreeNode* left; // 左子树
struct TreeNode* right; // 右子树
} TreeNode;
// 创建新节点
TreeNode* createNode(int key) {
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
newNode->key = key;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// 插入节点到二叉排序树
TreeNode* insert(TreeNode* root, int key) {
if (root == NULL) {
return createNode(key);
}
if (key < root->key) {
root->left = insert(root->left, key);
} else if (key > root->key) {
root->right = insert(root->right, key);
}
return root;
}
// 计算树的高度
int height(TreeNode* root) {
if (root == NULL) {
return 0;
}
int leftHeight = height(root->left);
int rightHeight = height(root->right);
return 1 + (leftHeight > rightHeight ? leftHeight : rightHeight);
}
// 判断树是否平衡
bool isBalanced(TreeNode* root) {
if (root == NULL) {
return true; // 空树是平衡的
}
// 计算左右子树的高度
int leftHeight = height(root->left);
int rightHeight = height(root->right);
// 检查当前节点是否平衡
if (abs(leftHeight - rightHeight) > 1) {
return false;
}
// 递归检查左右子树是否平衡
return isBalanced(root->left) && isBalanced(root->right);
}
int main() {
TreeNode* root = NULL;
// 插入节点构建二叉排序树
root = insert(root, 50);
root = insert(root, 30);
root = insert(root, 70);
root = insert(root, 20);
root = insert(root, 40);
// 判断树是否平衡
if (isBalanced(root)) {
printf("该二叉排序树是平衡的。\n");
} else {
printf("该二叉排序树不是平衡的。\n");
}
return 0;
}
希尔排序
#include <stdio.h>
#define MAX_SIZE 100 // 最大输入数字个数
// 输出数组
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// 希尔排序并输出每一趟结果
void shellSort(int arr[], int n) {
int gap, i, j, temp;
// 初始间隔为 n/2,逐步缩小间隔
for (gap = n / 2; gap > 0; gap /= 2) {
// 对每个间隔进行插入排序
for (i = gap; i < n; i++) {
temp = arr[i];
j = i;
// 将比 temp 大的元素向后移动
while (j >= gap && arr[j - gap] > temp) {
arr[j] = arr[j - gap];
j -= gap;
}
// 插入 temp
arr[j] = temp;
}
// 输出当前趟的结果
printf("间隔为 %d 的排序结果:", gap);
printArray(arr, n);
}
}
int main() {
int arr[MAX_SIZE];
int n = 0; // 实际输入的数字个数
// 输入数字
printf("请输入一串数字(以空格分隔,回车结束):");
char ch;
while (scanf("%d", &arr[n]) == 1) {
n++;
if ((ch = getchar()) == '\n') {
break; // 输入结束
}
}
// 输出原始数组
printf("原始数组:");
printArray(arr, n);
// 希尔排序并输出每一趟结果
shellSort(arr, n);
return 0;
}
直接插入排序
#include <stdio.h>
#define MAX_SIZE 100 // 最大输入数字个数
// 输出数组
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// 直接插入排序并输出每一趟结果
void insertionSort(int arr[], int n) {
for (int i = 1; i < n; i++) {
int key = arr[i]; // 当前待插入的元素
int j = i - 1;
// 将比 key 大的元素向后移动
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
// 插入 key
arr[j + 1] = key;
// 输出当前趟的结果
printf("第 %d 趟排序结果:", i);
printArray(arr, n);
}
}
int main() {
int arr[MAX_SIZE];
int n = 0; // 实际输入的数字个数
// 输入数字
printf("请输入一串数字(以空格分隔,回车结束):");
char ch;
while (scanf("%d", &arr[n]) == 1) {
n++;
if ((ch = getchar()) == '\n') {
break; // 输入结束
}
}
// 输出原始数组
printf("原始数组:");
printArray(arr, n);
// 直接插入排序并输出每一趟结果
insertionSort(arr, n);
return 0;
}
图
不带权的无向图求最短路径
#include <stdio.h>
#include <stdlib.h>
#define MAX_NODES 100 // 最大节点数
// 定义邻接表节点
typedef struct AdjListNode {
int dest; // 目标顶点
struct AdjListNode* next; // 指向下一个邻接节点
} AdjListNode;
// 定义邻接表
typedef struct {
AdjListNode* head; // 邻接表的头节点
} AdjList;
// 定义图
typedef struct {
int numNodes; // 节点数
AdjList* array; // 邻接表数组
} Graph;
// 创建新节点
AdjListNode* createNode(int dest) {
AdjListNode* newNode = (AdjListNode*)malloc(sizeof(AdjListNode));
newNode->dest = dest;
newNode->next = NULL;
return newNode;
}
// 初始化图
Graph* createGraph(int numNodes) {
Graph* graph = (Graph*)malloc(sizeof(Graph));
graph->numNodes = numNodes;
graph->array = (AdjList*)malloc(numNodes * sizeof(AdjList));
// 初始化每个邻接表
for (int i = 0; i < numNodes; i++) {
graph->array[i].head = NULL;
}
return graph;
}
// 添加边
void addEdge(Graph* graph, int src, int dest) {
// 添加从 src 到 dest 的边
AdjListNode* newNode = createNode(dest);
newNode->next = graph->array[src].head;
graph->array[src].head = newNode;
// 添加从 dest 到 src 的边(无向图)
newNode = createNode(src);
newNode->next = graph->array[dest].head;
graph->array[dest].head = newNode;
}
// 广度优先搜索(BFS)查找最短路径
void BFS(Graph* graph, int start, int dist[]) {
// 初始化距离数组
for (int i = 0; i < graph->numNodes; i++) {
dist[i] = -1; // -1 表示尚未访问
}
// 创建队列
int queue[MAX_NODES];
int front = 0, rear = 0;
// 将起点加入队列
queue[rear++] = start;
dist[start] = 0;
// BFS 遍历
while (front < rear) {
int current = queue[front++]; // 出队
// 遍历当前节点的邻接节点
AdjListNode* neighbor = graph->array[current].head;
while (neighbor != NULL) {
int neighborDest = neighbor->dest;
// 如果邻接节点未被访问过
if (dist[neighborDest] == -1) {
dist[neighborDest] = dist[current] + 1; // 更新距离
queue[rear++] = neighborDest; // 入队
}
neighbor = neighbor->next;
}
}
}
int main() {
int numNodes = 6; // 假设图有 6 个节点
Graph* graph = createGraph(numNodes);
// 添加边
addEdge(graph, 0, 1);
addEdge(graph, 1, 3);
addEdge(graph, 2, 3);
addEdge(graph, 3, 4);
// 输入起点
int start;
printf("请输入起点(0-%d):", numNodes - 1);
scanf("%d", &start);
// 检查起点是否有效
if (start < 0 || start >= numNodes) {
printf("起点无效!\n");
return 1;
}
// 计算最短路径
int dist[MAX_NODES];
BFS(graph, start, dist);
// 输出结果
printf("从顶点 %d 到其他顶点的最短路径:\n", start);
for (int i = 0; i < numNodes; i++) {
if (dist[i] == -1) {
printf("顶点 %d 不可达\n", i);
} else {
printf("顶点 %d 的最短距离:%d\n", i, dist[i]);
}
}
return 0;
}
带权无向图最短路径
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MAX_NODES 100 // 最大节点数
#define INF INT_MAX // 表示无穷大
// 定义邻接表节点
typedef struct AdjListNode {
int dest; // 目标顶点
int weight; // 边的权重
struct AdjListNode* next; // 指向下一个邻接节点
} AdjListNode;
// 定义邻接表
typedef struct {
AdjListNode* head; // 邻接表的头节点
} AdjList;
// 定义图
typedef struct {
int numNodes; // 节点数
AdjList* array; // 邻接表数组
} Graph;
// 创建新节点
AdjListNode* createNode(int dest, int weight) {
AdjListNode* newNode = (AdjListNode*)malloc(sizeof(AdjListNode));
newNode->dest = dest;
newNode->weight = weight;
newNode->next = NULL;
return newNode;
}
// 初始化图
Graph* createGraph(int numNodes) {
Graph* graph = (Graph*)malloc(sizeof(Graph));
graph->numNodes = numNodes;
graph->array = (AdjList*)malloc(numNodes * sizeof(AdjList));
// 初始化每个邻接表
for (int i = 0; i < numNodes; i++) {
graph->array[i].head = NULL;
}
return graph;
}
// 添加边
void addEdge(Graph* graph, int src, int dest, int weight) {
// 添加从 src 到 dest 的边
AdjListNode* newNode = createNode(dest, weight);
newNode->next = graph->array[src].head;
graph->array[src].head = newNode;
// 添加从 dest 到 src 的边(无向图)
newNode = createNode(src, weight);
newNode->next = graph->array[dest].head;
graph->array[dest].head = newNode;
}
// Dijkstra 算法
void Dijkstra(Graph* graph, int start, int dist[]) {
// 初始化距离数组
for (int i = 0; i < graph->numNodes; i++) {
dist[i] = INF; // 初始化为无穷大
}
dist[start] = 0; // 起点到自身的距离为 0
// 创建一个数组记录顶点是否已处理
int processed[MAX_NODES] = {0};
// 遍历所有顶点
for (int count = 0; count < graph->numNodes - 1; count++) {
// 找到未处理顶点中距离最小的顶点
int minDist = INF;
int minIndex = -1;
for (int i = 0; i < graph->numNodes; i++) {
if (!processed[i] && dist[i] < minDist) {
minDist = dist[i];
minIndex = i;
}
}
// 如果没有找到,说明剩下的顶点不可达
if (minIndex == -1) {
break;
}
// 标记当前顶点为已处理
processed[minIndex] = 1;
// 更新邻接顶点的距离
AdjListNode* neighbor = graph->array[minIndex].head;
while (neighbor != NULL) {
int dest = neighbor->dest;
int weight = neighbor->weight;
if (!processed[dest] && dist[minIndex] + weight < dist[dest]) {
dist[dest] = dist[minIndex] + weight;
}
neighbor = neighbor->next;
}
}
}
int main() {
int numNodes = 6; // 假设图有 6 个节点
Graph* graph = createGraph(numNodes);
// 添加边
addEdge(graph, 0, 1, 2);
addEdge(graph, 0, 2, 4);
addEdge(graph, 1, 2, 1);
addEdge(graph, 1, 3, 7);
addEdge(graph, 2, 4, 3);
addEdge(graph, 3, 4, 1);
addEdge(graph, 3, 5, 5);
addEdge(graph, 4, 5, 2);
// 输入起点
int start;
printf("请输入起点(0-%d):", numNodes - 1);
scanf("%d", &start);
// 检查起点是否有效
if (start < 0 || start >= numNodes) {
printf("起点无效!\n");
return 1;
}
// 计算最短路径
int dist[MAX_NODES];
Dijkstra(graph, start, dist);
// 输出结果
printf("从顶点 %d 到其他顶点的最短路径:\n", start);
for (int i = 0; i < numNodes; i++) {
if (dist[i] == INF) {
printf("顶点 %d 不可达\n", i);
} else {
printf("顶点 %d 的最短距离:%d\n", i, dist[i]);
}
}
return 0;
}
带权有向图最短路径
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define MAX_NODES 100 // 最大节点数
#define INF INT_MAX // 表示无穷大
// 定义邻接表节点
typedef struct AdjListNode {
int dest; // 目标顶点
int weight; // 边的权重
struct AdjListNode* next; // 指向下一个邻接节点
} AdjListNode;
// 定义邻接表
typedef struct {
AdjListNode* head; // 邻接表的头节点
} AdjList;
// 定义图
typedef struct {
int numNodes; // 节点数
AdjList* array; // 邻接表数组
} Graph;
// 创建新节点
AdjListNode* createNode(int dest, int weight) {
AdjListNode* newNode = (AdjListNode*)malloc(sizeof(AdjListNode));
newNode->dest = dest;
newNode->weight = weight;
newNode->next = NULL;
return newNode;
}
// 初始化图
Graph* createGraph(int numNodes) {
Graph* graph = (Graph*)malloc(sizeof(Graph));
graph->numNodes = numNodes;
graph->array = (AdjList*)malloc(numNodes * sizeof(AdjList));
// 初始化每个邻接表
for (int i = 0; i < numNodes; i++) {
graph->array[i].head = NULL;
}
return graph;
}
// 添加边(有向图)
void addEdge(Graph* graph, int src, int dest, int weight) {
// 添加从 src 到 dest 的边
AdjListNode* newNode = createNode(dest, weight);
newNode->next = graph->array[src].head;
graph->array[src].head = newNode;
}
// Dijkstra 算法
void Dijkstra(Graph* graph, int start, int dist[]) {
// 初始化距离数组
for (int i = 0; i < graph->numNodes; i++) {
dist[i] = INF; // 初始化为无穷大
}
dist[start] = 0; // 起点到自身的距离为 0
// 创建一个数组记录顶点是否已处理
int processed[MAX_NODES] = {0};
// 遍历所有顶点
for (int count = 0; count < graph->numNodes - 1; count++) {
// 找到未处理顶点中距离最小的顶点
int minDist = INF;
int minIndex = -1;
for (int i = 0; i < graph->numNodes; i++) {
if (!processed[i] && dist[i] < minDist) {
minDist = dist[i];
minIndex = i;
}
}
// 如果没有找到,说明剩下的顶点不可达
if (minIndex == -1) {
break;
}
// 标记当前顶点为已处理
processed[minIndex] = 1;
// 更新邻接顶点的距离
AdjListNode* neighbor = graph->array[minIndex].head;
while (neighbor != NULL) {
int dest = neighbor->dest;
int weight = neighbor->weight;
if (!processed[dest] && dist[minIndex] + weight < dist[dest]) {
dist[dest] = dist[minIndex] + weight;
}
neighbor = neighbor->next;
}
}
}
int main() {
int numNodes = 6; // 假设图有 6 个节点
Graph* graph = createGraph(numNodes);
// 添加边(有向图)
addEdge(graph, 0, 1, 2);
addEdge(graph, 0, 2, 4);
addEdge(graph, 1, 2, 1);
addEdge(graph, 1, 3, 7);
addEdge(graph, 2, 4, 3);
addEdge(graph, 3, 4, 1);
addEdge(graph, 3, 5, 5);
addEdge(graph, 4, 5, 2);
// 输入起点
int start;
printf("请输入起点(0-%d):", numNodes - 1);
scanf("%d", &start);
// 检查起点是否有效
if (start < 0 || start >= numNodes) {
printf("起点无效!\n");
return 1;
}
// 计算最短路径
int dist[MAX_NODES];
Dijkstra(graph, start, dist);
// 输出结果
printf("从顶点 %d 到其他顶点的最短路径:\n", start);
for (int i = 0; i < numNodes; i++) {
if (dist[i] == INF) {
printf("顶点 %d 不可达\n", i);
} else {
printf("顶点 %d 的最短距离:%d\n", i, dist[i]);
}
}
return 0;
}
输出邻接矩阵
#include <stdio.h>
#include <stdlib.h>
#define MAX_NODES 5 // 最大节点数
#define INF 99999 // 表示无穷大(无边)
// 定义节点名称到索引的映射
int getIndex(char node) {
switch (node) {
case 'a': return 0;
case 'b': return 1;
case 'c': return 2;
case 'd': return 3;
case 'e': return 4;
default: return -1; // 无效节点
}
}
// 初始化邻接矩阵
void initMatrix(int matrix[MAX_NODES][MAX_NODES]) {
for (int i = 0; i < MAX_NODES; i++) {
for (int j = 0; j < MAX_NODES; j++) {
matrix[i][j] = INF; // 初始化为无穷大
}
matrix[i][i] = 0; // 对角线为0(节点到自身的距离为0)
}
}
// 添加边到邻接矩阵
void addEdge(int matrix[MAX_NODES][MAX_NODES], char src, char dest, int weight) {
int srcIndex = getIndex(src);
int destIndex = getIndex(dest);
if (srcIndex == -1 || destIndex == -1) {
printf("无效的节点!\n");
return;
}
matrix[srcIndex][destIndex] = weight;
matrix[destIndex][srcIndex] = weight; // 无向图,对称填充
}
// 打印邻接矩阵
void printMatrix(int matrix[MAX_NODES][MAX_NODES]) {
printf("邻接矩阵:\n");
printf(" a b c d e\n"); // 对齐节点名称
for (int i = 0; i < MAX_NODES; i++) {
switch (i) {
case 0: printf("a "); break;
case 1: printf("b "); break;
case 2: printf("c "); break;
case 3: printf("d "); break;
case 4: printf("e "); break;
}
for (int j = 0; j < MAX_NODES; j++) {
if (matrix[i][j] == INF) {
printf(" INF"); // 对齐 INF
} else {
printf("%6d", matrix[i][j]); // 对齐数字
}
}
printf("\n");
}
}
int main() {
int matrix[MAX_NODES][MAX_NODES];
// 初始化邻接矩阵
initMatrix(matrix);
// 添加边
addEdge(matrix, 'a', 'b', 3);
addEdge(matrix, 'a', 'c', 6);
addEdge(matrix, 'a', 'e', 7);
addEdge(matrix, 'b', 'c', 2);
addEdge(matrix, 'b', 'd', 8);
addEdge(matrix, 'b', 'e', 3);
addEdge(matrix, 'c', 'd', 9);
// 打印邻接矩阵
printMatrix(matrix);
return 0;
}
拓扑排序
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_NODES 100 // 最大节点数
// 定义邻接表节点
typedef struct AdjListNode {
int dest; // 目标顶点
struct AdjListNode* next; // 指向下一个邻接节点
} AdjListNode;
// 定义邻接表
typedef struct {
AdjListNode* head; // 邻接表的头节点
} AdjList;
// 定义图
typedef struct {
int numNodes; // 节点数
AdjList* array; // 邻接表数组
} Graph;
// 创建新节点
AdjListNode* createNode(int dest) {
AdjListNode* newNode = (AdjListNode*)malloc(sizeof(AdjListNode));
newNode->dest = dest;
newNode->next = NULL;
return newNode;
}
// 初始化图
Graph* createGraph(int numNodes) {
Graph* graph = (Graph*)malloc(sizeof(Graph));
graph->numNodes = numNodes;
graph->array = (AdjList*)malloc(numNodes * sizeof(AdjList));
// 初始化每个邻接表
for (int i = 0; i < numNodes; i++) {
graph->array[i].head = NULL;
}
return graph;
}
// 添加边(有向图)
void addEdge(Graph* graph, int src, int dest) {
// 添加从 src 到 dest 的边
AdjListNode* newNode = createNode(dest);
newNode->next = graph->array[src].head;
graph->array[src].head = newNode;
}
// 计算每个顶点的入度
void calculateInDegree(Graph* graph, int inDegree[]) {
for (int i = 0; i < graph->numNodes; i++) {
inDegree[i] = 0;
}
for (int i = 0; i < graph->numNodes; i++) {
AdjListNode* neighbor = graph->array[i].head;
while (neighbor != NULL) {
inDegree[neighbor->dest]++;
neighbor = neighbor->next;
}
}
}
// 输出拓扑排序
void printTopologicalSort(int order[], int n) {
for (int i = 0; i < n; i++) {
printf("%d ", order[i]);
}
printf("\n");
}
// 递归生成所有拓扑排序
void allTopologicalSortsUtil(Graph* graph, int inDegree[], bool visited[], int order[], int index) {
// 如果所有顶点都已加入排序,则输出当前排序
if (index == graph->numNodes) {
printTopologicalSort(order, graph->numNodes);
return;
}
// 遍历所有顶点
for (int i = 0; i < graph->numNodes; i++) {
// 如果当前顶点入度为 0 且未被访问过
if (inDegree[i] == 0 && !visited[i]) {
// 将当前顶点加入排序
order[index] = i;
visited[i] = true;
// 减少其邻接顶点的入度
AdjListNode* neighbor = graph->array[i].head;
while (neighbor != NULL) {
inDegree[neighbor->dest]--;
neighbor = neighbor->next;
}
// 递归生成剩余顶点的拓扑排序
allTopologicalSortsUtil(graph, inDegree, visited, order, index + 1);
// 回溯:恢复状态
visited[i] = false;
neighbor = graph->array[i].head;
while (neighbor != NULL) {
inDegree[neighbor->dest]++;
neighbor = neighbor->next;
}
}
}
}
// 输出所有拓扑排序
void allTopologicalSorts(Graph* graph) {
// 初始化入度数组
int inDegree[MAX_NODES];
calculateInDegree(graph, inDegree);
// 初始化访问数组和排序数组
bool visited[MAX_NODES] = {false};
int order[MAX_NODES];
// 生成所有拓扑排序
allTopologicalSortsUtil(graph, inDegree, visited, order, 0);
}
int main() {
int numNodes = 6; // 假设图有 6 个节点
Graph* graph = createGraph(numNodes);
// 添加边(有向图)
addEdge(graph, 0, 1);
addEdge(graph, 0, 2);
addEdge(graph, 1, 3);
addEdge(graph, 2, 3);
addEdge(graph, 2, 4);
addEdge(graph, 2, 5);
addEdge(graph, 3, 4);
addEdge(graph, 3, 5);
addEdge(graph, 4, 5);
// 输出所有拓扑排序
printf("所有拓扑排序:\n");
allTopologicalSorts(graph);
return 0;
}
无向图回路
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_NODES 5 // 最大节点数
#define MAX_EDGES 6 // 最大边数
// 定义图的结构 //04 01 42 43 23
typedef struct {
int edges[MAX_NODES][MAX_NODES]; // 邻接矩阵
int degree[MAX_NODES]; // 每个顶点的度数
int numNodes; // 节点数
int numEdges; // 边数
} Graph;
// 初始化图
void initGraph(Graph *graph) {
graph->numNodes = MAX_NODES;
graph->numEdges = 0;
for (int i = 0; i < MAX_NODES; i++) {
graph->degree[i] = 0;
for (int j = 0; j < MAX_NODES; j++) {
graph->edges[i][j] = 0; // 初始化邻接矩阵
}
}
}
// 添加边
void addEdge(Graph *graph, int src, int dest) {
graph->edges[src][dest] = 1;
graph->edges[dest][src] = 1; // 无向图,对称填充
graph->degree[src]++;
graph->degree[dest]++;
graph->numEdges++;
}
// 检查图是否连通
bool isConnected(Graph *graph) {
bool visited[MAX_NODES] = {false};
int stack[MAX_NODES];
int top = -1;
// 从顶点0开始深度优先搜索(DFS)
stack[++top] = 0;
visited[0] = true;
while (top >= 0) {
int node = stack[top--];
for (int i = 0; i < MAX_NODES; i++) {
if (graph->edges[node][i] && !visited[i]) {
visited[i] = true;
stack[++top] = i;
}
}
}
// 检查是否所有顶点都被访问过
for (int i = 0; i < MAX_NODES; i++) {
if (!visited[i]) {
return false; // 图不连通
}
}
return true; // 图连通
}
// 检查是否存在欧拉回路
bool hasEulerianCircuit(Graph *graph) {
// 检查是否所有顶点的度数都是偶数
for (int i = 0; i < MAX_NODES; i++) {
if (graph->degree[i] % 2 != 0) {
return false; // 存在奇数度数的顶点
}
}
// 检查图是否连通
return isConnected(graph);
}
// 找到欧拉回路
void findEulerianCircuit(Graph *graph, int start, int *path, int *pathIndex) {
for (int i = 0; i < MAX_NODES; i++) {
if (graph->edges[start][i]) {
// 删除边
graph->edges[start][i] = 0;
graph->edges[i][start] = 0;
// 递归查找
findEulerianCircuit(graph, i, path, pathIndex);
}
}
// 将当前节点加入路径
path[(*pathIndex)++] = start;
}
int main() {
Graph graph;
initGraph(&graph);
// 用户输入边
printf("请输入6条边(格式:u v,表示顶点u和顶点v之间的边):\n");
for (int i = 0; i < MAX_EDGES; i++) {
int u, v;
printf("边 %d:", i + 1);
scanf("%d %d", &u, &v);
if (u < 0 || u >= MAX_NODES || v < 0 || v >= MAX_NODES) {
printf("输入的顶点无效!请重新输入。\n");
i--; // 重新输入当前边
continue;
}
addEdge(&graph, u, v);
}
// 检查是否存在欧拉回路
if (!hasEulerianCircuit(&graph)) {
printf("图中不存在欧拉回路!\n");
return 0;
}
// 输入起始顶点
int k;
printf("请输入起始顶点(0-4):");
scanf("%d", &k);
if (k < 0 || k >= MAX_NODES) {
printf("输入的顶点无效!\n");
return 1;
}
// 找到欧拉回路
int path[MAX_EDGES + 1]; // 路径最多包含 MAX_EDGES + 1 个顶点
int pathIndex = 0;
findEulerianCircuit(&graph, k, path, &pathIndex);
// 输出路径
printf("欧拉回路路径:");
for (int i = 0; i < pathIndex; i++) {
printf("%d ", path[i]);
}
printf("\n");
return 0;
}