在学习C语言时,结构体、指针
和
常见的数据结构如链表、栈、队列、二叉树等,是绕不开的重点。
本篇博客用通俗易懂的方式,介绍这些概念,结合简单的代码示例,带你逐步掌握这些基础知识。
1. 结构体和指针
我们先来看一眼结构体和指针,不懂这些的话,下面的代码肯定看不懂,
没学过这些的朋友可以先看完这些内容再进行数据结构的学习
结构体就是用来存储不同类型的数据。比如你想保存一个人的姓名、年龄和身高,用结构体就很方便。
个人感觉这里有点象Java里的class,这里叫做struct
#include <stdio.h>
// 定义一个结构体,用于存储人的信息
struct Person {
char name[50]; // 姓名
int age; // 年龄
float height; // 身高
};
int main() {
struct Person person1; // 创建一个Person类型的变量person1
// 赋值给person1
person1.age = 25;
person1.height = 1.75;
snprintf(person1.name, sizeof(person1.name), "Alice");
// 打印信息
printf("姓名: %s, 年龄: %d, 身高: %.2f\n", person1.name, person1.age, person1.height);
return 0;
}
指针 是C语言中一个重要的工具,指向内存中的某个地址。用指针操作结构体可以提高效率,特别是当你要操作大的结构体或者需要传递结构体给函数时。
#include <stdio.h>
// 定义结构体
struct Person {
char name[50];
int age;
float height;
};
int main() {
struct Person person1 = {"Bob", 30, 1.80}; // 定义并初始化结构体
struct Person *p = &person1; // 定义指针指向结构体person1
// 通过指针访问结构体数据
printf("姓名: %s, 年龄: %d, 身高: %.2f\n", p->name, p->age, p->height);
return 0;
}
简单解释:
struct Person *p = &person1;
:我们创建了一个结构体指针p
,它指向person1
这个结构体。p->name
:用->
来访问指针指向的结构体成员。
2. 链表(Linked List)
链表 是由节点组成的,每个节点包含数据和指向下一个节点的指针。相比数组,链表的优势是可以随时增减节点,非常灵活。
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点
struct Node {
int data; // 节点数据
struct Node* next; // 指向下一个节点的指针
};
// 打印链表
void printList(struct Node* n) {
while (n != NULL) { // 循环打印每个节点的数据
printf("%d ", n->data);
n = n->next;
}
}
int main() {
// 动态分配内存创建三个节点
struct Node* head = (struct Node*)malloc(sizeof(struct Node));
struct Node* second = (struct Node*)malloc(sizeof(struct Node));
struct Node* third = (struct Node*)malloc(sizeof(struct Node));
// 初始化节点数据
head->data = 1; // 第一个节点数据
head->next = second; // 第一个节点指向第二个节点
second->data = 2; // 第二个节点数据
second->next = third; // 第二个节点指向第三个
third->data = 3; // 第三个节点数据
third->next = NULL; // 第三个节点是最后一个,指向空
printList(head); // 打印链表
return 0;
}
简单解释:
- 链表中的每个节点通过
next
指针连接起来。 - 你可以随时添加或删除节点,不像数组那样需要预先确定大小。
3. 栈(Stack)
栈 是一种后进先出(LIFO)的数据结构,意思是,最后放进去的元素最先被取出来。常用的操作有 push
(入栈)和 pop
(出栈)。
#include <stdio.h>
#define MAX 5 // 栈的最大容量
int stack[MAX];
int top = -1; // 栈顶指针,初始值为-1
// 入栈操作
void push(int data) {
if (top == MAX - 1) {
printf("栈满了,不能再入栈\n");
} else {
stack[++top] = data; // 栈顶指针先加1,再将数据放入栈
}
}
// 出栈操作
int pop() {
if (top == -1) {
printf("栈空了,不能再出栈\n");
return -1;
} else {
return stack[top--]; // 先返回栈顶数据,再将栈顶指针减1
}
}
int main() {
push(10); // 入栈10
push(20); // 入栈20
printf("出栈: %d\n", pop()); // 应该输出20
printf("出栈: %d\n", pop()); // 应该输出10
return 0;
}
简单解释:
stack[++top] = data;
:将数据入栈,同时移动栈顶指针。return stack[top--];
:取出栈顶数据,并将栈顶指针减1。
4. 队列(Queue)
队列 是一种先进先出(FIFO)的数据结构,最早入队的元素最先被取出。主要操作有 enqueue
(入队)和 dequeue
(出队)。
#include <stdio.h>
#define MAX 5 // 队列的最大容量
int queue[MAX];
int front = -1, rear = -1; // 队列的前后指针
// 入队操作
void enqueue(int data) {
if (rear == MAX - 1) {
printf("队列满了,不能再入队\n");
} else {
if (front == -1) front = 0; // 队列为空时,初始化front
queue[++rear] = data; // 入队
}
}
// 出队操作
int dequeue() {
if (front == -1 || front > rear) {
printf("队列空了,不能再出队\n");
return -1;
} else {
return queue[front++]; // 出队并移动front指针
}
}
int main() {
enqueue(10); // 入队10
enqueue(20); // 入队20
printf("出队: %d\n", dequeue()); // 应该输出10
printf("出队: %d\n", dequeue()); // 应该输出20
return 0;
}
简单解释:
queue[++rear] = data;
:将数据入队,队尾指针后移。return queue[front++];
:出队操作,队首指针前移。
5. 二叉树(Binary Tree)
二叉树 是每个节点最多有两个子节点(左、右)的数据结构,常用于搜索树或表达层次结构。
#include <stdio.h>
#include <stdlib.h>
// 定义二叉树节点
struct Node {
int data;
struct Node* left; // 左子节点
struct Node* right; // 右子节点
};
// 创建新节点
struct Node* newNode(int data) {
struct Node* node = (struct Node*)malloc(sizeof(struct Node));
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
// 先序遍历(根 -> 左 -> 右)
void preOrder(struct Node* node) {
if (node == NULL) return;
printf("%d ", node->data);
preOrder(node->left);
preOrder(node->right);
}
int main() {
struct Node* root = newNode(1); // 创建根节点
root->left = newNode(2); // 左子节点
root->right = newNode(3); // 右子节点
root->left->left = newNode(4); // 左子节点的左子节点
root->left->right = newNode(5); // 左子节点的右子节点
printf("先序遍历结果:\n");
preOrder(root); // 打印顺序:1 2 4 5 3
return 0;
}
简单解释:
preOrder
是一种遍历方式,先访问根节点,再依次访问左子节点和右子节点。上面例子中,按照先序遍历的顺序,会依次打印节点的数据。
总结
在这篇文章里,我们学习了C语言中的结构体、指针和几种常见的数据结构,包括链表、栈、队列和二叉树。这些数据结构是程序设计中非常基础的概念,
必须掌握,否则之后会寸步难行
学数据结构的几点建议:
- 理解指针:指针是C语言的灵魂,多写写指针相关的代码,理解它怎么指向内存、怎么操作数据。
- 多练习链表:链表的操作虽然看起来简单,但很多细节很容易出错,多加练习有助于提高编程能力。
- 掌握栈和队列的应用场景:栈和队列常常在算法题中出现,比如递归、广度优先搜索等,这些数据结构的实现可以加深我们对这些算法的理解。
以上的这些代码,不仅需要看,更需要跟着敲一遍代码,才能理解这其中的结构.
代码是需要肌肉记忆的.
标签:Node,struct,int,C语言,数据结构,data,节点,指针 From: https://blog.csdn.net/2301_79175212/article/details/142471559