《数据结构》栈,队列,双向链表

目录

栈概念

顺序栈

链式栈(链表实现)

顺序栈和链式栈的区别是什么?

队列

队列概念

顺序队列

链式队列

双向链表


栈概念

  • 什么是栈?

只能在一端进行插入和删除数据的线性表(称为栈),把能进行插入和删除的这一端叫栈顶,另一端成为栈底。实现栈可以用顺序表实现(顺序栈),也可以用链表实现(链式栈)

  • 栈的特点

先进后出:first in last out FILO

后进先出:last in first out LIFO

顺序栈

  • 逻辑结构:线性结构
  • 存储结构:顺序存储
  • 定义一个结构体描述顺序栈的信息
typedef  int   datatype_t;
typedef struct
{
    datatypde_t *data;	//保存栈的地址(数组)
	int  top;			//保存栈顶数据的下标
    int  len;			//栈的大小
}seqstack_t,*seqstack_p;
栈的常用操作
#include 
#include 

typedef int datatype_t;
typedef struct {
    datatype_t *data;   // 保存栈的地址(数组)
    int top;            // 保存栈顶数据的下标
    int len;            // 栈的大小
} seqstack_t, *seqstack_p;

// 1. 创建一个空栈
seqstack_p createStack(int size) {
    seqstack_p stack = (seqstack_p)malloc(sizeof(seqstack_t));
    if (stack == NULL) {
        printf("Failed to allocate memory for stack.\n");
        return NULL;
    }

    stack->data = (datatype_t*)malloc(size * sizeof(datatype_t));
    if (stack->data == NULL) {
        printf("Failed to allocate memory for stack data.\n");
        free(stack);
        return NULL;
    }

    stack->top = -1;
    stack->len = size;
    return stack;
}

// 2. 入栈
int push(seqstack_p stack, datatype_t value) {
    if (stack->top == stack->len - 1) {
        printf("Stack is full. Cannot push %d.\n", value);
        return 0;
    }
    stack->top++;
    stack->data[stack->top] = value;
    return 1;
}

// 3. 判断栈是否满
int isFull(seqstack_p stack) {
    return stack->top == stack->len - 1;
}

// 4. 出栈
int pop(seqstack_p stack, datatype_t *value) {
    if (stack->top == -1) {
        printf("Stack is empty. Cannot pop.\n");
        return 0;
    }

    *value = stack->data[stack->top];
    stack->top--;
    return 1;
}

// 5. 判断栈是否为空
int isEmpty(seqstack_p stack) {
    return stack->top == -1;
}

// 6. 求栈的长度
int stackLength(seqstack_p stack) {
    return stack->top + 1;
}

// 7. 获取栈顶的值
int getTop(seqstack_p stack, datatype_t *value) {
    if (stack->top == -1) {
        printf("Stack is empty. Cannot get top value.\n");
        return 0;
    }

    *value = stack->data[stack->top];
    return 1;
}

int main() {
    int size = 5;
    seqstack_p stack = createStack(size);
    if (stack == NULL) {
        return 1;
    }
    push(stack, 1);
    push(stack, 2);
    push(stack, 3);
    int topValue;
    if (getTop(stack, &topValue)) {
        printf("Top value: %d\n", topValue);
    }
    printf("Stack length: %d\n", stackLength(stack));
    while (!isEmpty(stack)) {
        int value;
        pop(stack, &value);
        printf("Pop value: %d\n", value);
    }
    free(stack->data);
    free(stack);
    return 0;
}

链式栈(链表实现)

  • 逻辑结构:线性结构
  • 存储结构:链式存储
  • 定义节点结构
typedef int datatype_t;
typedef struct node_t
{
	datatype_t data;		//数据
	struct node_t *next;	//节点
}linkstack_t,*linkstack_p;
  • 链式栈的操作
#include 
#include 

typedef int datatype_t;
typedef struct node_t {
    datatype_t data;
    struct node_t* next;
} linkstack_t, *linkstack_p;

// 1. 创建一个空的栈
linkstack_p createStack() {
    linkstack_p stack = (linkstack_p)malloc(sizeof(linkstack_t));
    if (stack == NULL) {
        printf("Failed to allocate memory for stack.\n");
        return NULL;
    }

    stack->next = NULL;
    return stack;
}

// 2. 入栈
void push(linkstack_p stack, datatype_t value) {
    linkstack_p newNode = (linkstack_p)malloc(sizeof(linkstack_t));
    if (newNode == NULL) {
        printf("Failed to allocate memory for new node.\n");
        return;
    }

    newNode->data = value;
    newNode->next = stack->next;
    stack->next = newNode;
}

// 3. 判断栈是否为空
int isEmpty(linkstack_p stack) {
    return stack->next == NULL;
}

// 4. 出栈
datatype_t pop(linkstack_p stack) {
    if (isEmpty(stack)) {
        printf("Stack is empty. Cannot pop.\n");
        return NULL;
    }

    linkstack_p temp = stack->next;
    datatype_t value = temp->data;
    stack->next = temp->next;
    free(temp);

    return value;
}

// 5. 清空栈
void clearStack(linkstack_p stack) {
    while (!isEmpty(stack)) {
        pop(stack);
    }
}

// 6. 求栈的长度
int stackLength(linkstack_p stack) {
    int count = 0;
    linkstack_p p = stack->next;
    while (p != NULL) {
        count++;
        p = p->next;
    }
    return count;
}

// 7. 获取栈顶的值
datatype_t getTop(linkstack_p stack) {
    if (isEmpty(stack)) {
        printf("Stack is empty. Cannot get top value.\n");
        return NULL;
    }

    return stack->next->data;
}

int main() {
    linkstack_p stack = createStack();
    push(stack, 1);
    push(stack, 2);
    push(stack, 3);
    printf("Stack length: %d\n", stackLength(stack));
    datatype_t topValue = getTop(stack);
    printf("Top value: %d\n", topValue);
    while (!isEmpty(stack)) {
        datatype_t value = pop(stack);
        printf("Pop value: %d\n", value);
    }
    clearStack(stack);
    free(stack);
    return 0;
}

顺序栈和链式栈的区别是什么?

(1)顺序栈的存储结构是顺序存储,链式栈的存储结构是链式存储

(2)顺序栈的长度受限制,而链栈不会

队列

队列概念

  • 什么是队列?

只允许在两端进行插入删除操作的线性表,在队尾插入,插入数据的这一端,被称为"队尾",删除的一端被称为"队头"。实现队列的方式有两种:顺序队列 链式队列

  • 队列特点

先进先出、后进后出 FIFO LILO

顺序队列

  • 逻辑结构:线性结构
  • 存储结构:顺序结构
  • 定义顺序队列的结构体
#define N 6
typedef int  datatype_t;
typedef struct 
{
    datatype_t  data[N];//顺序表定义的队
    int front;			//队头下标
    int  rear;			//队尾下标
}sequeue_t;  
顺序队列基础操作
#include 
#include 

#define N 6
typedef int datatype_t;
typedef struct {
    datatype_t data[N]; // 顺序表定义的队
    int front; 			// 队头下标
    int rear; 			// 队尾下标
} sequeue_t;

// 1. 创建一个空的顺序队列
sequeue_t* createQueue() {
    sequeue_t* queue = (sequeue_t*)malloc(sizeof(sequeue_t));
    if (queue == NULL) {
        printf("Failed to allocate memory for queue.\n");
        return NULL;
    }
    queue->front = 0;
    queue->rear = 0;
    return queue;
}

// 2. 入队
void enqueue(sequeue_t* queue, datatype_t value) {
    if ((queue->rear + 1) % N == queue->front) {	
        printf("Queue is full. Cannot enqueue.\n");
        return;
    }

    queue->data[queue->rear] = value;
    queue->rear = (queue->rear + 1) % N;
}

// 3. 判断队列是否满
int isFull(sequeue_t* queue) {
    return (queue->rear + 1) % N == queue->front;
}

// 4. 出队
datatype_t dequeue(sequeue_t* queue) {
    if (queue->front == queue->rear) {
        printf("Queue is empty. Cannot dequeue.\n");
        return NULL;
    }

    datatype_t value = queue->data[queue->front];
    queue->front = (queue->front + 1) % N;
    return value;
}

// 5. 判断队列是否为空
int isEmpty(sequeue_t* queue) {
    return queue->front == queue->rear;
}

// 6. 计算队列的长度
int queueLength(sequeue_t* queue) {
    return (queue->rear - queue->front + N) % N;
}

// 7. 清空队列
void clearQueue(sequeue_t* queue) {
    queue->front = queue->rear;
}

int main() {
    sequeue_t* queue = createQueue();

    enqueue(queue, 1);
    enqueue(queue, 2);
    enqueue(queue, 3);

    printf("Queue length: %d\n", queueLength(queue));

    while (!isEmpty(queue)) {
        datatype_t value = dequeue(queue);
        printf("Dequeued value: %d\n", value);
    }

    if (isEmpty(queue)) {
        printf("Queue is empty.\n");
    }

    clearQueue(queue);
    free(queue);

    return 0;
}

链式队列

  • 逻辑结构:线性结构
  • 存储结构:链式存储
  • 定义节点结构体
typedef   int  datatype;
typedef struct  node_t
{
	datatype data;	//数据域
	struct node_t *next;
}link_t;

//保存头尾节点地址结构体:
typedef struct
{
	link_t *front;	//头指针
	link_t *rear;	//尾指针
	int len;		//保存队列的长度(个数)
}queue_t;
  • 链式队列的操作
#include 
#include 

typedef int datatype;

typedef struct node_t {
    datatype data;          // 数据域
    struct node_t *next;    // 指向下一个节点的指针
} link_t;

typedef struct {
    link_t *front;          // 头指针
    link_t *rear;           // 尾指针
    int len;                // 队列长度
} queue_t;

// 创建空队列
void createQueue(queue_t *queue) {
    queue->front = NULL;
    queue->rear = NULL;
    queue->len = 0;
}

// 入队
void enqueue(queue_t *queue, datatype data) {
    link_t *newNode = (link_t*)malloc(sizeof(link_t));
    newNode->data = data;
    newNode->next = NULL;

    if (queue->rear == NULL) {
        queue->front = newNode;
        queue->rear = newNode;
    } else {
        queue->rear->next = newNode;
        queue->rear = newNode;
    }

    queue->len++;
}

// 出队
datatype dequeue(queue_t *queue) {
    if (queue->front == NULL) {
        printf("Queue is empty.\n");
        return -1; // 用-1表示队列为空的情况
    }

    link_t *temp = queue->front;
    datatype data = temp->data;

    queue->front = queue->front->next;
    free(temp);

    if (queue->front == NULL) {
        queue->rear = NULL;
    }

    queue->len--;

    return data;
}

// 判断队列是否为空
int isQueueEmpty(queue_t *queue) {
    return (queue->front == NULL);
}

// 清空队列
void clearQueue(queue_t *queue) {
    while (queue->front != NULL) {
        link_t *temp = queue->front;
        queue->front = queue->front->next;
        free(temp);
    }

    queue->rear = NULL;
    queue->len = 0;
}

// 计算队列的长度
int getQueueLength(queue_t *queue) {
    return queue->len;
}

int main() {
    queue_t queue;
    createQueue(&queue);

    // 测试入队
    enqueue(&queue, 10);
    enqueue(&queue, 20);
    enqueue(&queue, 30);

    // 测试出队
    printf("Dequeued element: %d\n", dequeue(&queue));

    // 测试判断队列是否为空
    if (isQueueEmpty(&queue)) {
        printf("Queue is empty.\n");
    } else {
        printf("Queue is not empty.\n");
    }

    // 测试清空队列
    clearQueue(&queue);

    // 测试计算队列的长度
    printf("Queue length: %d\n", getQueueLength(&queue));

    return 0;
}

双向链表

  • 逻辑结构:线性结构
  • 存储结构:链式存储
  • 保存数据的结构体
typede int  datatype;

typedef struct node_t
{
	datatype data;			//数据域
	struct node_t *prior;	//保存前一个节点的地址
	struct node_t *next;	//保存后一个节点地址
}link_t;

//用于保存双向链表信息的结构体:
typedef struct
{
    link_t *head;	//保存头节点地址
	link_t *tail;	//保存尾节点的地址
	int len;		//保存双向链表的长度
}double_t;
  • 双向链表的操作
#include 
#include 

typedef int datatype;

typedef struct node_t {
    datatype data;          // 数据域
    struct node_t *prior;   // 前一个节点的指针
    struct node_t *next;    // 后一个节点的指针
} link_t;

typedef struct {
    link_t *head;           // 头节点的指针
    link_t *tail;           // 尾节点的指针
    int len;                // 双向链表的长度
} double_t;

// 创建一个空的双向链表
void createDoubleList(double_t *list) {
    list->head = NULL;
    list->tail = NULL;
    list->len = 0;
}

// 向双向链表的指定位置插入数据
void insertData(double_t *list, int pos, datatype data) {
    if (pos < 0 || pos > list->len) {
        printf("Invalid position.\n");
        return;
    }

    link_t *newNode = (link_t*)malloc(sizeof(link_t));
    newNode->data = data;

    if (pos == 0) {
        newNode->prior = NULL;
        newNode->next = list->head;

        if (list->head != NULL) {
            list->head->prior = newNode;
        }

        list->head = newNode;

        if (list->tail == NULL) {
            list->tail = newNode;
        }
    } else if (pos == list->len) {
        newNode->prior = list->tail;
        newNode->next = NULL;

        if (list->tail != NULL) {
            list->tail->next = newNode;
        }

        list->tail = newNode;
    } else {
        link_t *current = list->head;
        int i = 0;

        while (i < pos) {
            current = current->next;
            i++;
        }

        newNode->prior = current->prior;
        newNode->next = current;

        current->prior->next = newNode;
        current->prior = newNode;
    }

    list->len++;
}

// 遍历双向链表
void traverseList(double_t *list) {
    link_t *current = list->head;

    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }

    printf("\n");
}

// 删除双向链表指定位置的数据
void deleteData(double_t *list, int pos) {
    if (pos < 0 || pos >= list->len) {
        printf("Invalid position.\n");
        return;
    }

    link_t *current = list->head;

    if (pos == 0) {
        list->head = current->next;

        if (list->head != NULL) {
            list->head->prior = NULL;
        }

        if (list->tail == current) {
            list->tail = NULL;
        }
    } else if (pos == list->len - 1) {
        current = list->tail;
        list->tail = current->prior;
        list->tail->next = NULL;
    } else {
        int i = 0;

        while (i < pos) {
            current = current->next;
            i++;
        }

        current->prior->next = current->next;
        current->next->prior = current->prior;
    }

    free(current);
    list->len--;
}

// 判断双向链表是否为空
int isDoubleListEmpty(double_t *list) {
    return (list->head == NULL);
}

// 求双向链表的长度
int getDoubleListLength(double_t *list) {
    return list->len;
}

// 查找指定数据出现的位置
int findDataPosition(double_t *list, datatype data) {
    link_t *current = list->head;
    int pos = 0;

    while (current != NULL) {
        if (current->data == data) {
            return pos;
        }

        current = current->next;
        pos++;
    }

    return -1; // 表示未找到数据
}

// 修改指定位置的数据
void modifyData(double_t *list, int pos, datatype newData) {
    if (pos < 0 || pos >= list->len) {
        printf("Invalid position.\n");
        return;
    }

    link_t *current = list->head;
    int i = 0;

    while (i < pos) {
        current = current->next;
        i++;
    }

    current->data = newData;
}

// 删除双向链表中的指定数据
void deleteDataByValue(double_t *list, datatype data) {
    int pos = findDataPosition(list, data);

    if (pos != -1) {
        deleteData(list, pos);
    } else {
        printf("Data not found.\n");
    }
}

// 转置双向链表
void reverseList(double_t *list) {
    if (list->len <= 1) {
        return;
    }

    link_t *current = list->head;
    link_t *temp = NULL;

    while (current != NULL) {
        temp = current->prior;
        current->prior = current->next;
        current->next = temp;

        current = current->prior;
    }

    temp = list->head;
    list->head = list->tail;
    list->tail = temp;
}

int main() {
    double_t list;
    createDoubleList(&list);

    // 测试向双向链表的指定位置插入数据
    insertData(&list, 0, 10);
    insertData(&list, 1, 20);
    insertData(&list, 2, 30);

    // 测试遍历双向链表
    traverseList(&list);

    // 测试删除双向链表指定位置的数据
    deleteData(&list, 1);

    // 测试判断双向链表是否为空
    if (isDoubleListEmpty(&list)) {
        printf("Double linked list is empty.\n");
    } else {
        printf("Double linked list is not empty.\n");
    }

    // 测试求双向链表的长度
    printf("Double linked list length: %d\n", getDoubleListLength(&list));

    // 测试查找指定数据出现的位置
    int pos = findDataPosition(&list, 20);
    if (pos != -1) {
        printf("Data found at position: %d\n", pos);
    } else {
        printf("Data not found.\n");
    }

    // 测试修改指定位置的数据
    modifyData(&list, 0, 50);

    // 测试删除双向链表中的指定数据
    deleteDataByValue(&list, 30);

    // 测试转置双向链表
    reverseList(&list);

    // 再次遍历双向链表
    traverseList(&list);

    return 0;
}

你可能感兴趣的:(复习知识,算法,数据结构,链表)