反转链表——C语言经典单链表题目

首先,把oj题目的链接放在这,大家可以先去练习一下,再来看解析。

反转链表——力扣


题目:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

 


现在让我们来看一下解决代码,先看一下我写的代码。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* reverseList(struct ListNode* head){

    struct ListNode* tmp = NULL;//一个新的链表,来存储翻转时的链表。
    struct ListNode* newhead = head;//一般我们都会创建一个新的指针来指向链表。
    while(newhead)
    {
        struct ListNode* nexthead = newhead->next;//让nexthead指向下一个节点。
        newhead->next = tmp;//让下一个节点等于tmp,第一次相当于将第一个节点的next=NULL,第二次以后就相当于将newhead->next链接到翻转后的链表,然后依次链接。
        tmp = newhead;//让tmp来接收翻转后的链表
        newhead = nexthead;//再让newhead进行下一个节点的翻转。
    }
    return tmp;
}

        这是一种依次翻转,然后链接的方法。

        其空间复杂度是:O(1);

            时间复杂度是:O(N)。


现在让我们来看一下它的详细讲解,其实我在代码旁边的注释已经十分清楚了,但是让我们来看一下图,可以更清晰的理解它。 

首先:第一次翻转

这个时候tmp的具体指向就是:1-NULL。

 然后,就是不断的翻转,存储,最后返回。

 后面就是不断的重复这个过程。

 


当然它还有其他的方法,具体的可以看力扣或者其他的讲解,我这边就放一下代码。

struct ListNode* reverseList(struct ListNode* head) {
    if (head == NULL || head->next == NULL) {
        return head;
    }
    struct ListNode* newHead = reverseList(head->next);
    head->next->next = head;
    head->next = NULL;
    return newHead;
}

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-by-leetcode-solution-d1k2/
来源:力扣(LeetCode)

### C语言数据结构中的常见算法练习题 以下是几个常见的基于C语言数据结构相关算法练习题: #### 题目一:单链表反转 实现一个函数来反转给定的单链表。 输入是一个指向头节点的指针,返回值是新的头节点。 ```c struct Node { int data; struct Node* next; }; struct Node* reverseList(struct Node* head) { struct Node* prev = NULL; struct Node* current = head; struct Node* nextNode = NULL; while (current != NULL) { nextNode = current->next; // Store the next node current->next = prev; // Reverse the link prev = current; // Move to the next pair of nodes current = nextNode; } return prev; // New head is at 'prev' } ``` 此题目可以帮助理解如何操作链表以及掌握指针的操作[^1]。 --- #### 题目二:栈的应用——括号匹配 编写一个程序验证字符串中的括号是否正确配对。可以扩展到多种类型的括号 `{}`, `[]`, 和 `()` 的情况。 ```c #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 char stack[MAX_SIZE]; int top = -1; void push(char c) { if (top >= MAX_SIZE - 1) { printf("Stack Overflow\n"); exit(1); } stack[++top] = c; } char pop() { if (top < 0) { printf("Stack Underflow\n"); exit(1); } return stack[top--]; } int main() { char str[100], ch; int i, flag = 1; printf("Enter a string with brackets: "); scanf("%s", str); for (i = 0; str[i]; ++i) { ch = str[i]; if (ch == '(' || ch == '{' || ch == '[') { push(ch); // Push opening bracket onto stack } else if (ch == ')' || ch == '}' || ch == ']') { if (top == -1) { // Stack empty but closing bracket found flag = 0; break; } switch (pop()) { case '(': if (ch != ')') flag = 0; break; case '{': if (ch != '}') flag = 0; break; case '[': if (ch != ']') flag = 0; break; } } } if (flag && top == -1) printf("Balanced Brackets.\n"); else printf("Unbalanced Brackets.\n"); return 0; } ``` 该题目展示了栈这种数据结构的实际应用之一,帮助熟悉字符处理逻辑[^2]。 --- #### 题目三:队列模拟银行排队系统 设计实现一个简单的银行排队管理系统,支持客户进入队伍、离开队伍等功能。 ```c #include <stdio.h> #include <stdlib.h> typedef struct Queue { int front, rear, size; unsigned capacity; int* array; } Queue; Queue* createQueue(unsigned capacity) { Queue* queue = (Queue*) malloc(sizeof(Queue)); queue->capacity = capacity; queue->front = queue->size = 0; queue->rear = capacity - 1; queue->array = (int*) malloc(queue->capacity * sizeof(int)); return queue; } int isEmpty(Queue* queue) { return queue->size == 0; } int isFull(Queue* queue) { return queue->size == queue->capacity; } void enqueue(Queue* queue, int item) { if (isFull(queue)) { printf("Overflow! Cannot add more items."); return; } queue->rear = (queue->rear + 1) % queue->capacity; queue->array[queue->rear] = item; queue->size++; } // Similar dequeue function can be implemented here. int main() { Queue* q = createQueue(100); enqueue(q, 10); enqueue(q, 20); return 0; } ``` 通过这个例子,学习者能够深入理解循环队列的工作原理及其边界条件管理方法[^3]。 --- #### 题目四:树的遍历(前序、中序、后序) 对于一棵二叉树,分别写出其前序、中序和后序遍历的方法。 ```c struct TreeNode { int val; struct TreeNode* left; struct TreeNode* right; }; void preorderTraversal(struct TreeNode* root) { if (!root) return; printf("%d ", root->val); preorderTraversal(root->left); preorderTraversal(root->right); } void inorderTraversal(struct TreeNode* root) { if (!root) return; inorderTraversal(root->left); printf("%d ", root->val); inorderTraversal(root->right); } void postorderTraversal(struct TreeNode* root) { if (!root) return; postorderTraversal(root->left); postorderTraversal(root->right); printf("%d ", root->val); } ``` 这些基本的递归遍历方式有助于巩固对递归的理解以及二叉树这一重要数据结构的认识[^4]。 --- #### 题目五:哈希表冲突解决策略 创建一个简单的哈希表,演示两种不同的冲突解决方案:线性探测法与拉链法。 ```c const int TABLE_SIZE = 7; // Linear Probing Example... int hashFunction(int key) { return key % TABLE_SIZE; } void insertLinearProbing(int table[], int key) { int index = hashFunction(key); while (table[index] != 0) { index = (index + 1) % TABLE_SIZE; // Resolve collision by linear probing. } table[index] = key; } // Separate Chaining Example... typedef struct HashNode { int key; struct HashNode* next; } HashNode; HashNode* hashtable[TABLE_SIZE] = {NULL}; void insertSeparateChaining(int key) { int index = hashFunction(key); HashNode* newNode = (HashNode*)malloc(sizeof(HashNode)); newNode->key = key; newNode->next = hashtable[index]; hashtable[index] = newNode; } ``` 这道习题可以让学生探索不同场景下适合使用的具体技术手段[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值