公共头文件common.h
cpp
#define TRUE 1
#define FALSE 0
// 定义节点数据类型
#define DATA_TYPE int
单链表C语言实现
SingleList.h
cpp
#pragma once
#include "common.h"
typedef struct Node
{
DATA_TYPE data;
struct Node *next;
} Node;
Node *initList();
void headInsert(Node *L, DATA_TYPE data);
void tailInsert(Node *L, DATA_TYPE data);
int contains(Node *L, DATA_TYPE data);
int list_delete(Node *L, DATA_TYPE data);
void printList(Node *L);
void test_SingleList();
int size(Node *L);
SingleList.c
cpp
#include <stdio.h>
#include <stdlib.h>
#include "SingleList.h"
// 头结点 链表的第一个节点 通常不存储实际的数据元素 用于简化操作、管理链表
// 首节点 头结点之后的第一个节点 链表中第一个存储实际数据的节点
Node *initList()
{
Node *head = malloc(sizeof(Node));
head->data = 0;
head->next = NULL;
return head;
}
// 头插法
void headInsert(Node *L, DATA_TYPE data)
{
Node *node = malloc(sizeof(Node));
node->data = data;
node->next = L->next;
L->next = node;
L->data++;
}
// 尾插法 需要遍历整个链表找到尾结点
void tailInsert(Node *L, DATA_TYPE data)
{
Node *p_tmp = L;
while (p_tmp->next != NULL) // 找到尾结点
{
p_tmp = p_tmp->next;
}
Node *node = malloc(sizeof(Node));
node->data = data;
node->next = NULL;
p_tmp->next = node;
L->data++;
}
int contains(Node *L, DATA_TYPE data)
{
Node *p_tmp = L;
while (p_tmp->next != NULL && p_tmp->next->data != data)
{
p_tmp = p_tmp->next;
}
if (p_tmp->next == NULL)
{
return FALSE;
}
return TRUE;
}
int list_delete(Node *L, DATA_TYPE data)
{
Node *preNode = L;
Node *node = L->next;
while (node)
{
if (node->data == data)
{
preNode->next = node->next; // 删除节点
free(node); // 释放节点占用内存
L->data--; // 链表节点数减一
return TRUE;
}
preNode = node; // 保存前一个节点指针
node = node->next;
}
return FALSE;
}
void printList(Node *L)
{
Node *node = L->next;
while (node)
{
printf("%d -> ", node->data);
node = node->next;
}
printf("NULL\n");
}
int size(Node *L)
{
return L->data;
}
void test_SingleList()
{
Node *head = initList();
headInsert(head, 1);
headInsert(head, 2);
headInsert(head, 3);
tailInsert(head, 4);
tailInsert(head, 5);
tailInsert(head, 6);
printf("contains: %d\n", contains(head, 1));
printf("contains: %d\n", contains(head, 6));
printf("size: %d\n", size(head));
printList(head);
printf("\n");
list_delete(head, 4);
list_delete(head, 6);
printf("size: %d\n", size(head));
printList(head);
}
单链表Java实现
java
public class SingleList {
private int size; // 保存节点个数
private Node head;
public SingleList() {
head = new Node(0); // 头结点数据域保存节点个数 与 size等价
}
public void headInsert(int data) {
Node node = new Node(data, head.next);
head.next = node;
head.data++;
size++;
}
public void tailInsert(int data) {
Node tmp = head;
while (tmp.next != null) { // 找到尾结点
tmp = tmp.next;
}
Node node = new Node(data);
tmp.next = node;
size++;
head.data++;
}
public boolean contains(int data) {
Node tmp = head;
while (tmp.next != null && tmp.data != data) {
tmp = tmp.next;
}
if (tmp.next == null) {
return false;
}
return true;
}
public boolean delete(int data) { // Java LinkedList包含节点前后引用
Node preNode = head; // 保存删除节点的前一个节点
Node node = head.next;
while (node != null) {
if (node.data == data) { // 要删除的节点
preNode.next = node.next;
size--;
head.data--;
return true;
}
preNode = node;
node = node.next;
}
return false;
}
public void printList() {
Node node = head.next;
while (node != null) {
System.out.print(node.data + " -> ");
node = node.next;
}
}
public int size() {
// return size;
return head.data;
}
/**
* 单链表节点类
*/
private static class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
}
public Node(int data, Node next) {
this.data = data;
this.next = next;
}
}
public static void main(String[] args) {
SingleList list = new SingleList();
list.headInsert(1);
list.headInsert(2);
list.headInsert(3);
list.tailInsert(4);
list.tailInsert(5);
list.tailInsert(6);
System.out.println(list.contains(1));
System.out.println(list.contains(6));
System.out.println("size: " + list.size());
list.printList();
System.out.println();
list.delete(4);
list.delete(6);
System.out.println("size: " + list.size());
list.printList();
}
}
循环单链表
LoopSingleList.h
cpp
#pragma once
#include "common.h"
typedef struct Node
{
DATA_TYPE data;
struct Node *next;
} Node;
Node *initList();
void headInsert(Node *L, DATA_TYPE data);
void tailInsert(Node *L, DATA_TYPE data);
int list_delete(Node *L, DATA_TYPE data);
void printList(Node *L);
int size(Node *L);
void test_loop_singleList();
LoopSingleList.c
cpp
#include <stdio.h>
#include <stdlib.h>
#include "LoopSingleList.h"
Node *initList()
{
Node *head = malloc(sizeof(Node));
head->data = 0;
head->next = head;
return head;
}
void headInsert(Node *L, DATA_TYPE data)
{
Node *node = malloc(sizeof(Node));
node->data = data;
node->next = L->next;
L->next = node;
L->data++;
}
void tailInsert(Node *L, DATA_TYPE data)
{
Node *node = malloc(sizeof(Node));
node->data = data;
Node *head = L;
while (head->next != L)
{
head = head->next;
}
node->next = L;
head->next = node;
L->data++;
}
int list_delete(Node *L, DATA_TYPE data)
{
Node *preNode = L;
Node *node = L->next;
while (node != L)
{
if (node->data == data)
{
preNode->next = node->next;
free(node);
L->data--;
return TRUE;
}
preNode = node;
node = node->next;
}
return FALSE;
}
void printList(Node *L)
{
Node *node = L->next;
while (node != L)
{
printf("%d -> ", node->data);
node = node->next;
}
printf("(首节点)%d", node->next->data);
}
int size(Node *L)
{
return L->data;
}
void test_loop_singleList()
{
Node *head = initList();
headInsert(head, 1);
headInsert(head, 2);
headInsert(head, 3);
tailInsert(head, 4);
tailInsert(head, 5);
tailInsert(head, 6);
printf("size: %d\n", size(head));
printList(head);
printf("\n");
list_delete(head, 4);
list_delete(head, 6);
printf("size: %d\n", size(head));
printList(head);
}
双链表
DoubleList.h
cpp
#include "common.h"
typedef struct Node
{
DATA_TYPE data;
struct Node *pre;
struct Node *next;
} Node;
Node *initList();
void headInsert(Node *L, DATA_TYPE data);
void tailInsert(Node *L, DATA_TYPE data);
int list_delete(Node *L, DATA_TYPE data);
void printList(Node *L);
int size(Node *L);
void test_double_list();
DoubleList.c
cpp
#include <stdio.h>
#include <stdlib.h>
#include "DoubleList.h"
Node *initList()
{
Node *head = malloc(sizeof(Node));
head->data = 0;
head->pre = NULL;
head->next = NULL;
return head;
}
void headInsert(Node *L, DATA_TYPE data)
{
Node *node = malloc(sizeof(Node));
node->data = data;
node->pre = L;
node->next = L->next;
if (L->next)
{
L->next->pre = node;
L->next = node;
}
else // 首次插入 L->next=NULL
{
L->next = node;
}
L->data++;
}
void tailInsert(Node *L, DATA_TYPE data)
{
Node *tail = L;
while (tail->next)
{
tail = tail->next;
}
Node *node = malloc(sizeof(Node));
node->data = data;
node->pre = tail;
node->next = tail->next; // NULL
tail->next = node;
L->data++;
}
int list_delete(Node *L, DATA_TYPE data)
{
Node *head = L->next;
while (head)
{
if (head->data == data)
{
if (head->next) // 如果不是尾结点
{
head->next->pre = head->pre;
}
head->pre->next = head->next;
free(head);
L->data--;
return TRUE;
}
head = head->next;
}
return FALSE;
}
void printList(Node *L)
{
Node *node = L->next;
while (node)
{
printf("%d -> ", node->data);
node = node->next;
}
printf("NULL\n");
}
int size(Node *L)
{
return L->data;
}
void test_double_list()
{
Node *head = initList();
headInsert(head, 1);
headInsert(head, 2);
headInsert(head, 3);
tailInsert(head, 4);
tailInsert(head, 5);
tailInsert(head, 6);
printf("size: %d\n", size(head));
printList(head);
printf("\n");
list_delete(head, 3); // 首节点
list_delete(head, 4); // 中间节点
list_delete(head, 6); // 尾结点
printf("size: %d\n", size(head));
printList(head);
}
循环双链表
LoopDoubleList.c
cpp
#include <stdio.h>
#include <stdlib.h>
#include "DoubleList.h"
Node *initList()
{
Node *head = malloc(sizeof(Node));
head->data = 0;
head->pre = head;
head->next = head;
return head;
}
void headInsert(Node *L, DATA_TYPE data)
{
Node *node = malloc(sizeof(Node));
node->data = data;
node->pre = L;
node->next = L->next;
L->next->pre = node;
L->next = node;
L->data++;
}
void tailInsert(Node *L, DATA_TYPE data)
{
Node *tail = L;
while (tail->next != L)
{
tail = tail->next;
}
Node *node = malloc(sizeof(Node));
node->data = data;
node->pre = tail;
node->next = tail->next;
tail->next = node;
L->data++;
}
int list_delete(Node *L, DATA_TYPE data)
{
Node *head = L->next;
while (head != L)
{
if (head->data == data)
{
head->next->pre = head->pre;
head->pre->next = head->next;
free(head);
L->data--;
return TRUE;
}
head = head->next;
}
return FALSE;
}
void printList(Node *L)
{
Node *node = L->next;
while (node != L)
{
printf("%d -> ", node->data);
node = node->next;
}
printf("NULL\n");
}
int size(Node *L)
{
return L->data;
}
void test_double_list()
{
Node *head = initList();
headInsert(head, 1);
headInsert(head, 2);
headInsert(head, 3);
tailInsert(head, 4);
tailInsert(head, 5);
tailInsert(head, 6);
printf("size: %d\n", size(head));
printList(head);
list_delete(head, 3); // 首节点
list_delete(head, 4); // 中间节点
list_delete(head, 6); // 尾结点
printf("size: %d\n", size(head));
printList(head);
}
栈-链表实现
ListStack.h
cpp
#include "common.h"
typedef struct Node
{
DATA_TYPE data;
struct Node *next;
} Node;
Node *initStack();
void push(Node *L, DATA_TYPE data);
DATA_TYPE pop(Node *L);
int is_empty(Node *L);
void printStack(Node *L);
void test_List_Stack();
ListStack.c
cpp
#include <stdio.h>
#include <stdlib.h>
#include "listStack.h"
Node *initStack()
{
Node *head = malloc(sizeof(Node));
head->data = 0;
head->next = NULL;
return head;
}
void push(Node *L, DATA_TYPE data)
{
Node *node = malloc(sizeof(Node));
node->data = data;
node->next = L->next;
L->next = node;
L->data++;
}
DATA_TYPE pop(Node *L)
{
if (L->next)
{
Node *node = L->next;
DATA_TYPE data = node->data;
L->next = node->next;
free(node); // 释放首节点内存
L->data--;
return data;
}
return 0;
}
int is_empty(Node *L)
{
return L->data == 0;
}
void printStack(Node *L)
{
Node *head = L->next;
while (head)
{
printf("%d -> ", head->data);
head = head->next;
}
printf("NULL\n");
}
void test_List_Stack()
{
Node *stack = initStack();
printf("is_empty: %d\n", is_empty(stack));
push(stack, 1);
push(stack, 2);
push(stack, 3);
push(stack, 4);
printf("is_empty: %d\n", is_empty(stack));
printStack(stack);
pop(stack);
printStack(stack);
}
栈-数组实现
ArrayStack.h
cpp
#include "common.h"
void initStack();
void push(DATA_TYPE data);
DATA_TYPE pop();
DATA_TYPE top();
int is_empty();
void printStack();
void destroy_stack();
void test_Array_Stack();
ArrayStack.c
cpp
#include <stdio.h>
#include <stdlib.h>
#include "ArrayStack.h"
static size_t size; // 栈大小
static DATA_TYPE *stack; // 数组表示
static int index = -1; // 栈顶指针
void initStack(size_t stack_size)
{
size = stack_size;
stack = malloc(sizeof(DATA_TYPE) * size);
}
void push(DATA_TYPE data)
{
stack[++index] = data;
}
DATA_TYPE pop()
{
if (is_empty())
{
perror("空栈...\n");
exit(1);
}
return stack[index--];
}
DATA_TYPE top()
{
return stack[index];
}
int is_empty()
{
return index == -1;
}
void printStack()
{
for (int i = index; i >= 0; i--)
{
printf("%d ", stack[i]);
}
printf("\n");
}
void destroy_stack()
{
size = 0;
free(stack);
stack = NULL;
}
void test_Array_Stack()
{
initStack(10);
printf("is_empty: %d\n", is_empty());
push(1);
push(2);
push(3);
push(4);
printf("is_empty: %d\n", is_empty());
printStack();
printf("pop: %d\n", pop());
printf("top: %d\n", top());
printStack();
destroy_stack();
}
队列-双链表实现
ListQueue.h
cpp
#pragma once
#include "common.h"
typedef struct Node
{
DATA_TYPE data;
struct Node *pre;
struct Node *next;
} Node;
Node *initQueue();
void enQueue(Node *L, DATA_TYPE data);
void deQueue(Node *L);
void printQueue(Node *L);
void test_List_Queue();
ListQueue.c
cpp
#include <stdio.h>
#include <stdlib.h>
#include "ListQueue.h"
Node *initQueue()
{
Node *head = malloc(sizeof(Node));
head->data = 0;
head->pre = NULL;
head->next = NULL;
return head;
}
void enQueue(Node *L, DATA_TYPE data)
{
Node *head = L;
while (head->next)
{
head = head->next;
}
Node *node = malloc(sizeof(Node));
node->data = data;
node->pre = head;
node->next = head->next;
head->next = node;
L->data++;
}
void deQueue(Node *L)
{
Node *node = L->next;
L->next = node->next;
node->next->pre = L;
free(node);
L->data--;
}
void printQueue(Node *L)
{
Node *node = L;
while (node->next)
{
printf("%d <- ", node->next->data);
node = node->next;
}
printf("NULL\n");
}
void test_List_Queue()
{
Node *head = initQueue();
enQueue(head, 1);
enQueue(head, 2);
enQueue(head, 3);
enQueue(head, 4);
printQueue(head);
deQueue(head);
deQueue(head);
printQueue(head);
}
循环队列
ArrayCircularQueue.h
cpp
#include <stdlib.h>
#include "common.h"
typedef struct Queue
{
DATA_TYPE *data;
int front;
int rear;
} Queue;
Queue *initQueue(size_t size);
void enQueue(Queue *Q, DATA_TYPE value);
DATA_TYPE deQueue(Queue *Q);
int isFull(Queue* Q);
int isEmpty(Queue* Q);
void printQueue(Queue *Q);
void test_Array_Queue();
ArrayCircularQueue.c
cpp
#include <stdio.h>
#include <stdlib.h>
#include "ArrayCircularQueue.h"
/**
* 当普通队列的尾指针达到存储空间的末尾时,即使队列前方仍有空位,也无法继续存储新元素,这就是假溢出现象。
* 循环队列通过将存储空间视为环状来解决这一问题,使得当队尾指针到达末尾时,可以循环回到存储空间的开头继续存储元素。
*/
static size_t queue_size = -1;
Queue *initQueue(size_t size)
{
Queue *Q = malloc(sizeof(Queue));
queue_size = size;
Q->data = malloc(sizeof(DATA_TYPE) * size);
Q->front = Q->rear = 0;
return Q;
}
void enQueue(Queue *Q, DATA_TYPE value)
{
if (isFull(Q))
return;
Q->data[Q->rear] = value;
Q->rear = (Q->rear + 1) % queue_size;
}
DATA_TYPE deQueue(Queue *Q)
{
if (isEmpty(Q))
{
perror("空队列...");
exit(1);
}
DATA_TYPE val = Q->data[Q->front];
Q->front = (Q->front + 1) % queue_size;
return val;
}
int isFull(Queue *Q)
{
return (Q->rear + 1) % queue_size == Q->front;
}
int isEmpty(Queue *Q)
{
return Q->front == Q->rear; // 初始化时 队列为空
}
void printQueue(Queue *Q)
{
// 获取队列长度:队列中有多少个元素
int len = (Q->rear - Q->front + queue_size) % queue_size;
int index = Q->front;
for (int i = 0; i < len; i++)
{
printf("%d <- ", Q->data[index]);
index = (index + 1) % queue_size;
}
printf("NULL\n");
}
void test_Array_Queue()
{
Queue *Q = initQueue(5);
enQueue(Q, 1);
enQueue(Q, 2);
enQueue(Q, 3);
enQueue(Q, 4);
printf("isFull: %d\n", isFull(Q));
enQueue(Q, 4);
printf("isFull: %d\n", isFull(Q));
printQueue(Q);
deQueue(Q);
deQueue(Q);
printQueue(Q);
}
总结
栈: 适用于需要后进先出的场景,如函数调用栈、表达式求值等。
队列: 适用于需要先进先出的场景,如任务调度、消息队列等。
链表: 适用于频繁插入和删除元素的场景,如链表实现的动态内存管理。
**顺序表:**一种以数组形式实现的线性结构,具有随机访问的特点。元素在内存中是连续存储的,支持快速的元素访问,但插入和删除操作需要移动多个元素。