数据结构-线性结构(链表、栈、队列)实现

公共头文件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);
}

总结

栈: 适用于需要后进先出的场景,如函数调用栈、表达式求值等。
队列: 适用于需要先进先出的场景,如任务调度、消息队列等。
链表: 适用于频繁插入和删除元素的场景,如链表实现的动态内存管理。
**顺序表:**一种以数组形式实现的线性结构,具有随机访问的特点。元素在内存中是连续存储的,支持快速的元素访问,但插入和删除操作需要移动多个元素。

相关推荐
海码0072 小时前
【Hot 100】94. 二叉树的中序遍历
数据结构·c++·算法·二叉树·hot100
Light603 小时前
探秘数据结构:构建高效算法的灵魂密码
数据结构·可视化·算法优化·性能分析·应用场景
qq_447429415 小时前
数据结构与算法:图论——并查集
数据结构·算法·图论
兮山与5 小时前
数据结构4.0
java·开发语言·数据结构
照海19Gin12 小时前
从括号匹配看栈:数据结构入门的实战与原理
数据结构
奔跑的乌龟_16 小时前
L3-040 人生就像一场旅行
数据结构·算法
旺仔老馒头.16 小时前
【数据结构】线性表--顺序表
c语言·数据结构·visual studio
一匹电信狗17 小时前
【数据结构】堆的完整实现
c语言·数据结构·c++·算法·leetcode·排序算法·visual studio
Le_ee20 小时前
数据结构6 · BinaryTree二叉树模板
数据结构·c++·算法