1.栈
核心:后进先出
栈(Stack)是一种遵循后进先出原则的线性数据结构。其核心操作包括:
- 压栈(Push):将元素添加到栈顶
- 弹栈(Pop):移除并返回栈顶元素
- 查看栈顶(Peek/Top):返回栈顶元素但不移除
- 判空(isEmpty):检查栈是否为空
应用场景
- 撤销操作(编辑器历史记录)
C代码实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STACK_SIZE 50
typedef struct {
char address[MAX_STACK_SIZE];
} StackItem;
typedef struct {
StackItem items[MAX_STACK_SIZE];
int top;
} Stack;
void initStack(Stack *stack) {
stack->top = -1;
}
/*
判断栈是否为空
检查传入的栈是否为空,若栈为空则返回1,否则返回0。
*/
int isStackEmpty(Stack *stack) {
return stack->top == -1;
}
/*
检查栈是否已满
如果栈已满返回1,否则返回0
*/
int isStackFull(Stack *stack) {
return stack->top == MAX_STACK_SIZE - 1;
}
void push(Stack *stack, char *address) {
if (isStackFull(stack))
{
printf("Stack 满\n");
return;
}
stack->top++;
strcpy(stack->items[stack->top].address, address);
}
char* pop(Stack *stack) {
if (isStackEmpty(stack)) {
printf("Stack underflow!\n");
return NULL;
}
char *address = stack->items[stack->top].address;
stack->top--;
return address;
}
int main() {
char inputaddress[MAX_STACK_SIZE];
int choice;
Stack stack;
initStack(&stack);
while (1)
{
printf("1:入栈\n");
printf("2:出栈\n");
scanf("%d",&choice);
switch (choice)
{
case 1:
printf("入栈内容:");
scanf("%s",inputaddress);
push(&stack,inputaddress);
printf("入栈成功\n");
break;
case 2:
if (!isStackEmpty(&stack)) {
char *address = pop(&stack);
printf("出栈:%s\n", address);
}else{
printf("空\n");
}
break;
default:
printf("输入错误\n");
break;
}
}
return 0;
}
2.队列
队列是一种先进先出的线性数据结构,类似于现实生活中的排队场景。最早进入队列的元素将最先被移除,而新元素只能添加到队列末尾。
操作规则:
- 入队(Enqueue):在队尾添加元素
- 出队(Dequeue):移除队首元素
- 其他操作:获取队首元素(Peek)、判断队列是否为空(IsEmpty)等
C代码实现
#include <stdio.h>
#define MAX_ID_SIZE 2
#define MAX_QUEUE_SIZE 5
typedef struct {
int id;
char ID[MAX_ID_SIZE];
} User;
typedef struct {
User data[MAX_QUEUE_SIZE];
int front; //队列头位置
int rear; //队列尾位置
} Queue;
/*
初始化队列
初始化时,由于队列为空,队列头和尾位置都在0
*/
void initQueue(Queue *q) {
q->front = q->rear = 0;
}
/*
判断队列是否为空
当队列头位置和尾位置相同时,队列为空
*/
int isQueueEmpty(Queue *q) {
return q->front == q->rear;
}
/*
判断队列是否满
当队列尾位置+1等于队列头位置时,队列满
*/
int isQueueFull(Queue *q) {
return (q->rear + 1) % MAX_QUEUE_SIZE == q->front;
}
/*
入队
先判断队列是否满,然后存储数据到队列尾位置,队列尾位置+1
*/
int enqueue(Queue *q, User *s) {
if (isQueueFull(q)) {
return 0;
}
printf("id=%d, ID=%s ", s->id, s->ID);
q->data[q->rear] = *s;
q->rear = (q->rear + 1) % MAX_QUEUE_SIZE;
return 1;
}
/*
出队
先判断队列是否空,然后读取队列头的数据,队列头位置+1
*/
int dequeue(Queue *q, User *s) {
if (isQueueEmpty(q)) {
return 0;
}
*s = q->data[q->front];
printf("id=%d, ID=%s\n", s->id, s->ID);
q->front = (q->front + 1) % MAX_QUEUE_SIZE;
return 1;
}
int main() {
int id = 0;
User user;
int choice;
Queue q;
initQueue(&q);
while (1)
{
printf("1:入队\n");
printf("2:出队\n");
scanf("%d",&choice);
switch (choice)
{
case 1:
printf("请输入ID:");
user.id = id ++;
scanf("%s",user.ID);
if(enqueue(&q, &user) == 1)
printf("入队成功\n");
else
printf("入队失败,队满\n");
break;
case 2:
printf("出队:");
User s;
if (!dequeue(&q, &s)) {
printf("队空\n");
}
break;
default:
printf("输入错误\n");
break;
}
}
return 0;
}
1.链表
链表是一种常见的线性数据结构,由一系列节点组成,每个节点包含数据元素和一个指向下一个节点的指针(称为“后继指针”)。与数组不同,链表在内存中不是连续存储的,而是通过指针动态连接,这使得插入和删除操作更高效,但随机访问效率较低。链表的基本结构可表示为:
每个节点包含数据和指向下一个节点的指针。
核心操作包括:
- 插入:在指定位置添加新节点。
- 删除:移除指定节点。
- 搜索:查找特定元素。
应用场景
实现信息表的插入、查找、删除功能
C代码实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct User {
char name[50];
int score;
struct User *next;
} User;
// 链表头节点
User *head = NULL;
// 插入用户信息
void insertUser() {
User *newUser = (User *) malloc(sizeof(User));
printf("用户名:");
scanf("%s", newUser->name);
printf("成绩:");
scanf("%d", &newUser->score);
newUser->next = NULL;
/*插入到链表
判断链表头指针 head 是否为 NULL:
如果 head 为 NULL,说明链表为空,直接将 newUser 设置为链表头。
如果 head 不为 NULL,则遍历链表直到找到最后一个节点(即 next 指针为 NULL 的节点),然后将该节点的 next 指针指向 newUser。
*/
if (head == NULL) {
head = newUser;
}
else
{
User *temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newUser;
}
printf("用户信息插入成功!\n");
}
// 删除用户信息
void deleteUser() {
if (head == NULL) {
printf("链表为空,无法删除用户信息!\n");
return;
}
char name[50];
printf("请输入要删除的用户名:");
scanf("%s", name);
User *temp = head;
User *prev = NULL;
while (temp != NULL && strcmp(temp->name, name) != 0) {
prev = temp;
temp = temp->next;
}
if (temp == NULL) {
printf("未找到要删除的用户信息!\n");
return;
}
if (prev == NULL) {
head = temp->next;
} else {
prev->next = temp->next;
}
free(temp);
//释放空间
printf("用户信息删除成功!\n");
}
// 查找用户信息
void findUser() {
if (head == NULL) {
printf("链表为空,无法查找用户信息!\n");
return;
}
char name[50];
printf("请输入要查找的用户名:");
scanf("%s", name);
User *temp = head;
while (temp != NULL && strcmp(temp->name, name) != 0) {
temp = temp->next;
}
if (temp == NULL) {
printf("未找到要查找的用户信息!\n");
} else {
printf("用户名:%s,成绩:%d\n", temp->name, temp->score);
}
}
int main() {
int choice;
while (1) {
printf("请选择要执行的操作:\n");
printf("1. 插入用户信息\n");
printf("2. 删除用户信息\n");
printf("3. 查找用户信息\n");
printf("4. 退出程序\n");
printf("请输入操作编号:");
scanf("%d", &choice);
switch (choice) {
case 1:
insertUser();
break;
case 2:
deleteUser();
break;
case 3:
findUser();
break;
case 4:
exit(0);
default:
printf("输入的操作编号有误,请重新输入!\n");
break;
}
}
return 0;
}