链表
两个链表合并成为一个
#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);// 输入 kint 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_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;
}