翻转带头结点的链表后 如何正确输出?如何正确释放内存?

发布于 2022-09-05 22:19:55 字数 4692 浏览 12 评论 0

#include <stdio.h>
#include <stdlib.h>

#define ERROR 0
#define OK 1
#define Overflow 2
#define Underflow 3
#define NotPresent 4
#define Duplicate 5
typedef int Status;
typedef char ElemType;

typedef struct Node {
    ElemType element;
    Node* link;
}Node;

typedef struct {
    Node* head;
    int n;
}HeaderList;

Status Init(HeaderList* h)
{
    h->head = (Node*)malloc(sizeof(Node));
    if (!h->head) return ERROR;
    h->head->link = NULL;
    h->n = 0;
    return OK;
}
Node*  ReverseHeaderList(HeaderList* h) {
    Node* prev = NULL;
    Node* head = h->head/*->link*/;

    Node* temp;
    while (head) {
        temp = head->link;
        head->link = prev;
        prev = head;
        head = temp;
    }
    return prev;
}

Status Find(HeaderList h, int i, ElemType* x)
{
    Node* p;
    int j;
    if (i < 0 || i > h.n - 1) return ERROR;
    p = h.head/*->link*/;
    for (j = 0; j <= i; j++) {
        p = p->link;
    }
    *x = p->element;
    return OK;
}
Status Insert(HeaderList* h, int i, ElemType x)
{
    Node *pCur, *pNext;
    int j;
    if (i < -1 || i > h->n - 1) return ERROR;

    pCur = h->head;
    for (j = 0; j <= i; j++) {
        pCur = pCur->link;
    }
    //pNext = (Node*)malloc(sizeof(Node));
    pNext = new Node;

    pNext->element = x;
    pNext->link = pCur->link;
    pCur->link = pNext;

    h->n++;
    return OK;
}

Status Delete(HeaderList* h, int i)
{
    Node *pCur, *pPre;
    if (!h->n /*|| !h->head*/) return ERROR;
    if (i < 0 || i > h->n - 1) return ERROR;
    pPre = h->head;
    for (int j = 0; j < i; j++) {
        pPre = pPre->link;
    }

    pCur = pPre->link;
    pPre->link = pCur->link;

    free(pCur);
    h->n--;
    return OK;
}

Status OutPut(HeaderList h)
{
    Node *pCur;
    if (!h.n) return ERROR;

    //Version 1
    pCur = h.head;//注意此处若加了link,则需先打印,再后移pCur
    while (pCur->link)
    {
        pCur = pCur->link;//①保证了头结点的element不打印(因为无意义)
                          //②(遍历到倒数第二个元素时)保证了循环体内可以打印出最后一个元素
        printf("%c ", pCur->element);
    }

    ////Version 2 & 3
    //pCur = h.head->link;//保证了头结点的element不打印(因为无意义)。注意此处加了link,需先打印元素,再后移pCur
    //while (pCur)//循环条件若为pCur->link,则循环结束后,最后一个元素还需打印
    //{
    //    printf("%c ", pCur->element);
    //    pCur = pCur->link;
    //}
    ////printf("%c ", pCur->element);//循环条件若为pCur->link,为打印出最后一个元素,需要在循环体外加上此句。
    printf("\n");
    return OK;
}

//因无法与OutPut(HeaderList h)的方法匹配,只好重写。
//暂未想出更好的方法可以与上面的方法相适应。
Status OutPut(Node* node)//不同之处:此处为先打印元素,再后移指针
{
    Node* p;
    if (/*!L.element ||*/ !node->link) return ERROR;
    p = node/*->link*/;
    while (p->link)//若不判断p->link,则最后一个p无后继结点,打印最后一个p的元素后,p继续后移,之后本应退出循环却未退出,导致结尾多打印出了一个‘?’
    {
        printf("%c ", p->element);
        p = p->link;
    }
    printf("\n");
    return OK;
}
void Destroy(HeaderList* h)
{
    Node* temp;
    Node* head = h->head;
    (*h).n = 0;
    while (head) {
        temp = head->link;
        free(head);
        head = temp;
    }
}

int main()
{
    int i;
    char x;
    HeaderList headerList;
    Init(&headerList);
    //    int insert;
    for (i = 0; i < 9; i++) {
        Insert(&headerList, i - 1,  'a' + i);//注意插入时,下标要从-1开始!(即i-1)
    }

    OutPut(headerList);

    Find(headerList, 0, &x);
    printf("Find(headerList, 0, &x): %c ,and then delete it from the HeaderList headerList...\n", x);

    Delete(&headerList, 0);
    OutPut(headerList);

    Insert(&headerList, 0, 'x');
    printf("\nInsert(&headerList,0,'x'): \n");
    OutPut(headerList);

    Insert(&headerList, -1, 'y');//i = -1 插入链表的下标0处!
    printf("\nInsert(&headerList,-1,'y'): \n");
    OutPut(headerList);

    printf("\nReverseHeaderList(&headerList): \n");
    Node* reversed = ReverseHeaderList(&headerList);
    HeaderList dummy;
    dummy.head = reversed;
    OutPut(dummy);//问题1:为什么这样输出有误?
    
    //问题2:这样输出直接崩溃了 WHY?
    //HeaderList* dummy2;
    //OutPut(*dummy2);

    OutPut(reversed);
    Destroy(&headerList);
    free(reversed);//问题3:这不报错!? 如何正确释放reversed的内存?
    return 0;
}

输出结果:
a b c d e f g h i
Find(headerList, 0, &x): a ,and then delete it from the HeaderList headerList...
b c d e f g h i

Insert(&headerList,0,'x'):
b x c d e f g h i

Insert(&headerList,-1,'y'):
y b x c d e f g h i

ReverseHeaderList(&headerList):
h g f e d c x b y ? //为什么此方法输出有误?
i h g f e d c x b y

代码如上。有三个小问题写在了对应注释里。(最后8行内)
第一次提问 希望大神们多多指教> <

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

只有一腔孤勇 2022-09-12 22:19:55

问题1:用你的方法将链表翻转后,y->link指向的是原来的头结点而不是NULL,所以会打印最后的问号。先输出i的原因看下面注释。

 pCur = h.head;//这时pCur为翻转后的i结点
    while (pCur->link)
    {
        pCur = pCur->link;//这一步将pCur变为了h结点,所以先输出了h,不会输出i
        printf("%c ", pCur->element);
    }

问题2:HeaderList* dummy2;在这里dummy是一个指针,使用前要先分配空间。所以正确代码应该如下,当然输出错误的原因和问题1一样。

    HeaderList* dummy2;
    dummy2 = new HeaderList;
    dummy2->head = reversed;
    OutPut(*dummy2);

问题3:没看懂你的问题是要释放整个链表所有结点的空间,还是只是释放reversed,如果是后者用delete(reversed)就可以,因为你是使用new申请的。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文