鱼C论坛

 找回密码
 立即注册
查看: 2589|回复: 28

[已解决]关于单循环链表的写法

[复制链接]
发表于 2022-11-8 20:45:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
#include<iostream>
using namespace std;
#include"time.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0


typedef int Status;
typedef int ElemType;

typedef struct Node
{
        ElemType data;
        struct Node* next;

}Node,*LinkList;


Status visit(ElemType c);
Status InitList(LinkList* L);
Status ListEmpty(LinkList L);
Status ClearList(LinkList* L);
Status DestroyList(LinkList* L);


Status visit(ElemType c)
{
        cout << c << " ";
        return 0;
}
Status InitList(LinkList *L)
{
        *L = new Node;
        if (!(*L))
        {
                return ERROR;
        }
        (*L)->next = *L;

}

Status ListEmpty(LinkList L)
{
        if (L->next=L)
        {
                return TRUE;
        }
        else
        {
                return FALSE;
        }


}
Status ClearList(LinkList *L)
{
        LinkList p, q;
        p = (*L)->next;
        while (p!=*L)
        {
                q = p->next;
                delete p;
                p = q;
        }
        (*L)->next = *L;
        return OK;
}

Status DestroyList(LinkList* L)
{
        LinkList p;
        p = (*L);
        while (*L!=(*L)->next)
        {
                p = (*L);
                (*L) = (*L)->next;
                delete p;
        }
       delete *L;

        return OK;
       


}



int main()
{

        return 0;
}

如果判断了*L=*L->next,就是一个空表,循环结束再删除(*L),有点繁琐,有没有更好解决的办法
最佳答案
2022-11-8 22:53:43
或者把next换成prev更好理解一些?

  1. #include <iostream>
  2. #include <ctype.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <math.h>
  7. #include <time.h>

  8. using namespace std;

  9. #define OK 1
  10. #define ERROR 0
  11. #define TRUE 1
  12. #define FALSE 0

  13. #define MAXSIZE 20

  14. typedef int Status;
  15. typedef int ElemType;

  16. typedef struct Node {
  17.     ElemType data;
  18.     //struct Node *next;
  19.     struct Node *prev;
  20. } Node;

  21. typedef struct Node *LinkList;

  22. Status InitList(LinkList *L);
  23. Status DestroyList(LinkList *L);
  24. Status ClearList(LinkList *L);
  25. Status ListInsert(LinkList *L, int i, ElemType e);
  26. Status ListDelete(LinkList *L, int i, ElemType *e);
  27. Status GetElem(LinkList L, int i, ElemType *e);
  28. Status SetElem(LinkList L, int i, const ElemType *e);
  29. int ListLength(LinkList L);
  30. Status ListEmpty(LinkList L);
  31. Status ListTraverse(LinkList L);

  32. Status InitList(LinkList *L) {
  33.     *L = new Node;
  34.     if(!*L) return ERROR;
  35.     (*L)->prev = *L;
  36.     return OK;
  37. }

  38. Status DestroyList(LinkList *L) {
  39.     ClearList(L);
  40.     delete *L;
  41.     return OK;
  42. }

  43. Status ClearList(LinkList *L) {
  44.     ElemType e;
  45.     while(!ListEmpty(*L)) ListDelete(L, 0, &e);
  46.     return OK;
  47. }

  48. Status ListInsert(LinkList *L, int i, ElemType e) {
  49.     int length = ListLength(*L);
  50.     if(i > length) return FALSE;
  51.     LinkList p = *L;
  52.     for(int x = 0; x < length - i; ++x) p = p->prev;
  53.     LinkList q = new Node;
  54.     if(!q) return FALSE;
  55.     q->data = e;
  56.     q->prev = p->prev;
  57.     p->prev = q;
  58.     return TRUE;
  59. }

  60. Status ListDelete(LinkList *L, int i, ElemType *e) {
  61.     int length = ListLength(*L);
  62.     if(i >= length) return FALSE;
  63.     LinkList p = *L;
  64.     for(int x = 0; x < length - i - 1; ++x) p = p->prev;
  65.     LinkList q = p->prev;
  66.     p->prev = q->prev;
  67.     delete q;
  68.     return TRUE;
  69. }

  70. Status GetElem(LinkList L, int i, ElemType *e) {
  71.     int length = ListLength(L);
  72.     if(i >= length) return FALSE;
  73.     LinkList p = L;
  74.     for(int x = 0; x < length - i; ++x) p = p->prev;
  75.     *e = p->data;
  76.     return TRUE;
  77. }

  78. Status SetElem(LinkList L, int i, const ElemType *e) {
  79.     ElemType temp;
  80.     Status s = ListDelete(&L, i, &temp);
  81.     return s ? ListInsert(&L, i, *e) : s;
  82. }

  83. int ListLength(LinkList L) {
  84.     int i = 0;
  85.     LinkList p = L;
  86.     while(p->prev != L) {
  87.         i++;
  88.         p = p->prev;
  89.     }
  90.     return i;
  91. }

  92. Status ListEmpty(LinkList L) {
  93.     if(ListLength(L) == 0) return TRUE;
  94.     return FALSE;
  95. }

  96. Status visit(ElemType c) {
  97.     cout << c << " ";
  98.     return OK;
  99. }

  100. Status ListTraverse(LinkList L) {
  101.     for(int i = 0; i < ListLength(L); ++i) {
  102.         ElemType e;
  103.         GetElem(L, i, &e);
  104.         visit(e);
  105.     }
  106.     cout << endl;
  107.     return OK;
  108. }

  109. Status ListAppend(LinkList L, const ElemType *e) {
  110.     return ListInsert(&L, ListLength(L), *e);
  111. }

  112. int main() {
  113.     LinkList L;
  114.     InitList(&L);
  115.     for(ElemType i = 0; i < 10; ++i) {
  116.         ListAppend(L, &i);
  117.     }
  118.     ListTraverse(L);
  119.     ElemType e = 100; SetElem(L, 3, &e);
  120.     ListTraverse(L);
  121.     GetElem(L, 5, &e);
  122.     cout << e << endl;
  123.     DestroyList(&L);
  124.     return 0;
  125. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-11-8 20:58:43 | 显示全部楼层
好方法?之前不是给你写了吗?你都不看吗?

  1. Status DestroyList(LinkList *L) {
  2.     ClearList(L);
  3.     delete *L;
  4.     *L = NULL;
  5.     return OK;
  6. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2022-11-8 20:59:18 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-8 21:01:00 | 显示全部楼层
我不能理解,我给你写了那么多东西,你都不看,伤心的说
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-8 21:02:03 | 显示全部楼层
我还以为你都看了,都弄懂了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-8 21:30:01 | 显示全部楼层
人造人 发表于 2022-11-8 21:02
我还以为你都看了,都弄懂了

过一遍单链表以后,想手写一次循环单链表,思维卡主了,在循环链表上,设置头指针和尾指针上思路有些不够清晰
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-8 21:32:50 | 显示全部楼层
1094570635 发表于 2022-11-8 21:30
过一遍单链表以后,想手写一次循环单链表,思维卡主了,在循环链表上,设置头指针和尾指针上思路有些不够 ...

都一样,销毁链表就是把链表清空了,然后删除头结点
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-8 21:34:39 | 显示全部楼层
1094570635 发表于 2022-11-8 21:30
过一遍单链表以后,想手写一次循环单链表,思维卡主了,在循环链表上,设置头指针和尾指针上思路有些不够 ...

清空链表等于什么呢?
等于一直删除第0个结点,直到链表为空

删除结点就没办法了,得老老实实的操作底层结构
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-8 21:53:00 | 显示全部楼层
人造人 发表于 2022-11-8 21:34
清空链表等于什么呢?
等于一直删除第0个结点,直到链表为空

有没有设置尾节点操作的办法,感觉循环链表用头结点操作比较麻烦orz,还有就是设置了尾节点操作链表插入,删除和单链表对比,需要做些什么修改么
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-8 22:47:55 | 显示全部楼层
1094570635 发表于 2022-11-8 21:53
有没有设置尾节点操作的办法,感觉循环链表用头结点操作比较麻烦orz,还有就是设置了尾节点操作链表插入, ...

把思维逆转过来,为什么头结点指向的就必须是第0个元素?
为什么头结点不能是指向最后一个元素?
下面这个代码把头结点指向的元素看成是最后一个元素
也就是那个所谓的 尾节点

  1. #include <iostream>
  2. #include <ctype.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <math.h>
  7. #include <time.h>

  8. using namespace std;

  9. #define OK 1
  10. #define ERROR 0
  11. #define TRUE 1
  12. #define FALSE 0

  13. #define MAXSIZE 20

  14. typedef int Status;
  15. typedef int ElemType;

  16. typedef struct Node {
  17.     ElemType data;
  18.     struct Node *next;
  19. } Node;

  20. typedef struct Node *LinkList;

  21. Status InitList(LinkList *L);
  22. Status DestroyList(LinkList *L);
  23. Status ClearList(LinkList *L);
  24. Status ListInsert(LinkList *L, int i, ElemType e);
  25. Status ListDelete(LinkList *L, int i, ElemType *e);
  26. Status GetElem(LinkList L, int i, ElemType *e);
  27. Status SetElem(LinkList L, int i, const ElemType *e);
  28. int ListLength(LinkList L);
  29. Status ListEmpty(LinkList L);
  30. Status ListTraverse(LinkList L);

  31. Status InitList(LinkList *L) {
  32.     *L = new Node;
  33.     if(!*L) return ERROR;
  34.     (*L)->next = *L;
  35.     return OK;
  36. }

  37. Status DestroyList(LinkList *L) {
  38.     ClearList(L);
  39.     delete *L;
  40.     return OK;
  41. }

  42. Status ClearList(LinkList *L) {
  43.     ElemType e;
  44.     while(!ListEmpty(*L)) ListDelete(L, 0, &e);
  45.     return OK;
  46. }

  47. Status ListInsert(LinkList *L, int i, ElemType e) {
  48.     int length = ListLength(*L);
  49.     if(i > length) return FALSE;
  50.     LinkList p = *L;
  51.     for(int x = 0; x < length - i; ++x) p = p->next;
  52.     LinkList q = new Node;
  53.     if(!q) return FALSE;
  54.     q->data = e;
  55.     q->next = p->next;
  56.     p->next = q;
  57.     return TRUE;
  58. }

  59. Status ListDelete(LinkList *L, int i, ElemType *e) {
  60.     int length = ListLength(*L);
  61.     if(i >= length) return FALSE;
  62.     LinkList p = *L;
  63.     for(int x = 0; x < length - i - 1; ++x) p = p->next;
  64.     LinkList q = p->next;
  65.     p->next = q->next;
  66.     delete q;
  67.     return TRUE;
  68. }

  69. Status GetElem(LinkList L, int i, ElemType *e) {
  70.     int length = ListLength(L);
  71.     if(i >= length) return FALSE;
  72.     LinkList p = L;
  73.     for(int x = 0; x < length - i; ++x) p = p->next;
  74.     *e = p->data;
  75.     return TRUE;
  76. }

  77. Status SetElem(LinkList L, int i, const ElemType *e) {
  78.     ElemType temp;
  79.     Status s = ListDelete(&L, i, &temp);
  80.     return s ? ListInsert(&L, i, *e) : s;
  81. }

  82. int ListLength(LinkList L) {
  83.     int i = 0;
  84.     LinkList p = L;
  85.     while(p->next != L) {
  86.         i++;
  87.         p = p->next;
  88.     }
  89.     return i;
  90. }

  91. Status ListEmpty(LinkList L) {
  92.     if(ListLength(L) == 0) return TRUE;
  93.     return FALSE;
  94. }

  95. Status visit(ElemType c) {
  96.     cout << c << " ";
  97.     return OK;
  98. }

  99. Status ListTraverse(LinkList L) {
  100.     for(int i = 0; i < ListLength(L); ++i) {
  101.         ElemType e;
  102.         GetElem(L, i, &e);
  103.         visit(e);
  104.     }
  105.     cout << endl;
  106.     return OK;
  107. }

  108. Status ListAppend(LinkList L, const ElemType *e) {
  109.     return ListInsert(&L, ListLength(L), *e);
  110. }

  111. int main() {
  112.     LinkList L;
  113.     InitList(&L);
  114.     for(ElemType i = 0; i < 10; ++i) {
  115.         ListAppend(L, &i);
  116.     }
  117.     ListTraverse(L);
  118.     ElemType e = 100; SetElem(L, 3, &e);
  119.     ListTraverse(L);
  120.     GetElem(L, 5, &e);
  121.     cout << e << endl;
  122.     DestroyList(&L);
  123.     return 0;
  124. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-8 22:53:43 | 显示全部楼层    本楼为最佳答案   
或者把next换成prev更好理解一些?

  1. #include <iostream>
  2. #include <ctype.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <math.h>
  7. #include <time.h>

  8. using namespace std;

  9. #define OK 1
  10. #define ERROR 0
  11. #define TRUE 1
  12. #define FALSE 0

  13. #define MAXSIZE 20

  14. typedef int Status;
  15. typedef int ElemType;

  16. typedef struct Node {
  17.     ElemType data;
  18.     //struct Node *next;
  19.     struct Node *prev;
  20. } Node;

  21. typedef struct Node *LinkList;

  22. Status InitList(LinkList *L);
  23. Status DestroyList(LinkList *L);
  24. Status ClearList(LinkList *L);
  25. Status ListInsert(LinkList *L, int i, ElemType e);
  26. Status ListDelete(LinkList *L, int i, ElemType *e);
  27. Status GetElem(LinkList L, int i, ElemType *e);
  28. Status SetElem(LinkList L, int i, const ElemType *e);
  29. int ListLength(LinkList L);
  30. Status ListEmpty(LinkList L);
  31. Status ListTraverse(LinkList L);

  32. Status InitList(LinkList *L) {
  33.     *L = new Node;
  34.     if(!*L) return ERROR;
  35.     (*L)->prev = *L;
  36.     return OK;
  37. }

  38. Status DestroyList(LinkList *L) {
  39.     ClearList(L);
  40.     delete *L;
  41.     return OK;
  42. }

  43. Status ClearList(LinkList *L) {
  44.     ElemType e;
  45.     while(!ListEmpty(*L)) ListDelete(L, 0, &e);
  46.     return OK;
  47. }

  48. Status ListInsert(LinkList *L, int i, ElemType e) {
  49.     int length = ListLength(*L);
  50.     if(i > length) return FALSE;
  51.     LinkList p = *L;
  52.     for(int x = 0; x < length - i; ++x) p = p->prev;
  53.     LinkList q = new Node;
  54.     if(!q) return FALSE;
  55.     q->data = e;
  56.     q->prev = p->prev;
  57.     p->prev = q;
  58.     return TRUE;
  59. }

  60. Status ListDelete(LinkList *L, int i, ElemType *e) {
  61.     int length = ListLength(*L);
  62.     if(i >= length) return FALSE;
  63.     LinkList p = *L;
  64.     for(int x = 0; x < length - i - 1; ++x) p = p->prev;
  65.     LinkList q = p->prev;
  66.     p->prev = q->prev;
  67.     delete q;
  68.     return TRUE;
  69. }

  70. Status GetElem(LinkList L, int i, ElemType *e) {
  71.     int length = ListLength(L);
  72.     if(i >= length) return FALSE;
  73.     LinkList p = L;
  74.     for(int x = 0; x < length - i; ++x) p = p->prev;
  75.     *e = p->data;
  76.     return TRUE;
  77. }

  78. Status SetElem(LinkList L, int i, const ElemType *e) {
  79.     ElemType temp;
  80.     Status s = ListDelete(&L, i, &temp);
  81.     return s ? ListInsert(&L, i, *e) : s;
  82. }

  83. int ListLength(LinkList L) {
  84.     int i = 0;
  85.     LinkList p = L;
  86.     while(p->prev != L) {
  87.         i++;
  88.         p = p->prev;
  89.     }
  90.     return i;
  91. }

  92. Status ListEmpty(LinkList L) {
  93.     if(ListLength(L) == 0) return TRUE;
  94.     return FALSE;
  95. }

  96. Status visit(ElemType c) {
  97.     cout << c << " ";
  98.     return OK;
  99. }

  100. Status ListTraverse(LinkList L) {
  101.     for(int i = 0; i < ListLength(L); ++i) {
  102.         ElemType e;
  103.         GetElem(L, i, &e);
  104.         visit(e);
  105.     }
  106.     cout << endl;
  107.     return OK;
  108. }

  109. Status ListAppend(LinkList L, const ElemType *e) {
  110.     return ListInsert(&L, ListLength(L), *e);
  111. }

  112. int main() {
  113.     LinkList L;
  114.     InitList(&L);
  115.     for(ElemType i = 0; i < 10; ++i) {
  116.         ListAppend(L, &i);
  117.     }
  118.     ListTraverse(L);
  119.     ElemType e = 100; SetElem(L, 3, &e);
  120.     ListTraverse(L);
  121.     GetElem(L, 5, &e);
  122.     cout << e << endl;
  123.     DestroyList(&L);
  124.     return 0;
  125. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-8 23:30:15 | 显示全部楼层
人造人 发表于 2022-11-8 22:53
或者把next换成prev更好理解一些?

Status DestroyList(LinkList *L) {
    ClearList(L);
    delete *L;
    *L = NULL;
    return OK;
}
感谢,另外我能问一下,ClearList(L)函数中,即是函数调用函数的时候,形参L=LinkList L,对么?即是可以直接写L,不用&L接收
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-8 23:55:35 | 显示全部楼层
1094570635 发表于 2022-11-8 23:30
Status DestroyList(LinkList *L) {
    ClearList(L);
    delete *L;

就初始化的时候需要取地址,其他的都不需要

  1. #include <iostream>
  2. #include <ctype.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <math.h>
  7. #include <time.h>

  8. using namespace std;

  9. #define OK 1
  10. #define ERROR 0
  11. #define TRUE 1
  12. #define FALSE 0

  13. #define MAXSIZE 20

  14. typedef int Status;
  15. typedef int ElemType;

  16. typedef struct Node {
  17.     ElemType data;
  18.     //struct Node *next;
  19.     struct Node *prev;
  20. } Node;

  21. typedef struct Node *LinkList;

  22. Status InitList(LinkList *L);
  23. Status DestroyList(LinkList L);
  24. Status ClearList(LinkList L);
  25. Status ListInsert(LinkList L, int i, ElemType e);
  26. Status ListDelete(LinkList L, int i, ElemType *e);
  27. Status GetElem(LinkList L, int i, ElemType *e);
  28. Status SetElem(LinkList L, int i, const ElemType *e);
  29. int ListLength(LinkList L);
  30. Status ListEmpty(LinkList L);
  31. Status ListTraverse(LinkList L);

  32. Status InitList(LinkList *L) {
  33.     *L = new Node;
  34.     if(!*L) return ERROR;
  35.     (*L)->prev = *L;
  36.     return OK;
  37. }

  38. Status DestroyList(LinkList L) {
  39.     ClearList(L);
  40.     delete L;
  41.     return OK;
  42. }

  43. Status ClearList(LinkList L) {
  44.     ElemType e;
  45.     while(!ListEmpty(L)) ListDelete(L, 0, &e);
  46.     return OK;
  47. }

  48. Status ListInsert(LinkList L, int i, ElemType e) {
  49.     int length = ListLength(L);
  50.     if(i > length) return FALSE;
  51.     LinkList p = L;
  52.     for(int x = 0; x < length - i; ++x) p = p->prev;
  53.     LinkList q = new Node;
  54.     if(!q) return FALSE;
  55.     q->data = e;
  56.     q->prev = p->prev;
  57.     p->prev = q;
  58.     return TRUE;
  59. }

  60. Status ListDelete(LinkList L, int i, ElemType *e) {
  61.     int length = ListLength(L);
  62.     if(i >= length) return FALSE;
  63.     LinkList p = L;
  64.     for(int x = 0; x < length - i - 1; ++x) p = p->prev;
  65.     LinkList q = p->prev;
  66.     p->prev = q->prev;
  67.     delete q;
  68.     return TRUE;
  69. }

  70. Status GetElem(LinkList L, int i, ElemType *e) {
  71.     int length = ListLength(L);
  72.     if(i >= length) return FALSE;
  73.     LinkList p = L;
  74.     for(int x = 0; x < length - i; ++x) p = p->prev;
  75.     *e = p->data;
  76.     return TRUE;
  77. }

  78. Status SetElem(LinkList L, int i, const ElemType *e) {
  79.     ElemType temp;
  80.     Status s = ListDelete(L, i, &temp);
  81.     return s ? ListInsert(L, i, *e) : s;
  82. }

  83. int ListLength(LinkList L) {
  84.     int i = 0;
  85.     LinkList p = L;
  86.     while(p->prev != L) {
  87.         i++;
  88.         p = p->prev;
  89.     }
  90.     return i;
  91. }

  92. Status ListEmpty(LinkList L) {
  93.     if(ListLength(L) == 0) return TRUE;
  94.     return FALSE;
  95. }

  96. Status visit(ElemType c) {
  97.     cout << c << " ";
  98.     return OK;
  99. }

  100. Status ListTraverse(LinkList L) {
  101.     for(int i = 0; i < ListLength(L); ++i) {
  102.         ElemType e;
  103.         GetElem(L, i, &e);
  104.         visit(e);
  105.     }
  106.     cout << endl;
  107.     return OK;
  108. }

  109. Status ListAppend(LinkList L, const ElemType *e) {
  110.     return ListInsert(L, ListLength(L), *e);
  111. }

  112. int main() {
  113.     LinkList L;
  114.     InitList(&L);
  115.     for(ElemType i = 0; i < 10; ++i) {
  116.         ListAppend(L, &i);
  117.     }
  118.     ListTraverse(L);
  119.     ElemType e = 100; SetElem(L, 3, &e);
  120.     ListTraverse(L);
  121.     GetElem(L, 5, &e);
  122.     cout << e << endl;
  123.     DestroyList(L);
  124.     return 0;
  125. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-9 19:33:02 | 显示全部楼层
人造人 发表于 2022-11-8 23:55
就初始化的时候需要取地址,其他的都不需要

在循环链表中,插入位置的合理性不能用p!=NULL,能否用p!=L来判断?,还是只能通过表长的长度来判断元素的插入位置是否合理?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-9 19:39:05 | 显示全部楼层
1094570635 发表于 2022-11-9 19:33
在循环链表中,插入位置的合理性不能用p!=NULL,能否用p!=L来判断?,还是只能通过表长的长度来判断元素 ...


整那么复杂干嘛
通过表长的长度来判断
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-9 19:40:35 | 显示全部楼层
获取链表长度的函数已经写了,写了函数为什么不用呢,直接用链表长度判断不是更好?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-9 22:15:50 | 显示全部楼层
人造人 发表于 2022-11-9 19:40
获取链表长度的函数已经写了,写了函数为什么不用呢,直接用链表长度判断不是更好?

稍微自己写了下,加了点功能
#include<iostream>
using namespace std;

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int Status;
typedef  int ElemType;
typedef struct Node
{
        ElemType  data;
        /*struct Node* next;*/
        struct Node* last;

}Node,*LinkList;


Status visit(ElemType c);
Status InitList(LinkList* L);
Status EmptyList(LinkList L);
Status DestroyList(LinkList* L);
Status ClearList(LinkList* L);
int ListLength(LinkList L);
Status GetElem(LinkList L, int i, ElemType* e);
int LocateElem(LinkList L, ElemType e);
Node* LocateElem2(LinkList L, ElemType e);
Status ListInsert(LinkList* L, int i, ElemType e);
Status ListDelete(LinkList* L, int i, ElemType* e);
void CreatListHead(LinkList* L, int n);
void CreatListTail(LinkList* L, int n);
Status ListTraverse(LinkList L);

Status visit(ElemType c)
{
        cout << c << " ";
        return OK;
}

Status InitList(LinkList *L)
{
        *L = new Node;
        if(!(*L))
        {
                return ERROR;
        }
        (*L)->last = *L;
        return OK;
}

Status EmptyList(LinkList L)
{
        if (L->last!=L)
        {
                return FALSE;
        }
        else
        {
                return TRUE;
        }

}

Status DestroyList(LinkList *L)
{
        LinkList p = (*L);
        while ((*L)->last!=(*L))
        {
                p = (*L);
                (*L) = (*L)->last;
                delete p;

        }
        return OK;

}

Status ClearList(LinkList *L)
{
        LinkList p, q;
        p = (*L)->last;
        while (p!=(*L))
        {
                q = p->last;
                delete p;
                p = q;
        }
        (*L)->last =(*L);
        return OK;
}

int ListLength(LinkList L)
{
        int i = 0;
        LinkList p = L->last;
        while (p!=L)
        {
                i++;
                p = p->last;

        }
        return i;
       
}

Status GetElem(LinkList L,int i, ElemType *e)
{
        int j = 1;
        LinkList p = L->last;
        while (p != L&&j<i )
        {
                p = p->last;
                j++;

        }
        if (p==L||j>i)
        {
                return ERROR;
        }
        *e = p->data;
        return OK;

}

int LocateElem(LinkList L, ElemType e)
{
        LinkList p = L->last;
        int i = 0;
        while (p!=L)
        {
                ++i;
                if (p->data==e)
                {
                        return i;
                }
                p = p->last;

        }
        return i;

}

Node* LocateElem2(LinkList L, ElemType e)
{
        LinkList p = L->last;
        while (p!=L)
        {
                if (p->data==e)
                {
                        return p;
                }

        }
        return p;

}

Status ListInsert(LinkList* L, int i, ElemType e)
{
        int length = ListLength(*L)+1;
        if (i > length||i<1)
        {
                return ERROR;
        }

        LinkList p, s;
        p = (*L);
        int j = 0;
        while (j<i-1)
        {
                ++j;
                p = p->last;

        }
        /*if (j>i-1)
        {
                return ERROR;
        }*/
        s = new Node;
        s->data=e;
        s->last = p->last;
        p->last = s;
        return OK;

}

Status ListDelete(LinkList* L, int i, ElemType* e)
{
        int length = ListLength(*L);
        if (i>length||i<1)
        {
                return ERROR;
        }

        int j=0;
        LinkList p, q;
        p = *L;
        while (p->last!=*L &&j<i-1)
        {
                p = p->last;
                ++j;
        }
        /*if (j > i - 1)
        {
                return ERROR;
        }*/

        q = p->last;
        p->last = q->last;
        *e = q->data;
        delete q;
        return OK;

}
Status ListTraverse(LinkList L)
{
        LinkList p = L->last;
        while (p!=L)
        {
                visit(p->data);
                p = p->last;
        }
        cout << endl;
        return OK;
       


}
void CreatListHead(LinkList* L, int n)
{
        *L = new Node;
        (*L)->last = *L;
        LinkList p;

        for (int i=0;i<n;i++)
        {
                p = new Node;
                cin >> p->data;
                p->last = (*L)->last;
                (*L)->last = p;


        }


}



void CreatListTail(LinkList* L, int n)
{
        LinkList p, r;
        *L = new Node;
        (*L)->last = (*L);
        r = (*L);
        for (int i=0;i<n;i++)
        {
                p = new Node;
                cin >> p->data;
                r->last = p;
                r = p;

        }
        r->last = *L;

}


Node* FindLast(Node* L)
{
        Node* p = L->last;
        while (p->last != L)
        {
                p = p->last;
        }
        return p;

}

LinkList Connect(LinkList*La,LinkList*Lb)
{
        LinkList La_last, Lb_Last;
        LinkList p;
        La_last = FindLast(*La);
        Lb_Last = FindLast(*Lb);

        p = La_last->last;
        La_last->last = Lb_Last->last->last;
        delete Lb_Last->last;
        Lb_Last->last = p;
        return Lb_Last;


}



int main()
{
        int i;
        int j;
        int k;
        ElemType e;
        LinkList L;
        LinkList p;
        LinkList La, Lb;
        i = InitList(&L);
        cout << "初始化链表(1.成功 0.失败)"<<i<< endl;
       
        for (j=1;j<=5;j++)
        {
                ListInsert(&L, 1, j);
        }
        cout << "表头插入5个元素后,L.data=";
        ListTraverse(L);


        i = EmptyList(L);
        cout << "L是否为空(1.是 0.否)" << i << endl;

        i = ClearList(&L);
        cout << "清空L后ListLength(L)=" << ListLength(L) << endl;

        i = EmptyList(L);
        cout << "L是否为空(1.是 0.否)" << i << endl;


        for (j = 1; j <= 10; j++)
        {
                ListInsert(&L, j, j);
        }
        cout << "表尾插入10个元素后,L.data=";
        ListTraverse(L);


        GetElem(L, 5, &e);
        cout << "第5个元素的值为" << e << endl;

        e = 9;
        i=LocateElem(L, e);
       
        if (i == 0)
        {
                cout << "没有找到值为" << e << "的元素" << endl;
        }
        else
        {
                cout << "值为" << e << "的元素的位序为" << i << endl;
        }
        /*p=LocateElem2(L, e);
        cout << "值为" << e << "元素的地址为" << p<< endl;*/

       
        for (i = 1; i <= 2; i++)
        {
                ListDelete(&L, 1, &e);

        }
        cout << "删除第一和第二个元素以后,L.date=";
        ListTraverse(L);

        k = ListLength(L);
        int T = 0;
        for (int j=1;j<=k+1;j++)
        {
                T++;
                i = ListDelete(&L, 1, &e);
                        if(i==ERROR)
                        {
                                cout << "删除第" << T << "个元素失败" << endl;
                        }
                        else
                        {
                                cout << "删除第" << T << "个元素的值为" << e << endl;
                        }

        }

        i = EmptyList(L);
        cout << "L是否为空(1.是 0.否)" << i << endl;

        cout << "插入元素(头插法)" << endl;
        CreatListHead(&La, 5);
        cout << "整体创建L的元素(头插法)" << endl;
        ListTraverse(La);

        cout << "插入元素(尾插法)" << endl;
        CreatListTail(&Lb, 5);
        cout << "整体创建L的元素(尾插法)" << endl;
        ListTraverse(Lb);
       
        L = Connect(&La, &Lb);//Lb合并到La之后
        cout << "合并La,Lb后,L=";
        ListTraverse(L);



        return 0;
}
发现合并La,Lb以后L的元素出错,还有就是p指针接收不了locateElem2()函数的地址.
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-9 23:39:42 | 显示全部楼层
1094570635 发表于 2022-11-9 22:15
稍微自己写了下,加了点功能
#include
using namespace std;

问题不大
4个问题
1. DestroyList 函数漏了个 delete *L; 为什么会这样呢?
2. 不释放内存,也就是没有调用 DestroyList 函数,为什么会这样呢?
3. date ? or data ?
4. Connect 函数最后返回的结点错了,这里你应该是大意了吧,上面4个步骤都没问题,说明你应该是理解了这个合并的过程了,就是最后返回错结点了

  1. #include <iostream>

  2. using namespace std;

  3. #define OK 1
  4. #define ERROR 0
  5. #define TRUE 1
  6. #define FALSE 0

  7. typedef int Status;
  8. typedef int ElemType;
  9. typedef struct Node {
  10.     ElemType data;
  11.     struct Node *last;

  12. } Node, *LinkList;

  13. Status visit(ElemType c);
  14. Status InitList(LinkList *L);
  15. Status EmptyList(LinkList L);
  16. Status DestroyList(LinkList *L);
  17. Status ClearList(LinkList *L);
  18. int ListLength(LinkList L);
  19. Status GetElem(LinkList L, int i, ElemType *e);
  20. int LocateElem(LinkList L, ElemType e);
  21. Node *LocateElem2(LinkList L, ElemType e);
  22. Status ListInsert(LinkList *L, int i, ElemType e);
  23. Status ListDelete(LinkList *L, int i, ElemType *e);
  24. void CreatListHead(LinkList *L, int n);
  25. void CreatListTail(LinkList *L, int n);
  26. Status ListTraverse(LinkList L);

  27. Status visit(ElemType c) {
  28.     cout << c << " ";
  29.     return OK;
  30. }

  31. Status InitList(LinkList *L) {
  32.     *L = new Node;
  33.     if(!(*L)) {
  34.         return ERROR;
  35.     }
  36.     (*L)->last = *L;
  37.     return OK;
  38. }

  39. Status EmptyList(LinkList L) {
  40.     if(L->last != L) {
  41.         return FALSE;
  42.     } else {
  43.         return TRUE;
  44.     }
  45. }

  46. Status DestroyList(LinkList *L) {
  47. #if 0
  48.     LinkList p = (*L);
  49.     while((*L)->last != (*L)) {
  50.         p = (*L);
  51.         (*L) = (*L)->last;
  52.         delete p;
  53.     }
  54.     // 这里是不是少了这一句?
  55.     // 我不知道你为什么就是坚持要这么写,你看出错了吧
  56.     // 早跟你说过了,尽量避免直接操作底层结构
  57.     // 因为这样很容易出错,代码也不好理解,出了问题调试的时候也很麻烦
  58.     // 你就是不听
  59.     // 你看这里你就少写了这一句,这样就内存泄露了
  60.     delete *L;
  61. #endif
  62.     // 你看下面就两行代码,而且逻辑也非常清晰
  63.     // 这样写代码怎么可能会出问题呢?
  64.     ClearList(L);       // 清空链表
  65.     delete *L;          // 删除头结点
  66.     return OK;
  67. }

  68. Status ClearList(LinkList *L) {
  69.     LinkList p, q;
  70.     p = (*L)->last;
  71.     while(p != (*L)) {
  72.         q = p->last;
  73.         delete p;
  74.         p = q;
  75.     }
  76.     (*L)->last = (*L);
  77.     return OK;
  78. }

  79. int ListLength(LinkList L) {
  80.     int i = 0;
  81.     LinkList p = L->last;
  82.     while(p != L) {
  83.         i++;
  84.         p = p->last;
  85.     }
  86.     return i;
  87. }

  88. Status GetElem(LinkList L, int i, ElemType *e) {
  89.     int j = 1;
  90.     LinkList p = L->last;
  91.     while(p != L && j < i) {
  92.         p = p->last;
  93.         j++;
  94.     }
  95.     if(p == L || j > i) {
  96.         return ERROR;
  97.     }
  98.     *e = p->data;
  99.     return OK;
  100. }

  101. int LocateElem(LinkList L, ElemType e) {
  102.     LinkList p = L->last;
  103.     int i = 0;
  104.     while(p != L) {
  105.         ++i;
  106.         if(p->data == e) {
  107.             return i;
  108.         }
  109.         p = p->last;
  110.     }
  111.     return i;
  112. }

  113. Node *LocateElem2(LinkList L, ElemType e) {
  114.     LinkList p = L->last;
  115.     while(p != L) {
  116.         if(p->data == e) {
  117.             return p;
  118.         }
  119.     }
  120.     return p;
  121. }

  122. Status ListInsert(LinkList *L, int i, ElemType e) {
  123.     int length = ListLength(*L) + 1;
  124.     if(i > length || i < 1) {
  125.         return ERROR;
  126.     }

  127.     LinkList p, s;
  128.     p = (*L);
  129.     int j = 0;
  130.     while(j < i - 1) {
  131.         ++j;
  132.         p = p->last;
  133.     }
  134.     /*if (j>i-1)
  135.     {
  136.             return ERROR;
  137.     }*/
  138.     s = new Node;
  139.     s->data = e;
  140.     s->last = p->last;
  141.     p->last = s;
  142.     return OK;
  143. }

  144. Status ListDelete(LinkList *L, int i, ElemType *e) {
  145.     int length = ListLength(*L);
  146.     if(i > length || i < 1) {
  147.         return ERROR;
  148.     }

  149.     int j = 0;
  150.     LinkList p, q;
  151.     p = *L;
  152.     while(p->last != *L && j < i - 1) {
  153.         p = p->last;
  154.         ++j;
  155.     }
  156.     /*if (j > i - 1)
  157.     {
  158.             return ERROR;
  159.     }*/

  160.     q = p->last;
  161.     p->last = q->last;
  162.     *e = q->data;
  163.     delete q;
  164.     return OK;
  165. }
  166. Status ListTraverse(LinkList L) {
  167.     LinkList p = L->last;
  168.     while(p != L) {
  169.         visit(p->data);
  170.         p = p->last;
  171.     }
  172.     cout << endl;
  173.     return OK;
  174. }
  175. void CreatListHead(LinkList *L, int n) {
  176.     *L = new Node;
  177.     (*L)->last = *L;
  178.     LinkList p;

  179.     for(int i = 0; i < n; i++) {
  180.         p = new Node;
  181.         cin >> p->data;
  182.         p->last = (*L)->last;
  183.         (*L)->last = p;
  184.     }
  185. }

  186. void CreatListTail(LinkList *L, int n) {
  187.     LinkList p, r;
  188.     *L = new Node;
  189.     (*L)->last = (*L);
  190.     r = (*L);
  191.     for(int i = 0; i < n; i++) {
  192.         p = new Node;
  193.         cin >> p->data;
  194.         r->last = p;
  195.         r = p;
  196.     }
  197.     r->last = *L;
  198. }

  199. Node *FindLast(Node *L) {
  200.     Node *p = L->last;
  201.     while(p->last != L) {
  202.         p = p->last;
  203.     }
  204.     return p;
  205. }

  206. LinkList Connect(LinkList *La, LinkList *Lb) {
  207.     LinkList La_last, Lb_Last;
  208.     LinkList p;
  209.     La_last = FindLast(*La);
  210.     Lb_Last = FindLast(*Lb);

  211.     p = La_last->last;
  212.     La_last->last = Lb_Last->last->last;
  213.     delete Lb_Last->last;
  214.     Lb_Last->last = p;
  215.     //return Lb_Last;
  216.     return Lb_Last->last;
  217. }

  218. int main() {
  219.     int i;
  220.     int j;
  221.     int k;
  222.     ElemType e;
  223.     LinkList L;
  224.     LinkList La, Lb;
  225.     i = InitList(&L);
  226.     cout << "初始化链表(1.成功 0.失败)" << i << endl;

  227.     for(j = 1; j <= 5; j++) {
  228.         ListInsert(&L, 1, j);
  229.     }
  230.     cout << "表头插入5个元素后,L.data=";
  231.     ListTraverse(L);

  232.     i = EmptyList(L);
  233.     cout << "L是否为空(1.是 0.否)" << i << endl;

  234.     i = ClearList(&L);
  235.     cout << "清空L后ListLength(L)=" << ListLength(L) << endl;

  236.     i = EmptyList(L);
  237.     cout << "L是否为空(1.是 0.否)" << i << endl;

  238.     for(j = 1; j <= 10; j++) {
  239.         ListInsert(&L, j, j);
  240.     }
  241.     cout << "表尾插入10个元素后,L.data=";
  242.     ListTraverse(L);

  243.     GetElem(L, 5, &e);
  244.     cout << "第5个元素的值为" << e << endl;

  245.     e = 9;
  246.     i = LocateElem(L, e);

  247.     if(i == 0) {
  248.         cout << "没有找到值为" << e << "的元素" << endl;
  249.     } else {
  250.         cout << "值为" << e << "的元素的位序为" << i << endl;
  251.     }
  252.     /*p=LocateElem2(L, e);
  253.     cout << "值为" << e << "元素的地址为" << p<< endl;*/

  254.     for(i = 1; i <= 2; i++) {
  255.         ListDelete(&L, 1, &e);
  256.     }
  257.     //cout << "删除第一和第二个元素以后,L.date=";   // date ?
  258.     cout << "删除第一和第二个元素以后,L.date=";     // data ?
  259.                                                     // date ? or data ?
  260.     ListTraverse(L);

  261.     k = ListLength(L);
  262.     int T = 0;
  263.     for(int j = 1; j <= k + 1; j++) {
  264.         T++;
  265.         i = ListDelete(&L, 1, &e);
  266.         if(i == ERROR) {
  267.             cout << "删除第" << T << "个元素失败" << endl;
  268.         } else {
  269.             cout << "删除第" << T << "个元素的值为" << e << endl;
  270.         }
  271.     }

  272.     i = EmptyList(L);
  273.     cout << "L是否为空(1.是 0.否)" << i << endl;

  274.     cout << "插入元素(头插法)" << endl;
  275.     CreatListHead(&La, 5);
  276.     cout << "整体创建L的元素(头插法)" << endl;
  277.     ListTraverse(La);

  278.     cout << "插入元素(尾插法)" << endl;
  279.     CreatListTail(&Lb, 5);
  280.     cout << "整体创建L的元素(尾插法)" << endl;
  281.     ListTraverse(Lb);

  282.     DestroyList(&L);    // ******************************** 要释放内存的说 **********************
  283.     L = Connect(&La, &Lb); // Lb合并到La之后
  284.     cout << "合并La,Lb后,L=";
  285.     ListTraverse(L);

  286.     DestroyList(&L);    // ******************************** 要释放内存的说 **********************
  287.     return 0;
  288. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-10 00:33:09 | 显示全部楼层
人造人 发表于 2022-11-9 23:39
问题不大
4个问题
1. DestroyList 函数漏了个 delete *L; 为什么会这样呢?

LinkList Connect(LinkList* La, LinkList* Lb) {
    LinkList La_last, Lb_Last;
    LinkList p;
    La_last = FindLast(*La);
    Lb_Last = FindLast(*Lb);

    p = La_last->last;
    La_last->last = Lb_Last->last->last;
    delete Lb_Last->last;
    Lb_Last->last = p;
    return Lb_Last->last;
}最后这个return 是否可以返回*La,或者*Lb?我发现返回*La程序似乎可以运行,*Lb则会引发 异常“ p 是 0xFFFFFFFFFFFFFFF7“

关于这个
p=LocateElem2(L, e);
    cout << "值为" << e << "元素的地址为" << p<< endl;,我无法获取e的地址,并且输出cout以后往后的命令也不会显示
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-11-10 00:42:54 | 显示全部楼层
1094570635 发表于 2022-11-10 00:33
LinkList Connect(LinkList* La, LinkList* Lb) {
    LinkList La_last, Lb_Last;
    LinkList p;

你是没有理解了这个合并的过程吗?你上面那4行代码怎么写出来的?
delete Lb_Last->last;
这都把Lb的头结点删除了
多画图,不理解的地方画画图就理解了

1.png

‘‘‘
关于这个
p=LocateElem2(L, e);
    cout << "值为" << e << "元素的地址为" << p<< endl;,我无法获取e的地址,并且输出cout以后往后的命令也不会显示

’’’

什么?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-10 05:22

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表