1094570635 发表于 2022-11-2 00:28:07

销毁链表操作问题

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


        return OK;
}
可否直接定义p=(*L),在循环里判断p是否为空,然后在移动*L的指针向下一个节点,然后删除p以后,重新定义p=(*L)?

人造人 发表于 2022-11-2 00:37:42

贴一下LinkList这个结构体的定义
还有初始化链表的函数
还有插入元素的函数
还有删除元素的函数

把这些都贴出来
你就贴一个销毁链表的函数,那我就只能通过这个销毁链表的函数去猜上面的那些函数和结构体定义
你直接贴出来不就好了,非要让我们去猜吗

人造人 发表于 2022-11-2 00:43:02

另外,销毁链表的这个函数有更好的写法
struct list_node_tag {
    void *data; size_t size;
    struct list_node_tag *next;
};

typedef struct {
    struct list_node_tag *head;
    size_t size;
} list_t;

void list_deinit(list_t *list) {
    if(!list) return;
    list_clean(list);
    free(list);
}


直接把这个链表清空了,然后释放头结点

清空也简单
如果当前链表不为空的话,那就一直删除当前链表的第0个元素
一直删除,直到当前链表为空了
bool list_clean(list_t *list) {
    if(!list) return false;
    while(!list_empty(list)) list_delete(list, 0);
    return true;
}


sh-5.1$ cat list.h
#ifndef _LIST_H_
#define _LIST_H_

#include <stddef.h>
#include <stdbool.h>

struct list_node_tag {
    void *data; size_t size;
    struct list_node_tag *next;
};

typedef struct {
    struct list_node_tag *head;
    size_t size;
} list_t;

list_t *list_init(void);
void list_deinit(list_t *list);
bool list_clean(list_t *list);
bool list_insert(list_t *list, size_t index, const void *data, size_t size);
bool list_delete(list_t *list, size_t index);
bool list_get(const list_t *list, size_t index, void *data, size_t size);
bool list_set(list_t *list, size_t index, const void *data, size_t size);
bool list_append(list_t *list, const void *data, size_t size);
size_t list_size(const list_t *list);
bool list_empty(const list_t *list);

#endif
sh-5.1$ cat list.c
#include "list.h"
#include <stdlib.h>
#include <memory.h>

list_t *list_init(void) {
    list_t *list = malloc(sizeof(*list));
    if(!list) return NULL;
    list->head = NULL;
    list->size = 0;
    return list;
}

void list_deinit(list_t *list) {
    if(!list) return;
    list_clean(list);
    free(list);
}

bool list_clean(list_t *list) {
    if(!list) return false;
    while(!list_empty(list)) list_delete(list, 0);
    return true;
}

bool list_insert(list_t *list, size_t index, const void *data, size_t size) {
    if(!list) return false;
    if(list_size(list) < index) return false;
    if(!data) return false;
    struct list_node_tag **current = &list->head;
    while(index--) current = &(*current)->next;
    struct list_node_tag *node = malloc(sizeof(*node));
    if(!node) return false;
    node->data = malloc(size);
    if(!node->data) {free(node); return false;}
    memcpy(node->data, data, size);
    node->size = size;
    node->next = *current;
    *current = node;
    ++list->size;
    return true;
}

bool list_delete(list_t *list, size_t index) {
    if(!list) return false;
    if(list_size(list) <= index) return false;
    struct list_node_tag **current = &list->head;
    while(index--) current = &(*current)->next;
    struct list_node_tag *temp = *current;
    *current = temp->next;
    free(temp->data); free(temp);
    --list->size;
    return true;
}

bool list_get(const list_t *list, size_t index, void *data, size_t size) {
    if(!list) return false;
    if(list_size(list) <= index) return false;
    if(!data) return false;
    struct list_node_tag *const *current = &list->head;
    while(index--) current = &(*current)->next;
    struct list_node_tag *temp = *current;
    if(temp->size > size) return false;
    memcpy(data, temp->data, temp->size);
    return true;
}

bool list_set(list_t *list, size_t index, const void *data, size_t size) {
    bool res = list_delete(list, index);
    return res ? list_insert(list, index, data, size) : res;
}

bool list_append(list_t *list, const void *data, size_t size) {
    if(!list) return false;
    return list_insert(list, list_size(list), data, size);
}

size_t list_size(const list_t *list) {
    if(!list) return 0;
    return list->size;
}

bool list_empty(const list_t *list) {
    if(!list) return true;
    return list_size(list) == 0;
}
sh-5.1$

1094570635 发表于 2022-11-2 12:41:36

人造人 发表于 2022-11-2 00:37
贴一下LinkList这个结构体的定义
还有初始化链表的函数
还有插入元素的函数


#include<iostream>
using namespace std;
#include"string.h"
#include"ctype.h"
#include"stdlib.h"

#include"math.h"
#include"time.h"

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

#define MAXSIZE 20

typedef int Status;
typedef int ElemType;

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

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

}Node;
typedef struct Node* LinkList;

Status InitList(LinkList *L)
{

        *L = new Node;
        if (!(*L))
        {
                return ERROR;
        }
        (*L)->next = NULL;
        return OK;

}

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

}



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


        return OK;
}
我的想法是,先直接用把头指针赋值给p,在循环里判断p是否为空,再销毁,这样是否可行

人造人 发表于 2022-11-2 13:23:11

1094570635 发表于 2022-11-2 12:41
#include
using namespace std;
#include"string.h"


二级指针?
Status InitList(LinkList *L)
再贴一下调用这个函数的代码
是main函数中调用的吧,贴一下main函数

1094570635 发表于 2022-11-2 13:36:57

人造人 发表于 2022-11-2 13:23
二级指针?
Status InitList(LinkList *L)
再贴一下调用这个函数的代码


#include<iostream>
using namespace std;
#include"stdio.h"
#include"string.h"
#include"ctype.h"
#include"stdlib.h"

#include"math.h"
#include"time.h"

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

#define MAXSIZE 20

typedef int Status;
typedef int ElemType;

Status visit(ElemType c)
{
        cout << c <<" ";
        return OK;
}
typedef struct Node
{
        ElemType data;
        struct Node* next;

}Node;
typedef struct Node* LinkList;

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

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

}


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

}

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

        }
        return OK;


}


int ListLength(LinkList L)
{
        int i = 0;
        LinkList p = L->next;
        while (p)
        {
                i++;
                p = p->next;
        }
        return i;


}

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

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

}

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


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

        while (p)
        {
                if (p->data != e)
                {
                        p = p->next;
                }

        }
        return p;


}

Status ListInsert(LinkList* L, int i, ElemType e)
{
        int j;
        LinkList p, s;
        p = *L;
        j = 1;
        while (p && j < i)
        {
                p = p->next;
                ++j;

        }
        if (!p||j>i)
        {
                return ERROR;
        }
        s = new Node;
        s->data = e;
        s->next = p->next;
        p->next = s;
        return OK;

}

Status ListDelete(LinkList *L,int i,ElemType*e)
{
        int j;
        LinkList p, q;
        p = *L;
        j = 1;
        while (p->next && j<i)
        {
                p = p->next;
                ++j;

        }
        if (!(p->next)||j>i)
        {
                return ERROR;
        }
        q = p->next;
        p->next = q->next;
        *e = q->data;
        delete(q);
        return OK;


}

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

void CreateListHead(LinkList *L,int n)
{
        LinkList p;
        int i;
        srand(time(0));
        *L = new Node;
        (*L)->next = NULL;
        for (i=0;i<n;i++)
        {
                p = new Node;
                p->data = rand() % 100 + 1;
                p->next = (*L)->next;
                (*L)->next = p;

        }

}

void CreateListTail(LinkList *L,int n)
{
        LinkList p, r;
        int i;
        srand(time(0));
        *L = new Node;
        r=*L;
        for (i=0;i<n;i++)
        {
                p = new Node;
                p->data = rand() % 100 + 1;
                r->next = p;
                r = p;

        }
        r->next = NULL;


}


int main()
{

        LinkList L;
        ElemType e;
        Status i;
        int j, k;
        i = InitList(&L);
        cout << "初始化L后:ListLength(L)=" << ListLength(L) << endl;
        for (j = 1; j <= 5; j++)
        {
                i = ListInsert(&L, 1, j);
        }
        cout << "在L的表头依次插入1~5后:L.date=" << endl;
        ListTraverse(L);
        cout << "ListLength(L)=" << ListLength(L) << endl;
        i = ListEmpty(L);
        cout << "L是否空:(1:是 0:否)" << i << endl;

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

        i = ListEmpty(L);
        cout << "L是否空:(1:是 0:否)" << i << endl;

        for (j=1;j<=10;j++)
        {
                ListInsert(&L, j, j);
               

        }
        cout << "在L的表尾依次插入1~10后:L.date=";
        ListTraverse(L);
        cout << "ListLength(L)=" << ListLength(L) << endl;

        ListInsert(&L, 1, 0);
        cout << "在L的表头插入0后:L.date=";
        ListTraverse(L);
        cout << "ListLength(L)=" << ListLength(L) << endl;

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

        for (j=3;j<=4;j++)
        {
                k = LocateElem(L, j);
                if (k)
                {
                        cout << "第" << k << "个元素的值为:" << j << endl;
                }
                else
                {
                        cout << "没有值为" << j << "的元素" << endl;
                }

        }

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

        cout << "依次输出L的元素:";
        ListTraverse(L);

        j = 5;
        ListDelete(&L, j, &e);
        cout << "删除第" << j << "个元素的值为:" << e << endl;
        cout << "依次输出L的元素:";
        ListTraverse(L);

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

        CreateListHead(&L, 20);
        cout << "整体创建L的元素(头插法)";
        ListTraverse(L);

        i = ClearList(&L);
        cout << "\n删除L后:ListLength(L)=" << ListLength(L) << endl;
        CreateListTail(&L, 20);
        cout << "整体创建L的元素(尾插法):";
        ListTraverse(L);

        i = ClearList(&L);
        cout << "\n删除L后:ListLength(L)=" << ListLength(L) << endl;

       


        system("pause");
        return 0;
}

1094570635 发表于 2022-11-2 13:42:10

人造人 发表于 2022-11-2 13:23
二级指针?
Status InitList(LinkList *L)
再贴一下调用这个函数的代码


DestroyList我自己加上去的,还没调用.

人造人 发表于 2022-11-2 14:07:01

1094570635 发表于 2022-11-2 13:42
DestroyList我自己加上去的,还没调用.

好的,我研究研究

人造人 发表于 2022-11-2 19:22:45

1094570635 发表于 2022-11-2 12:41
#include
using namespace std;
#include"string.h"


类似可不可以,能不能,对不对,这类问题,你完全可以试一试,试一试就知道可不可以,能不能,对不对了
问题有点多,写在注释里了

// 包含标准头文件要用尖括号 <>
// 双引号是先在当前目录下面找,找不到才去/usr/include下面找
/*
#include "ctype.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

#include "math.h"
#include "time.h"
*/

#include <iostream>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>

using namespace std;

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

#define MAXSIZE 20

typedef int Status;
typedef int ElemType;

// 把函数定义集中在一个地方,不要这里一个那里一个,看的时候不方便
/*
Status visit(ElemType c) {
    cout << c << " ";
    return OK;
}
*/

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

typedef struct Node *LinkList;

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

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

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

Status ClearList(LinkList *L) {
    LinkList p, q;
    p = (*L)->next;
    while(p) {
      q = p->next;
      //free(p);      // 这是什么操作?
                        // 用 new 关键字申请内存
                        // 然后用 free 函数释放内存?
      delete p;
      p = q;
    }
    (*L)->next = NULL;
    return OK;
}

#if 0
Status DestroyList(LinkList *L) {
    LinkList p;
    while(*L) {
      p = *L;
      *L = (*L)->next;
      delete p;
    }
    return OK;
}
#else
Status DestroyList(LinkList *L) {
    LinkList p = *L;
    while (p) {
      *L = (*L)->next;
      delete p;
      p = (*L);
    }
    return OK;
}
#endif

int ListLength(LinkList L) {
    int i = 0;
    LinkList p = L->next;
    while(p) {
      i++;
      p = p->next;
    }
    return i;
}

Status GetElem(LinkList L, int i, ElemType *e) {
    int j;
    LinkList p;
    p = L->next;
    j = 1;
    while(p && j < i) {
      p = p->next;
      j++;
    }
    if(!p || j > i) {
      return ERROR;
    }
    *e = p->data;
    return OK;
}

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

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

    while(p) {
      /*
      // 如果不是e的话,换下一个
      // 如果是e的话,怎么办?
      if(p->data != e) {
            p = p->next;
      }
      */

      if(p->data != e) {
            p = p->next;
      } else break;   // 退出循环对不对?
    }
    return p;
}

Status ListInsert(LinkList *L, int i, ElemType e) {
    int j;
    LinkList p, s;
    p = *L;
    j = 1;
    while(p && j < i) {
      p = p->next;
      ++j;
    }
    if(!p || j > i) {
      return ERROR;
    }
    s = new Node;
    s->data = e;
    s->next = p->next;
    p->next = s;
    return OK;
}

Status ListDelete(LinkList *L, int i, ElemType *e) {
    int j;
    LinkList p, q;
    p = *L;
    j = 1;
    while(p->next && j < i) {
      p = p->next;
      ++j;
    }
    if(!(p->next) || j > i) {
      return ERROR;
    }
    q = p->next;
    p->next = q->next;
    *e = q->data;
    delete(q);
    return OK;
}

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

void CreateListHead(LinkList *L, int n) {
    LinkList p;
    int i;
    //srand(time(0));       // 这个不能放在这里
    *L = new Node;
    (*L)->next = NULL;
    for(i = 0; i < n; i++) {
      p = new Node;
      p->data = rand() % 100 + 1;
      p->next = (*L)->next;
      (*L)->next = p;
    }
}

void CreateListTail(LinkList *L, int n) {
    LinkList p, r;
    int i;
    //srand(time(0));
    *L = new Node;
    r = *L;
    for(i = 0; i < n; i++) {
      p = new Node;
      p->data = rand() % 100 + 1;
      r->next = p;
      r = p;
    }
    r->next = NULL;
}

int main() {
    srand(time(NULL));// 这个函数调用应该放在这里
    LinkList L;
    ElemType e;
    Status i;
    int j, k;
    i = InitList(&L);
    cout << "初始化L后:ListLength(L)=" << ListLength(L) << endl;
    for(j = 1; j <= 5; j++) {
      i = ListInsert(&L, 1, j);
    }
    cout << "在L的表头依次插入1~5后:L.date=" << endl;
    ListTraverse(L);
    cout << "ListLength(L)=" << ListLength(L) << endl;
    i = ListEmpty(L);
    cout << "L是否空:(1:是 0:否)" << i << endl;

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

    i = ListEmpty(L);
    cout << "L是否空:(1:是 0:否)" << i << endl;

    for(j = 1; j <= 10; j++) {
      ListInsert(&L, j, j);
    }
    cout << "在L的表尾依次插入1~10后:L.date=";
    ListTraverse(L);
    cout << "ListLength(L)=" << ListLength(L) << endl;

    ListInsert(&L, 1, 0);
    cout << "在L的表头插入0后:L.date=";
    ListTraverse(L);
    cout << "ListLength(L)=" << ListLength(L) << endl;

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

    for(j = 3; j <= 4; j++) {
      k = LocateElem(L, j);
      if(k) {
            cout << "第" << k << "个元素的值为:" << j << endl;
      } else {
            cout << "没有值为" << j << "的元素" << endl;
      }
    }

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

    cout << "依次输出L的元素:";
    ListTraverse(L);

    j = 5;
    ListDelete(&L, j, &e);
    cout << "删除第" << j << "个元素的值为:" << e << endl;
    cout << "依次输出L的元素:";
    ListTraverse(L);

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

    DestroyList(&L);

    CreateListHead(&L, 20);
    cout << "整体创建L的元素(头插法)";
    ListTraverse(L);

    i = ClearList(&L);
    cout << "\n删除L后:ListLength(L)=" << ListLength(L) << endl;

    DestroyList(&L);

    CreateListTail(&L, 20);
    cout << "整体创建L的元素(尾插法):";
    ListTraverse(L);

    i = ClearList(&L);
    cout << "\n删除L后:ListLength(L)=" << ListLength(L) << endl;

    DestroyList(&L);

    //system("pause");      // 不是所有的环境都支持这个命令,尽量还是不要用
    return 0;
}

人造人 发表于 2022-11-2 19:51:23

#include <iostream>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>

using namespace std;

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

#define MAXSIZE 20

typedef int Status;
typedef int ElemType;

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

typedef struct Node *LinkList;

Status InitList(LinkList *L);
Status DestroyList(LinkList *L);
Status ClearList(LinkList *L);
Status ListInsert(LinkList *L, int i, ElemType e);
Status ListDelete(LinkList *L, int i, ElemType *e);
Status ListEmpty(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 ListTraverse(LinkList L);

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

// 函数也成对编写,写了初始化函数,下一个就写销毁函数
// 不然你很容易就把这个函数忘了
// 不然你打算什么时候写这个函数?
// 写完了其他的所有函数然后再写这个函数?
// 写到中途突然想起来了,然后再补上这个函数?
//
// 还有,你既然写了这些函数,为什么不用呢?
// 销毁链表的这个函数就是把整个链表删除掉么
// 你直接把链表清空了,然后释放头结点不就可以了
// 像你这样写,每一个函数都直接操作底层结构
// 不仅代码不好理解而且还非常容易出错
// 出了错,要调试程序也很不好调试
Status DestroyList(LinkList *L) {
    /*
    LinkList p;
    while(*L) {
      p = *L;
      *L = (*L)->next;
      delete p;
    }
    */
    ClearList(L);
    delete *L;
    *L = NULL;
    return OK;
}

// 清空链表也不需要直接操作底层结构吧
// 不仅代码不好理解而且还非常容易出错
// 调试的时候也是个麻烦
// 一直调用删除结点的函数,删除第0个结点,直到链表为空
Status ClearList(LinkList *L) {
    /*
    LinkList p, q;
    p = (*L)->next;
    while(p) {
      q = p->next;
      //free(p);      // 这是什么操作?
                        // 用 new 关键字申请内存
                        // 然后用 free 函数释放内存?
      delete p;
      p = q;
    }
    (*L)->next = NULL;
    */
    ElemType e;
    while(!ListEmpty(*L)) ListDelete(L, 1, &e);   // 你这从1开始数的吧,我们编程中从0开始数
    return OK;
}

Status ListInsert(LinkList *L, int i, ElemType e) {
    int j;
    LinkList p, s;
    p = *L;
    j = 1;
    while(p && j < i) {
      p = p->next;
      ++j;
    }
    if(!p || j > i) {
      return ERROR;
    }
    s = new Node;
    s->data = e;
    s->next = p->next;
    p->next = s;
    return OK;
}

Status ListDelete(LinkList *L, int i, ElemType *e) {
    int j;
    LinkList p, q;
    p = *L;
    j = 1;
    while(p->next && j < i) {
      p = p->next;
      ++j;
    }
    if(!(p->next) || j > i) {
      return ERROR;
    }
    q = p->next;
    p->next = q->next;
    *e = q->data;
    delete(q);
    return OK;
}

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

int ListLength(LinkList L) {
    int i = 0;
    LinkList p = L->next;
    while(p) {
      i++;
      p = p->next;
    }
    return i;
}

Status GetElem(LinkList L, int i, ElemType *e) {
    int j;
    LinkList p;
    p = L->next;
    j = 1;
    while(p && j < i) {
      p = p->next;
      j++;
    }
    if(!p || j > i) {
      return ERROR;
    }
    *e = p->data;
    return OK;
}

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

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

    while(p) {
      /*
      // 如果不是e的话,换下一个
      // 如果是e的话,怎么办?
      if(p->data != e) {
            p = p->next;
      }
      */

      if(p->data != e) {
            p = p->next;
      } else break;   // 退出循环对不对?
    }
    return p;
}

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

Status ListTraverse(LinkList L) {
    /*
    LinkList p = L->next;
    while(p) {
      visit(p->data);
      p = p->next;
    }
    cout << endl;
    */
    // 你这个求链表长度的函数应该把长度信息保存下来的
    // 这样每一次调用这个函数都遍历一遍链表
    // 虽然说可读性很重要,但是保证了可读性以后
    // 效率问题你也不能不管,除非他俩冲突了
    // 在顶层不要直接操作底层结构
    // 还是那句话
    // 不仅代码不好理解而且还非常容易出错
    // 调试的时候也是个麻烦
    // 你说把代码写成下面这样
    // 不好理解?不好调试?容易出错?
    for(int i = 1; i <= ListLength(L); ++i) {
      ElemType e;
      GetElem(L, i, &e);
      visit(e);
    }
    return OK;
}

void CreateListHead(LinkList *L, int n) {
    LinkList p;
    int i;
    //srand(time(0));       // 这个不能放在这里
    *L = new Node;
    (*L)->next = NULL;
    for(i = 0; i < n; i++) {
      p = new Node;
      p->data = rand() % 100 + 1;
      p->next = (*L)->next;
      (*L)->next = p;
    }
}

void CreateListTail(LinkList *L, int n) {
    LinkList p, r;
    int i;
    //srand(time(0));
    *L = new Node;
    r = *L;
    for(i = 0; i < n; i++) {
      p = new Node;
      p->data = rand() % 100 + 1;
      r->next = p;
      r = p;
    }
    r->next = NULL;
}

int main() {
    srand(time(NULL));// 这个函数调用应该放在这里
    LinkList L;
    ElemType e;
    Status i;
    int j, k;
    i = InitList(&L);
    cout << "初始化L后:ListLength(L)=" << ListLength(L) << endl;
    for(j = 1; j <= 5; j++) {
      i = ListInsert(&L, 1, j);
    }
    cout << "在L的表头依次插入1~5后:L.date=" << endl;
    ListTraverse(L);
    cout << "ListLength(L)=" << ListLength(L) << endl;
    i = ListEmpty(L);
    cout << "L是否空:(1:是 0:否)" << i << endl;

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

    i = ListEmpty(L);
    cout << "L是否空:(1:是 0:否)" << i << endl;

    for(j = 1; j <= 10; j++) {
      ListInsert(&L, j, j);
    }
    cout << "在L的表尾依次插入1~10后:L.date=";
    ListTraverse(L);
    cout << "ListLength(L)=" << ListLength(L) << endl;

    ListInsert(&L, 1, 0);
    cout << "在L的表头插入0后:L.date=";
    ListTraverse(L);
    cout << "ListLength(L)=" << ListLength(L) << endl;

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

    for(j = 3; j <= 4; j++) {
      k = LocateElem(L, j);
      if(k) {
            cout << "第" << k << "个元素的值为:" << j << endl;
      } else {
            cout << "没有值为" << j << "的元素" << endl;
      }
    }

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

    cout << "依次输出L的元素:";
    ListTraverse(L);

    j = 5;
    ListDelete(&L, j, &e);
    cout << "删除第" << j << "个元素的值为:" << e << endl;
    cout << "依次输出L的元素:";
    ListTraverse(L);

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

    DestroyList(&L);

    CreateListHead(&L, 20);
    cout << "整体创建L的元素(头插法)";
    ListTraverse(L);

    i = ClearList(&L);
    cout << "\n删除L后:ListLength(L)=" << ListLength(L) << endl;

    DestroyList(&L);

    CreateListTail(&L, 20);
    cout << "整体创建L的元素(尾插法):";
    ListTraverse(L);

    i = ClearList(&L);
    cout << "\n删除L后:ListLength(L)=" << ListLength(L) << endl;

    DestroyList(&L);

    //system("pause");      // 不是所有的环境都支持这个命令,尽量还是不要用
    return 0;
}

1094570635 发表于 2022-11-2 22:17:55

人造人 发表于 2022-11-2 19:51


srand(time(NULL))放在main函数里和放在main函数外有什么区别么

人造人 发表于 2022-11-2 22:23:40

1094570635 发表于 2022-11-2 22:17
srand(time(NULL))放在main函数里和放在main函数外有什么区别么

随机吗?
sh-5.1$ cat main.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void print(void) {
    srand(time(NULL));
    for(size_t i = 0; i < 10; ++i) {
      printf("%d ", rand());
    } puts("");
}

int main(void) {
    for(size_t i = 0; i < 10; ++i) {
      print();
    }
    return 0;
}
sh-5.1$ gcc -g -Wall -o main main.c
sh-5.1$ ./main
622341708 188212324 789665672 1213933180 693360735 231910325 1934037042 1317267579 709690999 2035198791
622341708 188212324 789665672 1213933180 693360735 231910325 1934037042 1317267579 709690999 2035198791
622341708 188212324 789665672 1213933180 693360735 231910325 1934037042 1317267579 709690999 2035198791
622341708 188212324 789665672 1213933180 693360735 231910325 1934037042 1317267579 709690999 2035198791
622341708 188212324 789665672 1213933180 693360735 231910325 1934037042 1317267579 709690999 2035198791
622341708 188212324 789665672 1213933180 693360735 231910325 1934037042 1317267579 709690999 2035198791
622341708 188212324 789665672 1213933180 693360735 231910325 1934037042 1317267579 709690999 2035198791
622341708 188212324 789665672 1213933180 693360735 231910325 1934037042 1317267579 709690999 2035198791
622341708 188212324 789665672 1213933180 693360735 231910325 1934037042 1317267579 709690999 2035198791
622341708 188212324 789665672 1213933180 693360735 231910325 1934037042 1317267579 709690999 2035198791
sh-5.1$ ./main
309819419 1067583074 1432107133 817694583 1616064653 1771008110 1623871959 1939448267 1355229725 1129497927
309819419 1067583074 1432107133 817694583 1616064653 1771008110 1623871959 1939448267 1355229725 1129497927
309819419 1067583074 1432107133 817694583 1616064653 1771008110 1623871959 1939448267 1355229725 1129497927
309819419 1067583074 1432107133 817694583 1616064653 1771008110 1623871959 1939448267 1355229725 1129497927
309819419 1067583074 1432107133 817694583 1616064653 1771008110 1623871959 1939448267 1355229725 1129497927
309819419 1067583074 1432107133 817694583 1616064653 1771008110 1623871959 1939448267 1355229725 1129497927
309819419 1067583074 1432107133 817694583 1616064653 1771008110 1623871959 1939448267 1355229725 1129497927
309819419 1067583074 1432107133 817694583 1616064653 1771008110 1623871959 1939448267 1355229725 1129497927
309819419 1067583074 1432107133 817694583 1616064653 1771008110 1623871959 1939448267 1355229725 1129497927
309819419 1067583074 1432107133 817694583 1616064653 1771008110 1623871959 1939448267 1355229725 1129497927
sh-5.1$ ./main
1856954868 701028812 1663808150 54317787 267359868 1652272965 2111498861 2143152743 527631056 1505733998
1856954868 701028812 1663808150 54317787 267359868 1652272965 2111498861 2143152743 527631056 1505733998
1856954868 701028812 1663808150 54317787 267359868 1652272965 2111498861 2143152743 527631056 1505733998
1856954868 701028812 1663808150 54317787 267359868 1652272965 2111498861 2143152743 527631056 1505733998
1856954868 701028812 1663808150 54317787 267359868 1652272965 2111498861 2143152743 527631056 1505733998
1856954868 701028812 1663808150 54317787 267359868 1652272965 2111498861 2143152743 527631056 1505733998
1856954868 701028812 1663808150 54317787 267359868 1652272965 2111498861 2143152743 527631056 1505733998
1856954868 701028812 1663808150 54317787 267359868 1652272965 2111498861 2143152743 527631056 1505733998
1856954868 701028812 1663808150 54317787 267359868 1652272965 2111498861 2143152743 527631056 1505733998
1856954868 701028812 1663808150 54317787 267359868 1652272965 2111498861 2143152743 527631056 1505733998
sh-5.1$


这次呢?
sh-5.1$ cat main.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void print(void) {
    for(size_t i = 0; i < 10; ++i) {
      printf("%d ", rand());
    } puts("");
}

int main(void) {
    srand(time(NULL));
    for(size_t i = 0; i < 10; ++i) {
      print();
    }
    return 0;
}
sh-5.1$ gcc -g -Wall -o main main.c
sh-5.1$ ./main
604538296 2098009029 1943287262 1134277048 691591644 1734807552 1141163187 1598981568 1110326647 926720166
1280765619 925259797 1531292135 535109179 1807699930 627452508 363372486 1657580384 1114987402 549412905
1064633975 1831256037 696164448 1512799187 1346119176 440842551 1791863202 1299382204 1907251982 2050305124
1460225360 364306630 2000830506 1256028974 1498583678 544938502 843352879 492263217 2143920070 1953679526
1418983383 1277202041 731455675 802791870 1812311221 391671958 1430244379 28200059 2049252342 397748133
577612964 966402669 81520522 1273777412 331718208 1427639699 1714619964 2123581410 579538255 1474388298
2026402887 2039763615 1838694929 1879749745 1148308942 1189794959 277204599 1991661821 1682058177 273641021
1797857699 953557912 1550843063 381829727 1756349783 1215670636 773501685 1039110514 1243870695 675270379
1436858647 1821483659 1641673049 1518379169 947777423 1973391257 798535220 514913739 1949489020 1378073475
1989302038 1828408259 1270353443 1680513319 1560674356 271178737 722824630 1837878955 115356910 257399159
sh-5.1$ ./main
310365455 850295180 1533523813 1833653220 1638556381 1152195453 1930831935 1176269331 1786692242 52166530
247849199 1297309432 1340345886 670349144 745099189 566194257 781639658 112433388 1560831106 2003963485
187781269 374653867 97139095 1285373098 811019729 1516350275 153410633 700769066 1086789438 1719916274
702639393 1397154893 422727806 88679558 1083324466 2061284188 1240875011 866672753 1090069871 880083605
918839284 1337919070 29909390 111701522 2008268215 775008579 677895779 642424225 887441968 91243238
498904063 1075223237 465897105 596043158 213112688 1276916834 2112393433 366523321 1977685900 1051699223
2086439595 532841645 301370468 361683754 621521203 1384694934 275484294 1862396214 103884040 1365554165
594996172 1022723324 555989588 624905562 1134424846 416774155 1399914141 1812320626 1059198380 139872461
1903563864 1558102443 1215095699 221977321 6661953 1428208387 1498894155 2119055386 1794731708 1329096407
1023270961 1733687655 1861938053 1324641430 2095371409 335975608 561852716 223372055 50888175 665736756
sh-5.1$ ./main
2138366949 651774460 17685022 354820966 408978915 1605136285 1609489056 1792811891 1344285063 1279934718
247637312 1616333678 21002565 1830373291 693870498 438889079 1141355915 641469207 1926992359 167102960
298566905 2043313712 487546415 956825062 160564149 342911285 1617410101 1037496453 144025691 176220700
853068847 134908992 827995160 870753869 489729958 1236974075 328406506 2099219015 882302318 1672691569
1231670085 1129939630 1141541599 1252672650 812829273 1835412097 1691561730 1954185188 329397657 1471070441
2121288149 627964562 1366900505 461350916 1584789624 1527464654 804262201 1054716078 417477460 948287893
1230936778 1270546307 1083196885 2058931938 2141300176 1572926844 1148422365 322223035 1524662211 2030724683
1994914604 608848648 1013180665 988972556 1861521298 1826009939 676901005 1405599380 1632711479 1006298662
729186173 1606515980 1634263225 2096086678 2067866896 1071569201 1476067685 724645450 2126285279 1893545145
1672933343 1209738409 1016607804 608646580 1121186699 1010424332 34089776 122125416 1332647367 1558751987
sh-5.1$ ./main
2138366949 651774460 17685022 354820966 408978915 1605136285 1609489056 1792811891 1344285063 1279934718
247637312 1616333678 21002565 1830373291 693870498 438889079 1141355915 641469207 1926992359 167102960
298566905 2043313712 487546415 956825062 160564149 342911285 1617410101 1037496453 144025691 176220700
853068847 134908992 827995160 870753869 489729958 1236974075 328406506 2099219015 882302318 1672691569
1231670085 1129939630 1141541599 1252672650 812829273 1835412097 1691561730 1954185188 329397657 1471070441
2121288149 627964562 1366900505 461350916 1584789624 1527464654 804262201 1054716078 417477460 948287893
1230936778 1270546307 1083196885 2058931938 2141300176 1572926844 1148422365 322223035 1524662211 2030724683
1994914604 608848648 1013180665 988972556 1861521298 1826009939 676901005 1405599380 1632711479 1006298662
729186173 1606515980 1634263225 2096086678 2067866896 1071569201 1476067685 724645450 2126285279 1893545145
1672933343 1209738409 1016607804 608646580 1121186699 1010424332 34089776 122125416 1332647367 1558751987
sh-5.1$

人造人 发表于 2022-11-2 22:24:38

srand函数是做什么用的?
页: [1]
查看完整版本: 销毁链表操作问题