单链表相关

不连续的存储结构

包含n个节点,每个节点包含数据域和指针域,指针域指向下一个节点

下述链表指单链表。。  

头结点只有指针域,是整个链表入口,相关的遍历查询都需要从头指针开始,头结点数据域没有意义为一个随机值

#include "stdafx.h"
#include <stdio.h>
#include<iostream>
using namespace std;
//创建
typedef struct student
{
    int data;
    student * Next;
}Node,*pNode;

Node* CreateList(void)
{
    int len;
    int val;
    pNode pEnd=NULL;
    pNode pHead = (Node*)malloc(sizeof(Node));
    pEnd = pHead;    //尾指针先指向头节点,在此基础上增加新节点
    pEnd->Next = NULL;  //此时只有一个头结点,头结点的next指针指向NULL
    printf("please input the len:");
    scanf("%d",&len);
    for(int i=0;i<len;i++)
    {
        printf("请输入第 %d 个节点的数据:", i + 1);
        scanf("%d",&val);
        pNode pNew =(Node*)malloc(sizeof(Node));    //给新节点分配内存
        pNew->data = val;              //给新节点赋值
        pNew->Next=NULL;           //新节点下一个先为空
        pEnd->Next= pNew;         //尾指针的指针域指向新增加的节点
        pEnd = pNew;     //尾指针指向新节点,新节点变成尾节点
    }
    printf("list create success");
    return pHead;
}

//遍历
void printlist(pNode phead)
{
    pNode p = phead->Next;
    while(p)
    {
        cout<<p->data<<endl;      //通过尾节点的指针域是否为空判断链表是否已结束
        p =p->Next;
    }
}
void main()
{
    pNode mHead = CreateList();
    printlist(mHead);
    cin.get();
    cin.get();
}

其余啥的删除、反转等操作均在此基础上进行,有点绕但并不复杂,F10、F11多单步运行就行

增加查询与删除接口:

//查询
int getlistIndex(pNode pHead,int data)
{
    pNode p = pHead->Next;
    int index = 0;
    while(p)
    {
        if(data == p->data)
        {
            break;
        }
        else
        {
            index++;
            p =p->Next;
        }
    }
    if(!p)
    {
        cout<<"there is no data in the list"<<endl;
        return -1;
    }
    else
    {
        return (index+1);
    }
}

//删除整个list
void deletelist(pNode pHead)
{
    pNode p = pHead->Next;
    free(pHead);                       //删除头指针
    while(p)
    {
        pNode tmp = p ->Next;
        free(p);
        p = tmp;
    }
    cout<<"delete all list successed"<<endl;
}

这里主要记录一下头指针的删除,之前从其他地方看的时候是没有这一步的,后来把main函数改成这样后

void main()
{
    pNode mHead = CreateList();
    deletelist(mHead);
    pNode p1 = (Node*)malloc(sizeof(Node));
    //printlist(mHead);
    //int index = getlistIndex(mHead,5);
    //cout << "5 in listIndex is :"<<index<<endl;
    cin.get();
    cin.get();
}

看了一下,无论我们在deletelist中还是在main函数中去释放这个头指针的空间,都是可以并且有必要的,因为如果释放,新创建的p1开辟的空间就可以使用已经被释放的堆空间,单步调试时也确实如此,而如果未释放,p1将去开辟新的空间,而我们以为删除掉了list,实际却留下了多余的垃圾,所有无论我们什么时候去malloc或者new去占掉了内存,都需要去对应的free或者delele掉它,而如果指向这片空间的指针为全局指针,还需要将指针置空,避免野指针的产生。

原文地址:https://www.cnblogs.com/doulcl/p/10241113.html