单向循环链表的内存问题


//单向循环链表 
#include  
#include 
#include 
#pragma warning(disable: 4996)
//链表的类型定义 
typedef struct LNode
{
    int data;
    struct LNode* next;
}LNode, * LinkList;
//链表的初始化,创建一个有头空链表。 

//链表的建立 
//头插法 
void Creatlist_head(LinkList L, int n)
{
     LinkList q; int i;
    q = L;
    for (i = 0; i < n; i++)
    {
        LinkList p = (LNode*)malloc(sizeof(LNode));//创建新的节点 
        printf("please input\n");
        scanf("%d", &p->data);//给新节点数据域赋值 
        p->next = q->next;//插入新节点的指针域 ,p->next 是说明 p 的指向,而L->next 是指下一个指针域 
        q->next = p;//插入新节点的指针域 , L->next 是说明 L 的指向

    }

}

//尾插法
void Creatlist_tail(LinkList L, int n)
{
    LinkList q; int i;
    q = L;
    for (i = 0; i < n; i++)
    {
        LinkList p = (LNode*)malloc(sizeof(LNode));
        printf("intput:\n");
        scanf("%d", &p->data);
        q->next = p;//插入新节点的指针域 ,L->next 是说明 L 的指向
        q = p;//保证插入后的新节点一直是尾节点 

    }
    //q->next = NULL;
}
//打印函数 
void printList(LinkList L)
{
    LinkList p;//定义一个指针 
    p = L;//
    printf("output:\n");
    while (p->next != L)//只要不指向指向本身,就没有遍历完 
    {
        printf("%d ", p->next->data);//打印已经检索到的节点的数据 //p->data?
        p = p->next;//顺链操作 
    }
    printf("\n");
}


//删除函数(按值查找)
void deletList(LinkList L, int i)
{
    LinkList p;//定义一个临时指针 
    p = L;
    int k = 100;
    while (p->next != L)//只要遍历的指针不指向头
    {
        if (p->next->data == i)//
        {
            p->next = p->next->next;//
            printf("delete success!\n");
            return;
        }
        if (p->next->data != i)
        {
            p = p->next;
        }
    }
    printf("delete fail\n");

}
int main()
{
    LinkList L;

    L = (LNode*)malloc(sizeof(LNode));//创建新的节点
    L->next = L;//指向本身 

    printf("start Creattail: \n");
    Creatlist_tail(L, 5);
    printf("start Creathead: \n");
    Creatlist_head(L, 5);
    deletList(L, 5);
    printList(L);
    return 0;
}

我想问一下,我这个程序删除链表节点的时候出现内存错误,是什么地方出了问题吗

单向循环链表,尾插法void Creatlist_tail(LinkList L, int n)里少了最尾部插入的结点 p->next = L; ,不然就不是循环链表了,代码里出现的问题,不是删除链表节点的问题,删除结点函数没有问题。修改如下,改动处见注释,供参考:

//单向循环链表 
#include <stdio.h> 
#include <string.h>
#include <stdlib.h>
#pragma warning(disable: 4996)
//链表的类型定义 
typedef struct LNode
{
    int data;
    struct LNode* next;
}LNode, * LinkList;
//链表的初始化,创建一个有头空链表。 
//链表的建立 
//头插法 
void Creatlist_head(LinkList L, int n)
{
    LinkList q; int i;
    q = L;
    for (i = 0; i < n; i++)
    {
        LinkList p = (LNode*)malloc(sizeof(LNode)); 
        printf("please input\n");
        scanf("%d", &p->data);
        p->next = q->next; 
        q->next = p;
    }
}
//尾插法
void Creatlist_tail(LinkList L, int n)
{
    LinkList q; int i;
    q = L;
    for (i = 0; i < n; i++)
    {
        LinkList p = (LNode*)malloc(sizeof(LNode));
        printf("intput:\n");
        scanf("%d", &p->data);
        q->next = p;
        q = p;
        p->next = L;  //修改
    }
}
//打印函数 
void printList(LinkList L)
{
    LinkList p;
    p = L;
    printf("output:\n");
    while (p->next != L)
    {
        printf("%d ", p->next->data);
        p = p->next;
    }
    printf("\n");
}
//删除函数(按值查找)
void deletList(LinkList L, int i)
{
    LinkList p, tmp;//修改
    p = L;
    int k = 100;
    while (p->next != L)
    {
        if (p->next->data == i)
        {
            tmp = p->next;     //修改
            p->next = p->next->next;
            free(tmp);        //修改
            printf("delete success!\n");
            return;
        }
        //if (p->next->data != i) 修改
        //{                       修改
        p = p->next;
        //}                       修改
    }
    printf("find fail\n");   //修改
}
int main()
{
    LinkList L;
    L = (LNode*)malloc(sizeof(LNode));//创建新的节点
    L->next = L;//指向本身 

    printf("start Creattail: \n");
    Creatlist_tail(L, 5);

    printf("start Creathead: \n");
    Creatlist_head(L, 5);

    deletList(L, 5);
    printList(L);

    return 0;
}


//删除函数(按值查找)
void deletList(LinkList L, int i)
{
    LinkList p;//定义一个临时指针 
    p = L;
    int k = 100;
    while (p->next != L)//只要遍历的指针不指向头
    {
        if (p->next->data == i)//
        {
            p->next = p->next->next;//
            printf("delete success!\n");
            return;
        }
        if (p->next->data != i)
        {
            p = p->next;
        }
    }
    printf("delete fail\n");

}

删除结点的函数有问题,p等于L,p->next怎么可能会再指向L呢,k定义出来也没有用到,我修改一下吧:

//删除函数(按值查找)
void deletList(LinkList &L, int i)
{
    LinkList ptr = L->next;  // ptr 指向头结点的下一个位置
    LinkList pre = L;        // pre 紧跟着ptr
    while (ptr != NULL)//只要遍历的指针不指向空
    {
        if (ptr->data == i)//
        {
            // 如果ptr不是最后一个节点,pre跳过ptr
            if (ptr->next != NULL) {
                pre->next = ptr->next;
                printf("delete success\n");
                break;
            }
            // 如果ptr是最后一个结点,pre指向空
            else {
                pre->next = NULL;
                printf("delete success\n");
                // 下面这两行可加可不加,加了更安全
                ptr->next = NULL;
                free(ptr);
                break;
            }
        }
        pre = ptr;
        ptr = ptr->next;
    }
    printf("delete fail\n");

}