• 链表OJ


    GDUFE 

    在期末前再刷一次链表题  ~

    203. 移除链表元素 - 力扣(LeetCode)

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. struct ListNode* removeElements(struct ListNode* head, int val) {
    9. struct ListNode* cur = head;
    10. struct ListNode*prev = NULL;
    11. while(cur){
    12. if(cur->val == val){
    13. if(cur==head){//头删
    14. cur=head->next;
    15. free(head);
    16. head= cur;
    17. }else{
    18. prev->next = cur->next;
    19. free(cur);
    20. cur = prev->next;
    21. }
    22. }
    23. else{
    24. //找到val值对应的地址(遍历链表)
    25. prev = cur;
    26. cur=cur->next;
    27. }
    28. }
    29. return head;
    30. }

    206. 反转链表 - 力扣(LeetCode)

    1. struct ListNode* reverseList(struct ListNode* head) {
    2. //记录前中后三个位置
    3. struct ListNode*prev = NULL;
    4. struct ListNode*cur = head;
    5. while(cur != NULL){
    6. struct Listndoe*nextnode = cur->next;
    7. cur->next = prev;
    8. prev = cur;
    9. cur= nextnode;
    10. }
    11. head = prev;
    12. return head;
    13. }

    876. 链表的中间结点 - 力扣(LeetCode)

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. struct ListNode* middleNode(struct ListNode* head) {
    9. struct ListNode* cur = head;
    10. struct ListNdoe* mid = NULL;
    11. int count = 0;
    12. while(cur){
    13. cur = cur->next;
    14. count++;
    15. }
    16. int n = (count/2);//n为几就需要头删几个
    17. while(n-->0){
    18. mid = head->next;
    19. free(head);
    20. head = mid;
    21. }
    22. return head;
    23. }

    19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    9. struct ListNode*phead = head;//这个变量用于求出链表结点个数
    10. struct ListNode* m = head;
    11. struct ListNode* prev = NULL;
    12. int count = 1,i = 0;
    13. while(phead!=NULL){
    14. phead = phead->next;
    15. count++;
    16. }
    17. while(i++-1){//找到倒数第n个节点
    18. prev = m;
    19. m = m->next;
    20. }
    21. if(m==head){//头删
    22. head = m->next;
    23. free(m);
    24. m = NULL;
    25. }
    26. else{//中间删除
    27. prev->next = m->next;
    28. free(m);
    29. m=NULL;
    30. }
    31. return head;
    32. }

    21. 合并两个有序链表 - 力扣(LeetCode)

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    9. //若这个地方不判断list是否为空指针,后面部分对tail解引用会报错为空指针解引用
    10. if(list1==NULL){
    11. return list2;
    12. }
    13. if(list2==NULL){
    14. return list1;
    15. }
    16. struct ListNode*n1 = list1;
    17. struct ListNode*n2 = list2;
    18. struct ListNode*head = NULL;
    19. struct ListNode*tail = NULL;//tail随时跟随新链表变动
    20. while(n1&&n2){
    21. if(n1->val >= n2->val){
    22. if(head==NULL){//head最开始为NULL,要先赋值
    23. head = n2;
    24. tail = n2;
    25. }else{
    26. tail->next = n2;
    27. tail = n2;
    28. //tail不断往前走,这样就可以不用每次都遍历链表找到尾再插入
    29. }
    30. n2 = n2->next;
    31. }else if(n1->val < n2->val){
    32. if(head==NULL){
    33. head = n1;
    34. tail = n1;
    35. }else{
    36. tail->next = n1;
    37. tail = n1;
    38. }
    39. n1 = n1->next;
    40. }
    41. }
    42. if(n2){//当n1或者n2其中一空就会跳出来判断
    43. tail->next = n2;
    44. }else if(n1){
    45. tail->next = n1;
    46. }
    47. return head;
    48. }

    现在有一链表的头指针ListNode* pHead,给一定值x,编写一段代码将所有小于x的节点都排在其余点之前,且不改变原来的数据顺序,返回重新排列后的链表头指针

    面试题 02.04. 分割链表 - 力扣(LeetCode)

    创建两个带哨兵的链表 然后一大放比x大的 一个放比x小的  

    1. /**
    2. * Definition for singly-linked list.
    3. * public class ListNode {
    4. * int val;
    5. * ListNode next;
    6. * ListNode(int x) { val = x; }
    7. * }
    8. */
    9. class Solution {
    10. public ListNode partition(ListNode head, int x) {
    11. ListNode smlDummy = new ListNode(0),bigDummy = new ListNode(0);
    12. ListNode sml = smlDummy,big = bigDummy;
    13. while(head!=null){
    14. if(head.val
    15. sml.next = head;
    16. sml = sml.next;
    17. }else{
    18. big.next = head;
    19. big = big.next;
    20. }
    21. head = head.next;
    22. }
    23. sml.next = bigDummy.next;
    24. big.next = null;
    25. return smlDummy.next;
    26. }
    27. }

    234. 回文链表 - 力扣(LeetCode)

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * struct ListNode *next;
    6. * };
    7. */
    8. bool isPalindrome(struct ListNode* head) {
    9. struct ListNode*n = head;
    10. struct ListNode*m = head;
    11. while(m && m->next){//找到中间的节点的新方法,这个地方循环后中间节点为n,可以自己画图验证
    12. n = n->next;
    13. m = m->next->next;
    14. }//n为中间结点
    15. struct ListNode*cur = n;
    16. struct ListNode*prev =NULL;
    17. struct ListNode*next = n->next;
    18. while(cur){//反转链表
    19. cur->next = prev;
    20. prev = cur;
    21. cur = next;
    22. if(next){
    23. next = next->next;
    24. }
    25. }//prev 为反转后的头
    26. struct ListNode*phead = head;
    27. while(phead&&prev){//比较两个链表,当一个链表为NULL的时候就停止
    28. if(phead->val!=prev->val){
    29. return false;
    30. }else{
    31. phead= phead->next;
    32. prev = prev->next;
    33. }
    34. }
    35. return true;
    36. }

    160. 相交链表 - 力扣(LeetCode)

    1. public class Solution {
    2. public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    3. ListNode A =headA,B = headB;
    4. while(A!=B){
    5. A = A!=null?A.next:headB;
    6. B =B!=null?B.next:headA;
    7. }
    8. return A;
    9. }
    10. }

    将两个递增的有序链表合并为一个递增的有序链表.要求结果链表仍使用原来两个链表的存储空间
    不另外占用其他的存储空间.表中不允许有重复的数据. 

    1. /* run this program using the console pauser or add your own getch, system("pause") or input loop */
    2. /*
    3. 思路:La,Lb是工作指针 当La和Lb所指向的元素值不同的时候,较小的值链接到Lc上
    4. La和Lb所指向的元素值相同的时候,将La的值链接到Lc上,Lb上的删掉
    5. */
    6. #include
    7. using namespace std;
    8. // 定义链表结点结构
    9. struct ListNode {
    10. int data;
    11. ListNode *next;
    12. };
    13. // 定义链表头指针类型
    14. typedef ListNode* LinkList;
    15. // 合并两个有序链表
    16. void MergeList(LinkList &La, LinkList &Lb, LinkList &Lc)
    17. {
    18. ListNode *pa = La->next; // La 的工作指针,初始化为第一个结点
    19. ListNode *pb = Lb->next; // Lb 的工作指针,初始化为第一个结点
    20. Lc = La; // 用 La 的头结点作为 Lc 的头结点
    21. ListNode *pc = Lc; // Lc 的工作指针
    22. while (pa && pb) {
    23. if (pa->data < pb->data) {
    24. pc->next = pa; // 将 pa 链接在 pc 的后面
    25. pc = pa; // pc 指针后移
    26. pa = pa->next; // pa 指针后移
    27. } else if (pa->data > pb->data) {
    28. pc->next = pb; // 将 pb 链接在 pc 的后面
    29. pc = pb; // pc 指针后移
    30. pb = pb->next; // pb 指针后移
    31. } else { // 相等时取 La 中的元素,删除 Lb 中的元素
    32. pc->next = pa; // 将 pa 链接在 pc 的后面
    33. pc = pa; // pc 指针后移
    34. pa = pa->next; // pa 指针后移
    35. ListNode *q = pb->next; // 保存 pb 的下一个结点
    36. delete pb; // 删除 pb 结点
    37. pb = q; // pb 指针后移
    38. }
    39. }
    40. // 插入剩余段
    41. pc->next = pa ? pa : pb;
    42. // 释放 Lb 的头结点
    43. delete Lb;
    44. }
    45. int main() {
    46. // 测试代码
    47. // 创建两个链表 La 和 Lb,并初始化它们
    48. LinkList La = new ListNode();
    49. La->next = NULL;
    50. LinkList Lb = new ListNode();
    51. Lb->next = NULL;
    52. // 填充链表 La
    53. ListNode *p = La;
    54. for (int i = 1; i <= 5; i += 2) {
    55. ListNode *node = new ListNode();
    56. node->data = i;
    57. node->next = NULL;
    58. p->next = node;
    59. p = node;
    60. }
    61. // 填充链表 Lb
    62. p = Lb;
    63. for (int i = 2; i <= 6; i += 2) {
    64. ListNode *node = new ListNode();
    65. node->data = i;
    66. node->next = NULL;
    67. p->next = node;
    68. p = node;
    69. }
    70. // 打印合并前的链表
    71. std::cout << "La: ";
    72. for (p = La->next; p != NULL; p = p->next)
    73. std::cout << p->data << " ";
    74. std::cout << "\nLb: ";
    75. for (p = Lb->next; p != NULL; p = p->next)
    76. std::cout << p->data << " ";
    77. std::cout << "\n";
    78. // 合并链表
    79. LinkList Lc;
    80. MergeList(La, Lb, Lc);
    81. // 打印合并后的链表
    82. std::cout << "Lc: ";
    83. for (p = Lc->next; p != NULL; p = p->next)
    84. std::cout << p->data << " ";
    85. std::cout << "\n";
    86. // 释放链表
    87. p = Lc;
    88. while (p != NULL) {
    89. ListNode *q = p->next;
    90. delete p;
    91. p = q;
    92. }
    93. return 0;
    94. }

    //3)已知两个链表 A 和 B 分别表示两个集合,其元素递增排列。请设计算法求出 A 与 B
    //的交集,并存放于 A 链表中。
    //[题目分析]
    //只有同时出现在两集合中的元素才出现在结果表中, 合并后的新表使用头指针 Lc 指向。
    //pa 和 pb 分别是链表 La 和 Lb 的工作指针, 初始化为相应链表的第一个结点, 从第一个结点开
    //始进行比较,当两个链表 La 和 Lb 均为到达表尾结点时,如果两个表中相等的元素时,摘取
    //La 表中的元素,删除 Lb 表中的元素;如果其中一个表中的元素较小时,删除此表中较小的
    //元素,此表的工作指针后移。当链表 La 和 Lb 有一个到达表尾结点,为空时,依次删除另一
    //个非空表中的所有元素。
    //

    1. #include
    2. struct Node {
    3. int data; // 数据
    4. Node* next; // 指向下一个节点的指针
    5. // 构造函数
    6. Node(int val) : data(val), next(nullptr) {}
    7. };
    8. typedef Node* LinkList; // 定义链表类型
    9. void Mix(LinkList& La, LinkList& Lb, LinkList& Lc) {
    10. Node* pa = La->next; // 指向链表 La 的当前节点
    11. Node* pb = Lb->next; // 指向链表 Lb 的当前节点
    12. Node* pc = La; // Lc 的工作指针,初始化为 La 的头结点
    13. Node* u; // 用于暂存要删除的节点
    14. Lc = La;
    15. while (pa && pb) {
    16. if (pa->data == pb->data) { // 如果两个节点数据相等(交集部分)
    17. pc->next = pa; // 将当前节点接入结果链表
    18. pc = pa; // pc 指向新接入的节点
    19. pa = pa->next; // pa 向后移动
    20. u = pb; // 暂存要删除的节点 pb
    21. pb = pb->next; // pb 向后移动
    22. delete u; // 删除节点 pb
    23. }
    24. else if (pa->data < pb->data) {
    25. u = pa; // 暂存要删除的节点 pa
    26. pa = pa->next; // pa 向后移动
    27. delete u; // 删除节点 pa
    28. }
    29. else {
    30. u = pb; // 暂存要删除的节点 pb
    31. pb = pb->next; // pb 向后移动
    32. delete u; // 删除节点 pb
    33. }
    34. }
    35. // 处理剩余的节点
    36. while (pa) {
    37. u = pa; // 暂存要删除的节点 pa
    38. pa = pa->next; // pa 向后移动
    39. delete u; // 删除节点 pa
    40. }
    41. while (pb) {
    42. u = pb; // 暂存要删除的节点 pb
    43. pb = pb->next; // pb 向后移动
    44. delete u; // 删除节点 pb
    45. }
    46. pc->next = NULL; // 置链表尾标记
    47. delete Lb; // 释放 Lb 的头结点
    48. }

    ( 4)已知两个链表 A 和 B 分别表示两个集合,其元素递增排列。请设计算法求出两个集
    合 A 和 B 的差集(即仅由在 A 中出现而不在 B 中出现的元素所构成的集合) ,并以同样的形
    式存储,同时返回该集合的元素个数。
    [ 题目分析 ]
    求两个集合 A 和 B 的差集是指在 A 中删除 A 和 B 中共有的元素,即删除链表中的相应结
    点 , 所以要保存待删除结点的前驱,使用指针 pre 指向前驱结点。 pa 和 pb 分别是链表 La 和
    Lb 的工作指针 , 初始化为相应链表的第一个结点,从第一个结点开始进行比较,当两个链表
    La 和 Lb 均为到达表尾结点时,如果 La 表中的元素小于 Lb 表中的元素, pre 置为 La 表的工
    作指针 pa 删除 Lb 表中的元素;如果其中一个表中的元素较小时,删除此表中较小的元素,
    此表的工作指针后移。 当链表 La 和 Lb 有一个为空时, 依次删除另一个非空表中的所有元素.

    1. *
    2. 将两个非递减的有序链表合并为一个非递增的有序链表。 要求结果链表仍使用原来
    3. 两个链表的存储空间 , 不另外占用其它的存储空间。表中允许有重复的数据。
    4. [ 题目分析 ]
    5. 合并后的新表使用头指针 Lc 指向, pa 和 pb 分别是链表 La 和 Lb 的工作指针 , 初始化为
    6. 相应链表的第一个结点,从第一个结点开始进行比较,当两个链表 La 和 Lb 均为到达表尾结
    7. 点时,依次摘取其中较小者重新链接在 Lc 表的表头结点之后,如果两个表中的元素相等,只
    8. 摘取 La 表中的元素,保留 Lb 表中的元素。当一个表到达表尾结点,为空时,将非空表的剩
    9. 余元素依次摘取,链接在 Lc 表的表头结点之后。
    10. */
    11. #include
    12. using namespace std;
    13. void Difference(LinkList& La, LinkList& Lb, int *n) {
    14. Node *pa = La->next; // 指向链表 La 的当前节点
    15. Node *pb = Lb->next; // 指向链表 Lb 的当前节点
    16. Node *pre = La; // pre 为 La 中 pa 所指结点的前驱结点的指针
    17. Node *u; // 用于暂存要删除的节点
    18. *n = 0; // 初始化结果集合中元素个数为 0
    19. while (pa && pb) {
    20. if (pa->data < pb->data) {
    21. pre = pa; // A 链表中当前结点指针后移
    22. pa = pa->next;
    23. (*n)++; // 计数器加一,表示找到一个差集元素
    24. } else if (pa->data > pb->data) {
    25. pb = pb->next; // B 链表中当前结点指针后移
    26. } else { // pa->data == pb->data,即 A 和 B 中当前结点数据相同
    27. pre->next = pa->next; // 删除 A 中当前结点
    28. u = pa;
    29. pa = pa->next;
    30. delete u; // 释放结点空间
    31. }
    32. }
    33. // 处理 A 中剩余的节点,这些节点都是 A 中独有的元素
    34. while (pa) {
    35. u = pa; // 暂存要删除的节点 pa
    36. pa = pa->next; // pa 向后移动
    37. delete u; // 删除节点 pa
    38. (*n)++; // 计数器加一,表示找到一个差集元素
    39. }
    40. // 由于 B 中剩余的节点都是不会出现在 A 中的元素,无需处理
    41. pre->next = nullptr; // 置链表尾标记
    42. // 释放 Lb 的头结点
    43. delete Lb;
    44. }

    5)设计算法将一个带头结点的单链表 A 分解为两个具有相同结构的链表 B、C,其中 B
    表的结点为 A 表中值小于零的结点,而 C 表的结点为 A 表中值大于零的结点(链表 A 中的元素为非零整数,要求 B、 C 表利用 A 表的结点) 。

    [ 题目分析 ]
    B 表的头结点使用原来 A 表的头结点,为 C 表新申请一个头结点。从 A 表的第一个结点
    开始,依次取其每个结点 p,判断结点 p 的值是否小于 0,利用前插法,将小于 0 的结点插入B 表 , 大于等于 0 的结点插入 C 表。

    1. #include
    2. #include
    3. // 定义链表结点结构
    4. typedef struct Node {
    5. int data;
    6. struct Node *next;
    7. } Node;
    8. // 创建新结点
    9. Node* createNode(int data) {
    10. Node *newNode = (Node *)malloc(sizeof(Node));
    11. if (!newNode) {
    12. printf("内存分配失败\n");
    13. exit(1);
    14. }
    15. newNode->data = data;
    16. newNode->next = NULL;
    17. return newNode;
    18. }
    19. // 打印链表
    20. void printList(Node *head) {
    21. Node *current = head->next; // 跳过头结点
    22. while (current != NULL) {
    23. printf("%d -> ", current->data);
    24. current = current->next;
    25. }
    26. printf("NULL\n");
    27. }
    28. // 释放链表内存
    29. void freeList(Node *head) {
    30. Node *current = head;
    31. Node *next;
    32. while (current != NULL) {
    33. next = current->next;
    34. free(current);
    35. current = next;
    36. }
    37. }
    38. // 分解链表
    39. void splitList(Node *A, Node *B, Node *C) {
    40. Node *current = A->next; // 跳过头结点
    41. Node *tailB = B; // B 表的尾指针
    42. Node *tailC = C; // C 表的尾指针
    43. while (current != NULL) {
    44. if (current->data < 0) {
    45. tailB->next = current;
    46. tailB = current;
    47. } else if (current->data > 0) {
    48. tailC->next = current;
    49. tailC = current;
    50. }
    51. current = current->next;
    52. }
    53. // 断开 B 和 C 表的最后一个结点
    54. tailB->next = NULL;
    55. tailC->next = NULL;
    56. }
    57. int main() {
    58. // 初始化链表 A
    59. Node *A = createNode(0); // 带头结点
    60. Node *current = A;
    61. int values[] = {3, -1, 5, -2, 8, -6, 7}; // 示例数据
    62. for (int i = 0; i < sizeof(values)/sizeof(values[0]); i++) {
    63. current->next = createNode(values[i]);
    64. current = current->next;
    65. }
    66. printf("链表 A: ");
    67. printList(A);
    68. // 初始化链表 B 和 C 的头结点
    69. Node *B = createNode(0); // 带头结点
    70. Node *C = createNode(0); // 带头结点
    71. // 分解链表
    72. splitList(A, B, C);
    73. printf("链表 B: ");
    74. printList(B);
    75. printf("链表 C: ");
    76. printList(C);
    77. // 释放链表内存
    78. freeList(A);
    79. freeList(B);
    80. freeList(C);
    81. return 0;
    82. }

    ( 6)设计一个算法,通过一趟遍历在单链表中确定值最大的结点。

    1. //( 6)设计一个算法,通过一趟遍历在单链表中确定值最大的结点。
    2. #include
    3. #include
    4. struct ListNode {
    5. int value;
    6. ListNode* next;
    7. ListNode(int x) : value(x), next(NULL) {}
    8. };
    9. ListNode* findMaxNode(ListNode* head) {
    10. if (!head) {
    11. return NULL;
    12. }
    13. ListNode* max_value_node = head;
    14. ListNode* current = head->next;
    15. while (current) {
    16. if (current->value > max_value_node->value) {
    17. max_value_node = current;
    18. }
    19. current = current->next;
    20. }
    21. return max_value_node;
    22. }
    23. int main() {
    24. // 创建一个链表用于测试
    25. ListNode* node5 = new ListNode(3);
    26. ListNode* node4 = new ListNode(1);
    27. node4->next = node5;
    28. ListNode* node3 = new ListNode(4);
    29. node3->next = node4;
    30. ListNode* node2 = new ListNode(2);
    31. node2->next = node3;
    32. ListNode* head = new ListNode(5);
    33. head->next = node2;
    34. // 调用函数并输出结果
    35. ListNode* max_node = findMaxNode(head);
    36. if (max_node) {
    37. std::cout << "最大值节点的值是: " << max_node->value << std::endl;
    38. } else {
    39. std::cout << "链表为空" << std::endl;
    40. }
    41. // 释放分配的内存
    42. delete node5;
    43. delete node4;
    44. delete node3;
    45. delete node2;
    46. delete head;
    47. return 0;
    48. }

    ( 7)设计一个算法,通过遍历一趟,将链表中所有结点的链接方向逆转,仍利用原表的
    存储空间。

    1. // 逆转链表
    2. #include
    3. using namespace std;
    4. struct ListNode{
    5. int value;
    6. ListNode* next;
    7. ListNode(int x=0):value(x),next(NULL){}
    8. };
    9. ListNode*reverseList(ListNode*head) {
    10. ListNode*prev = NULL;
    11. ListNode* current = head;
    12. while(current){
    13. ListNode*next = current->next;//保存当前节点的下一个节点
    14. current->next = prev;//反转当前节点指针;
    15. prev = current;//更新prev为当前节点
    16. current = next;//移动到下一个节点
    17. }
    18. return prev;//prev现在是新的头结点
    19. }
    20. int main()
    21. {
    22. //创建一个链表用于测试
    23. ListNode*node5 = new ListNode(5);
    24. ListNode*node4 = new ListNode(4);
    25. node4->next = node5;
    26. ListNode*node3 = new ListNode(3);
    27. node3->next = node4;
    28. ListNode* node2 = new ListNode(2);
    29. node2->next = node3;
    30. ListNode*head = new ListNode(1);
    31. head->next = node2;
    32. //打印原链表
    33. cout<<"原链表:";
    34. ListNode*temp = head;
    35. while(temp){
    36. cout<value<<" ";
    37. temp = temp->next;
    38. }
    39. cout<
    40. ///调用函数反转链表
    41. ListNode*new_head = reverseList(head);
    42. //打印反转后的链表
    43. cout<<"反转后的链表:";
    44. temp = new_head;
    45. while(temp){
    46. cout<value<<" ";
    47. temp = temp->next;
    48. }
    49. cout<
    50. //释放分配的内存
    51. delete node5;
    52. delete node4;
    53. delete node3;
    54. delete node2;
    55. delete head;
    56. return 0;
    57. }

     ( 8)设计一个算法,删除递增有序链表中值大于 mink 且小于 maxk 的所有元素( mink
    和 maxk 是给定的两个参数,其值可以和表中的元素相同,也可以不同 )。

    1. #include
    2. struct ListNode {
    3. int value;
    4. ListNode* next;
    5. ListNode(int x) : value(x), next(nullptr) {}
    6. };
    7. ListNode* removeElementsInRange(ListNode* head, int mink, int maxk) {
    8. // 创建哨兵节点
    9. ListNode* dummy = new ListNode(0);
    10. dummy->next = head;
    11. ListNode* prev = dummy;
    12. ListNode* current = head;
    13. while (current) {
    14. if (current->value > mink && current->value < maxk) {
    15. prev->next = current->next; // 跳过当前节点
    16. } else {
    17. prev = current; // 继续遍历
    18. }
    19. current = current->next; // 移动到下一个节点
    20. }
    21. // 更新头节点
    22. ListNode* new_head = dummy->next;
    23. delete dummy; // 释放哨兵节点的内存
    24. return new_head;
    25. }
    26. int main() {
    27. // 创建一个递增有序链表用于测试
    28. ListNode* node5 = new ListNode(6);
    29. ListNode* node4 = new ListNode(5);
    30. node4->next = node5;
    31. ListNode* node3 = new ListNode(4);
    32. node3->next = node4;
    33. ListNode* node2 = new ListNode(3);
    34. node2->next = node3;
    35. ListNode* head = new ListNode(1);
    36. head->next = node2;
    37. int mink = 2;
    38. int maxk = 5;
    39. // 打印原链表
    40. std::cout << "原链表: ";
    41. ListNode* temp = head;
    42. while (temp) {
    43. std::cout << temp->value << " ";
    44. temp = temp->next;
    45. }
    46. std::cout << std::endl;
    47. // 调用函数删除指定范围的元素
    48. ListNode* new_head = removeElementsInRange(head, mink, maxk);
    49. // 打印删除后的链表
    50. std::cout << "删除后的链表: ";
    51. temp = new_head;
    52. while (temp) {
    53. std::cout << temp->value << " ";
    54. temp = temp->next;
    55. }
    56. std::cout << std::endl;
    57. // 释放分配的内存
    58. delete node5;
    59. delete node4;
    60. delete node3;
    61. delete node2;
    62. delete head;
    63. return 0;
    64. }

    ( 9)已知 p 指向双向循环链表中的一个结点, 其结点结构为 data 、prior 、next 三个域,
    写出算法 change, 交换 p 所指向的结点和它的前缀结点的顺序。

    1. #include
    2. struct ListNode {
    3. int data;
    4. ListNode* prior;
    5. ListNode* next;
    6. ListNode(int x) : data(x), prior(nullptr), next(nullptr) {}
    7. };
    8. void change(ListNode* p) {
    9. if (p == nullptr || p->prior == nullptr) {
    10. return; // 无法交换
    11. }
    12. ListNode* Q = p->prior; // Q 是 p 的前驱节点
    13. ListNode* Q_prior = Q->prior; // Q 的前驱节点
    14. ListNode* P_next = p->next; // P 的后继节点
    15. // 交换 P 和 Q 的指针
    16. if (Q_prior != nullptr) {
    17. Q_prior->next = p;
    18. }
    19. if (P_next != nullptr) {
    20. P_next->prior = Q;
    21. }
    22. p->prior = Q_prior;
    23. p->next = Q;
    24. Q->prior = p;
    25. Q->next = P_next;
    26. }
    27. void printList(ListNode* head) {
    28. ListNode* temp = head;
    29. do {
    30. std::cout << temp->data << " ";
    31. temp = temp->next;
    32. } while (temp != head);
    33. std::cout << std::endl;
    34. }
    35. int main() {
    36. // 创建一个双向循环链表用于测试
    37. ListNode* node1 = new ListNode(1);
    38. ListNode* node2 = new ListNode(2);
    39. ListNode* node3 = new ListNode(3);
    40. ListNode* node4 = new ListNode(4);
    41. node1->next = node2; node1->prior = node4;
    42. node2->next = node3; node2->prior = node1;
    43. node3->next = node4; node3->prior = node2;
    44. node4->next = node1; node4->prior = node3;
    45. ListNode* head = node1;
    46. // 打印原链表
    47. std::cout << "原链表: ";
    48. printList(head);
    49. // 调用函数交换 node3 和 node2
    50. change(node3);
    51. // 打印交换后的链表
    52. std::cout << "交换后的链表: ";
    53. printList(head);
    54. // 释放分配的内存
    55. delete node1;
    56. delete node2;
    57. delete node3;
    58. delete node4;
    59. return 0;
    60. }

    ( 10)已知长度为 n 的线性表 A 采用顺序存储结构,请写一时间复杂度为 O(n) 、空间复
    杂度为 O(1) 的算法,该算法删除线性表中所有值为 item 的数据元素。

    1. #include
    2. void removeItem(int* A, int& n, int item) {
    3. int j = 0; // j 指向下一个保留的位置
    4. for (int i = 0; i < n; ++i) {
    5. if (A[i] != item) {
    6. A[j] = A[i];
    7. ++j;
    8. }
    9. }
    10. // 更新数组长度
    11. n = j;
    12. }
    13. int main() {
    14. // 测试数据
    15. int A[] = {1, 2, 3, 2, 4, 2, 5};
    16. int n = sizeof(A) / sizeof(A[0]);
    17. int item = 2;
    18. std::cout << "原数组: ";
    19. for (int i = 0; i < n; ++i) {
    20. std::cout << A[i] << " ";
    21. }
    22. std::cout << std::endl;
    23. // 删除所有值为 item 的元素
    24. removeItem(A, n, item);
    25. std::cout << "删除后的数组: ";
    26. for (int i = 0; i < n; ++i) {
    27. std::cout << A[i] << " ";
    28. }
    29. std::cout << std::endl;
    30. return 0;
    31. }

  • 相关阅读:
    我和谷歌共成长-资深安卓开发的转型之路
    ChatGPT的问题与回复的内容导出(Chorme)
    TiDB乐观事务、悲观事务模型验证
    【韩老师设计模式8】模板方法和命令模式,ConfigurableApplicationContext,JdbcTemplate
    cubeIDE开发,结合汉字取模工具,在LCD输出各种字体
    freeswitch 使用 silero-vad 静音拆分使用 fastasr 识别
    灵界的科学丨二、耳朵及手指识字的实验启示
    React中如何提高组件的渲染效率
    适用于中大型C++工程的CMake模板1
    重温C语言十四-----结构体与共用体
  • 原文地址:https://blog.csdn.net/2301_79602614/article/details/139835426