单链表的基本操作 增删改查 逆置

1.初始化

2. 求表长

3.按位查找结点

4.按值查找节点

5.后插

6.前插

7.删除

8.头插法新建单链表

9.尾插法新建单链表

10.链表逆置

11.主函数

 12.总代码

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

typedef struct LNode{
    int data;
    struct LNode *next;
}LNode,*LinkList;

//单链表的初始化
bool InitList(LinkList &L)
{
       L= (LNode*)malloc(sizeof(LNode));
       L->next=NULL;
       return true;
}

//求单链表的表长
int Length(LinkList L)
{
    int i=0;
    LNode *p=L->next;
    while(p!=NULL)
    {
        p=p->next;
        i++;
    }
    return i;
}

//按序号查找表节点  返回的是节点的指针
LNode* GetElem(LinkList L,int i)
{
    LNode *p=L->next;
    int j=1;
    while(p!=NULL && j<i)
    {
        p=p->next;
        j++;
    }
    return p;
}

//按照值查找表节点
LNode* LocateElem(LinkList L,int e)
{
    LNode *p=L->next;
    while(p!=NULL && p->data!=e)
    {
        p=p->next;
    }
    return p;
}

//前插与后插:比如说有1 2 3 4 5 五个数,要插入一个数字在第三个数字的位置,后插操作是在第二个位置的后面进行插入
//而前插则是在插到第四个位置,然后将第四个位置的数据域和第三个位置的数据域换一下,偷偷地实现前插
//后插入某一个结点
bool After_InsertList(LinkList &L,int i,int e)
{
    LNode *p = GetElem(L,i-1);   //后插操作,首先要先找到第i-1个结点
    if(p==NULL)
        return false;   //如果插入的位置不合法,返回false
    else
    {
        LNode *s = (LNode*) malloc(sizeof (LNode));
        s->data=e;
        s->next=p->next;
        p->next=s;
        return true;
    }
}

//前插入某一个结点         思想是将 待插入的结点插入到已知结点的后面,而后交换数据域的部分,实现前插
bool Before_InsertList(LinkList &L,int i,int e)
{
    LNode *p = GetElem(L,i);
    if(p==NULL)
        return false;
    else
    {
        LNode *s = (LNode*) malloc(sizeof (LNode));
        s->next=p->next;
        p->next = s ;
        s->data=p->data;
        p->data=e;
        return true;
    }

}

//删除某一结点    删除的结点的值要带回主函数
bool DeleteList(LinkList &L,int i,int &e)
{
    LNode *p= GetElem(L,i-1);    //要删除结点的前一个结点
    if(p==NULL || p->next==NULL)
        return false;
    LNode *dep=p->next;             //dep是要删除的结点
    e=dep->data;
    p->next=dep->next;
    free(dep);
    return true;
}

//删除某一确定的结点*p
bool Delete2List(LNode *p)
{
    if(p==NULL)
        return false;
    if(p->next==NULL)
    {
       //这样的话如果要删除的p结点是最后一个的话,
       // 那么afp->next 就可能出现空指针的错误,所以要加个判断
       //这时如果要删除的话,则需要从表头依次遍历找到前一个结点
    }
    LNode *afp=p->next;    //afp 是指p的后继结点
    p->data=afp->data;
    p->next=afp->next;
    free(afp);
    return true;
}

//头插法新建单链表
LinkList List_HeadInsert(LinkList &L)
{
    L=(LinkList) malloc(sizeof (LinkList));
    L->next=NULL;
    LNode *s;
    int e;
    scanf("%d",&e);
    while(e!=9999)
    {
        s=(LNode*) malloc(sizeof (LNode));
        s->data=e;
        s->next=L->next;
        L->next=s;
        scanf("%d",&e);
    }
    return L;
}

//尾插法新建单链表
LinkList List_TailInsert(LinkList &L)
{
    L=(LNode*) malloc(sizeof(LNode));
    LNode *p,*s;
    p=L;
    int e;
    scanf("%d",&e);
    while(e!=9999)
    {
        s=(LNode*) malloc(sizeof(LNode));
        s->data=e;
        p->next=s;
        p=p->next;
        scanf("%d",&e);
    }
    s->next=NULL;
    return L;
}
//打印单链表的函数
void PrintList(LinkList L)
{
    LNode *p=L->next;
    while(p!=NULL)
    {
        printf("%d ",p->data);
        p=p->next;
    }
    printf("\n");
}

//链表的逆置
//迭代法设置三个指针实现
LinkList Iterate_InversionList(LinkList &L)
{
    LNode *begin,*mid,*end;
    begin=NULL;
    mid=L->next;
    end=mid->next;
    while(1)
    {
        mid->next=begin;
        if(end==NULL)
            break;
        begin=mid;
        mid=end;
        end=end->next;
    }
    L->next=mid;
    return L;
}

//头插法实现链表的逆置    这里使用了一个新的头结点用来原链表上摘下的结点
LinkList Head_InversionList(LinkList &L)
{
    LinkList LL=(LNode*) malloc(sizeof(LNode));           //LL表示逆置后的链表
    LL->next=NULL;
    LNode *p=L->next,*temp;
    while(p!=NULL)
    {
        temp=p;                     //摘除结点:使用一个临时结点存下来
        p=p->next;
        temp->next=LL->next;
        LL->next=temp;
    }
    return LL;
}

//就地逆置法实现  思想和头插法类似,就地对原链表进行修改
LinkList NoAddList_InversionList(LinkList &L)
{
    LNode *begin,*end;
    begin=L->next;
    end=begin->next;
    while(end!=NULL)
    {
        begin->next=end->next;
        end->next=L->next;
        L->next=end;
        end=begin->next;
    }
    return L;
}

int main() {
    LinkList L;
    InitList(L);
    //List_HeadInsert(L);
    //PrintList(L);
    List_TailInsert(L);
    PrintList(L);
    printf("The length of LinkList: %d\n", Length(L));
    After_InsertList(L,3,56);                //后插
    PrintList(L);
    Before_InsertList(L,2,89);              //前插
    PrintList(L);
    int e;
    DeleteList(L,6,e);                     //删除
    PrintList(L);
    printf("The deleted element:%d\n",e);
    Iterate_InversionList(L);               //迭代实现链表逆置
    PrintList(L);
    NoAddList_InversionList(L);            // 原地对原链表逆置
    PrintList(L);
    LinkList newL=Head_InversionList(L);      //这个函数中使用了一个新的头结点用来原链表上摘下的结点,所以L会变化
    PrintList(newL);
    PrintList(L);
    return 0;
}

//测试数据: 7 8 6 3 1 2  9999

 13.测试结果

注:本文为借鉴别的文章后,自己动手所写的内容,仅供学习参考,欢迎批评指正,学习交流!

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值