目录
栈
栈概念
顺序栈
链式栈(链表实现)
顺序栈和链式栈的区别是什么?
队列
队列概念
顺序队列
链式队列
双向链表
只能在一端进行插入和删除数据的线性表(称为栈),把能进行插入和删除的这一端叫栈顶,另一端成为栈底。实现栈可以用顺序表实现(顺序栈),也可以用链表实现(链式栈)。
先进后出: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;
}