2023-03-25 单链表LinkList的基本操作

//单链表对钩

#include <stdio.h>
#include <stdbool.h>
#include <malloc.h>
typedef struct LNode
{
    int data;
    struct LNode *next;
}LNode,*LinkList;//相当于typedef struct LNode *LinkList;   LinkList a相当于struct LNode a

bool initLinkList(LinkList *L)//进行初始化,传入头指针所在的地址
{
    *L=(LNode *)malloc(sizeof(LNode));//新建一个头结点
    if(*L==NULL)//内存不足分配失败
    {
        return false;
    }
    else
    {
        (*L)->next=NULL;//将头结点的下一个节点设为NULL
        return true;
    }
}

LNode *GetElem(LinkList L,int i)//按位查找结点
{
    LNode *p;//存放最后返回的结点
    p=L->next;//先从第一个结点开始遍历
    if(i==0)
    {
        return L;//第零个节点是头指针?头结点是第一个结点?
    }
    if(i<1)
    {
        return NULL;
    }
    int j=1;//此时p在第一个结点处
    while(p!=NULL && j<i)
    {
        p=p->next;//第一次循环,p遍历到第二个结点
        j++;
    }
    return p;//返回p结点
}

LinkList List_HeadInsert(LinkList L)//头插法,最后插入的元素在第一个位置
{
    L = (LNode *)malloc(sizeof(LNode));
    L->next = NULL;//易忽略,头结点插入时要先将最后一个结点的next设为空
    int value;//结点的值即data
    scanf("%d",&value);
    LNode *s;
    while(value!=9999)
    {
        s=(LNode *)malloc(sizeof(LNode));//每次都拓展一个LNode大小的内存,并将开头地址强制转换为LNode*类型并赋值给s
        s->data = value;
        s->next = L->next;
        L->next = s;
        scanf("%d",&value);
    }
    return L;//返回单链表的头指针
}

LinkList List_TailInsert(LinkList L)//尾插法,在表的末尾进行插入
{
    int value;
    L=(LinkList)malloc(sizeof(LNode));
    LNode *s;//要插入的节点
    LNode *e=L;//表尾的节点
    scanf("%d",&value);
    while(value!=9999)
    {
        s=(LNode *)malloc(sizeof(LNode));//为插入节点扩充空间
        s->data=value;
        e->next=s;//此时e为未插入s前,L的表尾,将e的下一个节点指向s
        e=s;//此时s是最后一个节点,所以让e指向s的地址
        scanf("%d",&value);
    }
    e->next = NULL;//将下一个节点设为空
    return L;
}

LNode *LocateElem(LinkList L,int e)//按值来查找结点
{
    LNode *s;
    s=L->next;//先将s指向第一个结点来进行判断
    while(s!=NULL && e!=s->data)//如果s为空节点说明该值不存在,直接return 
    {
        s=s->next;
    }
    return s;
}

void LNode_TailInsert(LinkList L,int i,int e)//后插法(常用),在第i个位置上插入结点,data的值为e
{
    LNode *p=GetElem(L,i-1);//返回第i-1个节点,在GetElem中已经判断过插入位置的合法性
    LNode *s;//插入的节点,(野指针 指向未知变量)
    s=(LNode *)malloc(sizeof(LNode));//为什么不能直接LNode *s,然后进行插入s->data=e,必须要用malloc分配空间吗?->刚开始s指向的是一个未知变量是一个野指针,通过malloc来获取一个LNode大小的内存并让s指针指向他来完成指针的初始化,malloc相当于创建了只有一个元素的数组
    s->next=p->next;
    p->next=s;
    s->data=e;
}

void LNode_HeadInsert(LinkList L,int i,int e)//头插法,转换为后插法进行插入,将data值进行调换即可
{
    LNode *p=GetElem(L,i);
    LNode *s;
    s=(LNode *)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;
    int temp=p->data;
    p->data=s->data;
    s->data=temp;
}

void DeleteLNode(LinkList L,int i)//删除节点操作
{
    LNode *p;
    p=GetElem(L,i-1);//获取删除节点的前一个节点的地址
    LNode *q;
    q=p->next;//被删除的节点
    p->next=q->next;
    free(q);
}

int LinkList_length(LinkList L)//计算单链表长度
{
    LNode *p;
    p=L->next;
    int sum=0;
    while(p!=NULL)
    {
        sum++;
        p=p->next;   
    }
    return sum;
}

int main()
{
    LinkList L;//L即头指针
    //printf("%d \n",L->data);
    initlist(L);
    printf("%d \n",L->data);
    //printf("%p",L);//此时输出00400080
    //L = List_HeadInsert(L);//为什么要进行赋值操作,L是指针,函数不是在地址上对其进行修改的吗?->指针发生了改变?L的指向改变了?
    //printf("%p",L);//此时输出00B71988,如果不进行赋值操作,输出的仍然是00400080,指针指向的地址没有改变,L的本质也是个变量,只有地址才是不会变的
    //L=List_TailInsert(L);
    //int e;
    //e=GetElem(L,3)->data;
   // LNode *p;
    //p=LocateElem(L,666);
    //printf("%d",p->data);
    //printf("%d",e);

    //LNode_HeadInsert(L,3,6666);

    //DeleteLNode(L,3);
    //printf("%d",LinkList_length(L));

    return 0;
}
 

C++:

//单链表

#include <stdio.h>
#include <stdbool.h>
#include <malloc.h>
typedef struct LNode
{
    int data;
    struct LNode *next;
}LNode,*LinkList;//相当于typedef struct LNode *LinkList;   LinkList a相当于struct LNode a

bool initLinkList(LinkList &L)//进行初始化,传入头指针所在的地址
{
    L=(LNode *)malloc(sizeof(LNode));//新建一个头结点
    if(L==NULL)//内存不足分配失败
    {
        return false;
    }
    else
    {
        L->next=NULL;//将头结点的下一个节点设为NULL
        return true;
    }
}

LNode *GetElem(LinkList L,int i)//按位查找结点
{
    LNode *p;//存放最后返回的结点
    p=L->next;//先从第一个结点开始遍历
    if(i==0)
    {
        return L;//第零个节点是头指针?头结点是第一个结点?
    }
    if(i<1)
    {
        return NULL;
    }
    int j=1;//此时p在第一个结点处
    while(p!=NULL && j<i)
    {
        p=p->next;//第一次循环,p遍历到第二个结点
        j++;
    }
    return p;//返回p结点
}

LinkList List_HeadInsert(LinkList L)//头插法,最后插入的元素在第一个位置
{
    L = (LNode *)malloc(sizeof(LNode));
    L->next = NULL;//易忽略,头结点插入时要先将最后一个结点的next设为空
    int value;//结点的值即data
    scanf("%d",&value);
    LNode *s;
    while(value!=9999)
    {
        s=(LNode *)malloc(sizeof(LNode));//每次都拓展一个LNode大小的内存,并将开头地址强制转换为LNode*类型并赋值给s
        s->data = value;
        s->next = L->next;
        L->next = s;
        scanf("%d",&value);
    }
    return L;//返回单链表的头指针
}

LinkList List_TailInsert(LinkList L)//尾插法,在表的末尾进行插入
{
    int value;
    L=(LinkList)malloc(sizeof(LNode));
    LNode *s;//要插入的节点
    LNode *e=L;//表尾的节点
    scanf("%d",&value);
    while(value!=9999)
    {
        s=(LNode *)malloc(sizeof(LNode));//为插入节点扩充空间
        s->data=value;
        e->next=s;//此时e为未插入s前,L的表尾,将e的下一个节点指向s
        e=s;//此时s是最后一个节点,所以让e指向s的地址
        scanf("%d",&value);
    }
    e->next = NULL;//将下一个节点设为空
    return L;
}

LNode *LocateElem(LinkList L,int e)//按值来查找结点
{
    LNode *s;
    s=L->next;//先将s指向第一个结点来进行判断
    while(s!=NULL && e!=s->data)//如果s为空节点说明该值不存在,直接return 
    {
        s=s->next;
    }
    return s;
}

void LNode_TailInsert(LinkList L,int i,int e)//后插法(常用),在第i个位置上插入结点,data的值为e
{
    LNode *p=GetElem(L,i-1);//返回第i-1个节点,在GetElem中已经判断过插入位置的合法性
    LNode *s;//插入的节点,(野指针 指向未知变量)
    s=(LNode *)malloc(sizeof(LNode));//为什么不能直接LNode *s,然后进行插入s->data=e,必须要用malloc分配空间吗?->刚开始s指向的是一个未知变量是一个野指针,通过malloc来获取一个LNode大小的内存并让s指针指向他来完成指针的初始化,malloc相当于创建了只有一个元素的数组
    s->next=p->next;
    p->next=s;
    s->data=e;
}

void LNode_HeadInsert(LinkList L,int i,int e)//头插法,转换为后插法进行插入,将data值进行调换即可
{
    LNode *p=GetElem(L,i);
    LNode *s;
    s=(LNode *)malloc(sizeof(LNode));
    s->data=e;
    s->next=p->next;
    p->next=s;
    int temp=p->data;
    p->data=s->data;
    s->data=temp;
}

void DeleteLNode(LinkList L,int i)//删除节点操作
{
    LNode *p;
    p=GetElem(L,i-1);//获取删除节点的前一个节点的地址
    LNode *q;
    q=p->next;//被删除的节点
    p->next=q->next;
    free(q);
}

int LinkList_length(LinkList L)//计算单链表长度
{
    LNode *p;
    p=L->next;
    int sum=0;
    while(p!=NULL)
    {
        sum++;
        p=p->next;   
    }
    return sum;
}

int main()
{
    LinkList L;//L即头指针
    //printf("%d \n",L->data);
    initLinkList(L);
    printf("%d \n",L->data);
    //printf("%p",L);//此时输出00400080
    //L = List_HeadInsert(L);//为什么要进行赋值操作,L是指针,函数不是在地址上对其进行修改的吗?->指针发生了改变?L的指向改变了?
    //printf("%p",L);//此时输出00B71988,如果不进行赋值操作,输出的仍然是00400080,指针指向的地址没有改变,L的本质也是个变量,只有地址才是不会变的
    //L=List_TailInsert(L);
    //int e;
    //e=GetElem(L,3)->data;
   // LNode *p;
    //p=LocateElem(L,666);
    //printf("%d",p->data);
    //printf("%d",e);

    //LNode_HeadInsert(L,3,6666);

    //DeleteLNode(L,3);
    //printf("%d",LinkList_length(L));

    return 0;
}

 

posted @ 2023-03-25 17:48  正方形的被子  阅读(71)  评论(0编辑  收藏  举报