王道数据结构源码实战ch2线性表(顺序表+单链表+双链表)

顺序表

顺序的表结构体定义

typedef struct SqList   //和链表定义的单个节点不同,顺序表定义的结构体就是整个完整的表
{
    ElemType data[MaxSize];
    int length;
} SqList;

在顺序表L的第i个位置插入元素e

bool ListInsert(SqList &L,int i,ElemType e)  //在第i个位置插入e
{
    if(i<1||i>L.length+1)     //插入位置越界,失败
        return false;
    if(L.length>=MaxSize)  //长度已经达到上限,插入失败
        return false;
//i已经用作参数,使用j作为循环变量
    for(int j=L.length; j>=i; j--)  //data[length]开始是空的,所以从最右边元素开始依次右移,直到原来第i个元素(下标为i-1)变为第i+1(下标为i)个元素
    {
        L.data[j]=L.data[j-1];   //每轮都是小的给大的
    }
    L.data[i-1]=e;              //在现在空出来的第i个位置(下标为i-1)插入
    L.length++;                //插入后,长度+1
    return true;

}

删除顺序表L第i个位置的元素,并用e取出

bool ListDelete(SqList &L,int i,ElemType &e)  //删除第i个位置的元素,删之前用e保存
{
    if(i<1||i>L.length)    //删除位置越界,失败
        return false;
    if(L.length==0)     //顺序表为空,无法删除,失败
        return false;
    e=L.data[i-1];   //取出第i个元素(下标为i-1)
    for(int j=i; j<L.length; j++)  //开始第i个位置(下标为i-1)是空的,所以从第i+1(下标为i)个位置开始向左填充
        L.data[j-1]=L.data[j];   //每轮都是大的给小的
    L.length--;   //删除后,顺序表长度-1
    return true;
}

在顺序表L中查找e是第几个元素

int ListLocate(SqList &L,ElemType e)  //查找e是第几个元素
{
    for(int i=0; i<L.length; i++)
        if(L.data[i]==e)
            return i+1;     //下表为i代表第i+1个元素
    return 0;
}

完整代码

#include<bits/stdc++.h>
using namespace std;

#define MaxSize 50
typedef int ElemType;

typedef struct SqList   //和链表定义的单个节点不同,顺序表定义的结构体就是整个完整的表
{
    ElemType data[MaxSize];
    int length;
} SqList;

bool ListInsert(SqList &L,int i,ElemType e)  //在第i个位置插入e
{
    if(i<1||i>L.length+1)     //插入位置越界,失败
        return false;
    if(L.length>=MaxSize)  //长度已经达到上限,插入失败
        return false;
//i已经用作参数,使用j作为循环变量
    for(int j=L.length; j>=i; j--)  //data[length]开始是空的,所以从最右边元素开始依次右移,直到原来第i个元素(下标为i-1)变为第i+1(下标为i)个元素
    {
        L.data[j]=L.data[j-1];   //每轮都是小的给大的
    }
    L.data[i-1]=e;              //在现在空出来的第i个位置(下标为i-1)插入
    L.length++;                //插入后,长度+1
    return true;

}
bool ListDelete(SqList &L,int i,ElemType &e)  //删除第i个位置的元素,删之前用e保存
{
    if(i<1||i>L.length)    //删除位置越界,失败
        return false;
    if(L.length==0)     //顺序表为空,无法删除,失败
        return false;
    e=L.data[i-1];   //取出第i个元素(下标为i-1)
    for(int j=i; j<L.length; j++)  //开始第i个位置(下标为i-1)是空的,所以从第i+1(下标为i)个位置开始向左填充
        L.data[j-1]=L.data[j];   //每轮都是大的给小的
    L.length--;   //删除后,顺序表长度-1
    return true;
}

int ListLocate(SqList &L,ElemType e)  //查找e是第几元素
{
    for(int i=0; i<L.length; i++)
        if(L.data[i]==e)
            return i+1;     //下表为i代表第i+1个元素
    return 0;
}
void PrintList(SqList L)   //打印
{
    for(int i=0; i<L.length; i++)
        printf("%3d",L.data[i]);  //每个数字占三个字符,右对齐,左边用空格占位
    cout<<endl;                    //%md 表示:如果数据的位数小于 m,则左端补以空格,若大于 m,则按实际位数输出。
}                                            //%-md  左对齐
//%0md 右对齐,左边补0

int main()
{
    SqList L;
    bool ret;
    ElemType del;

    L.data[0]=1;
    L.data[1]=2;
    L.data[2]=3;
    L.length=3;

    ret=ListInsert(L,2,60); //第二个位置插入60
    if(ret)
    {
        cout<<"insert success!"<<endl;
        PrintList(L);
    }
    else
    {
        cout<<"insert fail!"<<endl;
    }

    ret=ListDelete(L,1,del);
    if(ret)
    {
        cout<<"delete success!"<<endl;
        PrintList(L);
    }
    else
    {
        cout<<"delete fail!"<<endl;
    }

    int elem_pos;  //用来接收元素的位置
    elem_pos=ListLocate(L,60);
    if(elem_pos)
    {
        cout<<"search success!"<<endl;
        cout<<elem_pos<<endl;
    }
    else
    {
        cout<<"search fail!"<<endl;
    }

    return 0;
}

单链表

单链表节点的定义

typedef struct LNode  //因为在定义内需要定义节点类型的指针,所以这里必须对类型命名
{
    //结构体定义链表的节点,与顺序表的定义整个表不同
    ElemType data;
    struct LNode *next;  //定义的递归,内部用到了结构体的类型
} LNode,*LinkList;        //定义了结构体类型,与指向该结构体的指针,前者从名字上更强调的是一个节点,后者强调的是一个链表

头插法建立单链表L

LinkList List_Head_Insert(LinkList &L) //头插法一次插入多个
{
    LNode*s;  //临时变量,暂时指向待插入的节点
    int x;  //临时变量,暂存数据

    L=(LinkList)malloc(sizeof(LNode));  //只有指针,要先生成头结点,L指向新生成的头结点
    L->next=NULL;  //至此,初始化完成,只有一个头结点

    scanf("%d",&x);        //第一次先读入x,才能进入while循环
    while(x!=9999)           //9999为约定的终止输入符号
    {
        s=(LNode*)malloc(sizeof(LNode));   //创建新的节点,用临时指针s指向
        s->data=x;     //给新节点放入数据

        s->next=L->next;  //挂右
        L->next=s;     //挂左
        scanf("%d",&x);
    }
    return L;
}

尾插法建立单链表L

LinkList List_Tail_Insert(LinkList &L)//尾插法一次插入多个
{
    int x;   //临时变量,暂存数据
    LNode*s,*r; //生成临时指针s,尾指针r

    L=(LinkList)malloc(sizeof(LNode));  //只有指针,要先生成头结点
    r=L;  //r指向尾部节点(第一次写时写错了)
    L->next=NULL;  //初始化完成,此时有且仅有,一个头结点和一个尾指针

    scanf("%d",&x);
    while(x!=9999)
    {
        s=(LNode*)malloc(sizeof(LNode));
        s->data=x;

        //可省略挂右,s->next=NULL;,因为只有最后一个插入的节点需要置NULL
        r->next=s;  //只需挂左
        r=s;  //r=r->next更能表明指针后移一位
        scanf("%d",&x);
    }
    r->next=NULL;  //重要,最后一个节点 置NULL,否则会异常。
    //不是NULL的话,默认指针的值为0xCDCDCDCD,不可访问,无法继续执行
    return L;
}

获取单链表L第i个节点的指针

LNode* GetElem(LinkList L,int i)  //获取第i个节点的指针
{
    LNode*p=L->next; //临时指针指向头结点后第一个元素 ,作为遍历的开始
    int j=1;   //设定p现在的位置为第一个

    if(i==0)   //第0个节点是头结点
        return L;
    if(i<0)    //越界,失败
        return NULL;

    while(p &&j<i)  //当前节点不为NULL,最后停留在i前一个位置。
    {
        p=p->next;
        j++;
    }
    return p;     //最后一次循环中,p又后移一个位置,正好就是第i个。
}

获取单链表L中元素value第一次出现的位置

int LocateElem(LinkList L,ElemType value) //找到第一个相等的值的位置就结束,不考虑后面有相同的值
{
    LNode*p=L->next;   //从头结点后一个元素开始
    int j=1;
    while(p&&(p->data)!=value)
    {
        p=p->next;
        j++;
    }
    return j;
}

在单链表L的第i个位置插入新节点(数据域为e)

bool ListFrontInsert(LinkList L,int i,ElemType e) //在第i个位置插入新节点(数据域为e)
{
    LNode* p=GetElem(L,i-1);    //p指向插入位置前一个节点的位置,作为开始
    if(p==NULL)
        return false;

    LNode* s=(LNode*)malloc(sizeof(LNode));  //s临时指向新生成的节点
    s->data=e;

    s->next=p->next;    //挂右
    p->next=s;    //挂左
    return true;
}

删除单链表L的第i个元素

bool ListDelete(LinkList L,int i)   //删除第i个元素
{
    LNode* p=GetElem(L,i-1);    //p指向删除位置前一个节点的位置
    if(p==NULL) return false;

    LNode* q=p->next;  //必须暂存待删除节点的指针,因为后一歩改变了P的后继,找不到待删除节点了,无法free空间
    if(q==NULL) return false;

    p->next=q->next;    //挂右

    free(q);  //暂存了待删除元素的位置,才能free
    q==NULL;   //处理野指针
    return true;
}

完整代码

#include<bits/stdc++.h>
using namespace std;

typedef int ElemType;

typedef struct LNode  //因为在定义内需要定义节点类型的指针,所以这里必须对类型命名
{
    //结构体定义链表的节点,与顺序表的定义整个表不同
    ElemType data;
    struct LNode *next;  //定义的递归,内部用到了结构体的类型
} LNode,*LinkList;        //定义了结构体类型,与指向该结构体的指针,前者从名字上更强调的是一个节点,后者强调的是一个链表

LinkList List_Head_Insert(LinkList &L) //头插法一次插入多个
{
    LNode*s;  //临时变量,暂时指向待插入的节点
    int x;  //临时变量,暂存数据

    L=(LinkList)malloc(sizeof(LNode));  //只有指针,要先生成头结点,L指向新生成的头结点
    L->next=NULL;  //至此,初始化完成,只有一个头结点

    scanf("%d",&x);        //第一次先读入x,才能进入while循环
    while(x!=9999)           //9999为约定的终止输入符号
    {
        s=(LNode*)malloc(sizeof(LNode));   //创建新的节点,用临时指针s指向
        s->data=x;     //给新节点放入数据

        s->next=L->next;  //挂右
        L->next=s;     //挂左
        scanf("%d",&x);
    }
    return L;
}

LinkList List_Tail_Insert(LinkList &L)//尾插法一次插入多个
{
    int x;   //临时变量,暂存数据
    LNode*s,*r; //生成临时指针s,尾指针r

    L=(LinkList)malloc(sizeof(LNode));  //只有指针,要先生成头结点
    r=L;  //r指向尾部节点(第一次写时写错了)
    L->next=NULL;  //初始化完成,此时有且仅有,一个头结点和一个尾指针

    scanf("%d",&x);
    while(x!=9999)
    {
        s=(LNode*)malloc(sizeof(LNode));
        s->data=x;

        //可省略挂右,s->next=NULL;,因为只有最后一个插入的节点需要置NULL
        r->next=s;  //只需挂左
        r=s;  //r=r->next更能表明指针后移一位
        scanf("%d",&x);
    }
    r->next=NULL;  //重要,最后一个节点 置NULL,否则会异常。
    //不是NULL的话,默认指针的值为0xCDCDCDCD,不可访问,无法继续执行
    return L;
}

LNode* GetElem(LinkList L,int i)  //得到第i个节点的指针
{
    LNode*p=L->next; //临时指针指向头结点后第一个元素 ,作为遍历的开始
    int j=1;   //设定p现在的位置为第一个

    if(i==0)   //第0个节点是头结点
        return L;
    if(i<0)    //越界,失败
        return NULL;

    while(p &&j<i)  //当前节点不为NULL,最后停留在i前一个位置。
    {
        p=p->next;
        j++;
    }
    return p;     //最后一次循环中,p又后移一个位置,正好就是第i个。
}

int LocateElem(LinkList L,ElemType value) //找到第一个相等的值的位置就结束,不考虑后面有相同的值
{
    LNode*p=L->next;   //从头结点后一个元素开始
    int j=1;
    while(p&&(p->data)!=value)
    {
        p=p->next;
        j++;
    }
    return j;
}

//不需要引用,因为头结点L不变
bool ListFrontInsert(LinkList L,int i,ElemType e) //在第i个位置插入新节点(数据域为e)
{
    LNode* p=GetElem(L,i-1);    //p指向插入位置前一个节点的位置,作为开始
    if(p==NULL)
        return false;

    LNode* s=(LNode*)malloc(sizeof(LNode));  //s临时指向新生成的节点
    s->data=e;

    s->next=p->next;    //挂右
    p->next=s;    //挂左
    return true;
}

bool ListDelete(LinkList L,int i)   //删除第i个元素
{
    LNode* p=GetElem(L,i-1);    //p指向删除位置前一个节点的位置
    if(p==NULL) return false;

    LNode* q=p->next;  //必须暂存待删除节点的指针,因为后一歩改变了P的后继,找不到待删除节点了,无法free空间
    if(q==NULL) return false;

    p->next=q->next;    //挂右

    free(q);  //暂存了待删除元素的位置,才能free
    q==NULL;   //处理野指针
    return true;
}

void ShowList1(LinkList L)  //打印链表
{
    L=L->next;    //先移动一次
    while(L)     //此后每次先打印再移动
    {
        cout<<L->data<<" ";
        L=L->next;
    }
    cout<<endl;
}

void ShowList2(LinkList L)//打印链表方法二,自己想的
{
    while(L->next!=NULL)  //每次先移动,再打印
    {
        L=L->next;
        cout<<L->data<<" ";
    }
    cout<<endl;
}

int main()
{
    LinkList L;  //定义单链表
    LNode* searching;  //用来保存指向第i个节点的指针,要操作的节点的前驱

    //List_Head_Insert(L);    //前插法建立单链表
    //cout<<endl<<"------------linked list generated by head insertion:------------"<<endl;
    //ShowList1(L);

    List_Tail_Insert(L);   //后插法建立单链表
    cout<<endl<<"------------linked list generated by tail insertion:------------"<<endl;
    ShowList1(L);

    ListFrontInsert(L,3,666);   //在第3个位置插入666
    cout<<endl<<"------------Insert 666 in the 3rd position:------------"<<endl;
    ShowList1(L);

    ListDelete(L,2); //删除第2个元素
    cout<<endl<<"------------delete the second element:------------"<<endl;
    ShowList1(L);

    searching=GetElem(L,2);    //得到第2个位置的指针
    cout<<endl<<"------------data element in 2nd position:------------"<<endl;
    cout<<(searching->data)<<endl;  //打印第二个位置的数据元素

    int pos=LocateElem(L,5);   //查找5第一次出现的位置
    cout<<endl<<"------------The position 5 where it first appears:------------"<<endl;
    cout<<pos<<endl;   //打印5第一次出现的位置

    //Test Data:
    //5 6 96  85 65 9999
    return 0;
}

双链表

双链表节点的定义

typedef struct DLNode
{
    ElemType data;
    struct DLNode *prior;
    struct DLNode *next;
} DLNode,*DLinkList;

头插法建立双链表DL

DLinkList Dlist_Head_Insert(DLinkList &DL)  //头插法
{
    int x;            //临时变量,暂存数据
    DLNode  * s;//临时变量,暂时指向待插入的节点


    DL=(DLinkList)malloc(sizeof(DLNode));
    DL->next=NULL;
    DL->prior=NULL;    //至此,初始化完成,只有一个头结点,两个指针域都为空

    cin>>x;   //先输入第一个元素,才能进入while循环
    while(x!=9999)     //9999为约定的终止输入符号
    {
        s=(DLNode*)malloc(sizeof(DLNode));    //创建新节点
        s->data=x;
//插入过程为:先挂右,右返回;再挂左边,左返回
        s->next=DL->next;   //挂右
        if(DL->next!=NULL)   //右边没有元素时,不需要返回挂上
        {
            DL->next->prior=s;   //右边有元素时,挂右(返回)
        }

        s->prior=DL;   //挂左
        DL->next=s;    //挂左(返回)

        cin>>x;
    }
    return DL;
}

尾插法建立单链表L

DLinkList Dlist_Tail_Insert(DLinkList &DL) //尾插法
{
    int x;            //临时变量,暂存数据
    DLNode * s; //临时变量,暂时指向待插入的节点

    DL=(DLinkList)malloc(sizeof(DLNode));  //先创建头结点,才能定义尾指针
    DLNode*r=DL;   //尾插法需要额外一个尾指针
    DL->prior=NULL;
    DL->next=NULL;  //至此,初始化完成,只有一个头结点,两个指针域都为空

    cin>>x;
    while(x!=9999)
    {
        s=(DLNode*)malloc(sizeof(DLNode));  //创建新节点
        s->data=x;

        r->next=s;   //挂左(返回)
        s->prior=r;   //挂左
        r=s; //r=r->next; 尾指针后移

        cin>>x;
    }
    r->next=NULL;
    return DL;
}

获取双链表DL第i个节点的指针

DLNode* GetElem(DLinkList DL,int i)  //获取第i个节点的指针
{
    DLNode*p=DL->next; //临时指针指向头结点后第一个元素 ,作为遍历的开始
    int j=1;   //设定p现在的位置为第一个

    if(i==0)  //第0个元素,返回头结点
        return DL;
    if(i<0)  //越界
        return NULL;

    while(p &&j<i)  //当前节点不为NULL,最后停留在i前一个位置。
    {
        p=p->next;
        j++;
    }
    return p;     //最后一次循环中,p又后移一个位置,正好就是第i个。
}

在双链表DL的第i个位置插入新节点(数据域为e)

bool DList_Front_Insert(DLinkList &DL,int i,int e)  //在第i个位置插入
{
    DLNode*p=GetElem(DL,i-1);   //找到待插入位置的前一个节点
    if(p==NULL) return false;

    DLNode*s=(DLNode*)malloc(sizeof(DLNode));  //创建新节点
    s->data=e;

//第一种方式
    s->next=p->next;   //挂右
    p->next->prior=s;  //挂右(返回)     //若在第一个位置插入,且此时只有头结点,需要特判这一句,此处忽略
    s->prior=p;   //挂左
    p->next=s;    //挂左(返回)

    //另一种挂新节点的方式
    /*
    s->next=p->next;  //挂右
    s->prior=p;   //挂左
    p->next=s;     //挂左(返回)
    s->next->prior=s  挂右(返回)
    */

    return true;
}

双链表的两种插入方式详解(王道和天勤):

在这里插入图片描述

在这里插入图片描述

删除单链表DL的第i个元素

bool DListDelete(DLinkList &DL,int i)  //删除第i个位置的元素
{
    DLNode*p =GetElem(DL,i-1);  //找到待删除位置的前一个节点
    if(p==NULL) return false;

    DLNode*q=p->next;   //保存待删除节点的指针,不然无法free空间
    if(q==NULL)  return false;

    p->next=q->next;     //挂右(可以指向NULL)
    if(q->next!=NULL)   //判断删除的是否最后一个节点
    {
        q->next->prior=p;  //挂左
    }
    free(q);
    q=NULL;   //处理野指针

    return true;
}

完整代码

#include<bits/stdc++.h>
using namespace std;

typedef int ElemType ;

typedef struct DLNode
{
    ElemType data;
    struct DLNode *prior;
    struct DLNode *next;
} DLNode,*DLinkList;

DLinkList Dlist_Head_Insert(DLinkList &DL)  //头插法
{
    int x;            //临时变量,暂存数据
    DLNode  * s;//临时变量,暂时指向待插入的节点


    DL=(DLinkList)malloc(sizeof(DLNode));
    DL->next=NULL;
    DL->prior=NULL;    //至此,初始化完成,只有一个头结点,两个指针域都为空

    cin>>x;   //先输入第一个元素,才能进入while循环
    while(x!=9999)     //9999为约定的终止输入符号
    {
        s=(DLNode*)malloc(sizeof(DLNode));    //创建新节点
        s->data=x;
//插入过程为:先挂右,右返回;再挂左边,左返回
        s->next=DL->next;   //挂右
        if(DL->next!=NULL)   //右边没有元素时,不需要返回挂上
        {
            DL->next->prior=s;   //右边有元素时,挂右(返回)
        }

        s->prior=DL;   //挂左
        DL->next=s;    //挂左(返回)

        cin>>x;
    }
    return DL;
}

DLinkList Dlist_Tail_Insert(DLinkList &DL) //尾插法
{
    int x;            //临时变量,暂存数据
    DLNode * s; //临时变量,暂时指向待插入的节点

    DL=(DLinkList)malloc(sizeof(DLNode));  //先创建头结点,才能定义尾指针
    DLNode*r=DL;   //尾插法需要额外一个尾指针
    DL->prior=NULL;
    DL->next=NULL;  //至此,初始化完成,只有一个头结点,两个指针域都为空

    cin>>x;
    while(x!=9999)
    {
        s=(DLNode*)malloc(sizeof(DLNode));  //创建新节点
        s->data=x;

        r->next=s;   //挂左(返回)
        s->prior=r;   //挂左
        r=s; //r=r->next; 尾指针后移

        cin>>x;
    }
    r->next=NULL;
    return DL;
}

DLNode* GetElem(DLinkList DL,int i)  //查找第i个节点的值
{
    DLNode*p=DL->next; //临时指针指向头结点后第一个元素 ,作为遍历的开始
    int j=1;   //设定p现在的位置为第一个

    if(i==0)  //第0个元素,返回头结点
        return DL;
    if(i<0)  //越界
        return NULL;

    while(p &&j<i)  //当前节点不为NULL,最后停留在i前一个位置。
    {
        p=p->next;
        j++;
    }
    return p;     //最后一次循环中,p又后移一个位置,正好就是第i个。
}

bool DList_Front_Insert(DLinkList &DL,int i,int e)  //在第i个位置插入
{
    DLNode*p=GetElem(DL,i-1);   //找到待插入位置的前一个节点
    if(p==NULL) return false;

    DLNode*s=(DLNode*)malloc(sizeof(DLNode));  //创建新节点
    s->data=e;

//第一种方式
    s->next=p->next;   //挂右
    p->next->prior=s;  //挂右(返回)     //若在第一个位置插入,且此时只有头结点,需要特判这一句,此处忽略
    s->prior=p;   //挂左
    p->next=s;    //挂左(返回)

    //另一种挂新节点的方式
    /*
    s->next=p->next;  //挂右
    s->prior=p;   //挂左
    p->next=s;     //挂左(返回)
    s->next->prior=s  挂右(返回)
    */

    return true;
}

bool DListDelete(DLinkList &DL,int i)  //删除第i个位置的元素
{
    DLNode*p =GetElem(DL,i-1);  //找到待删除位置的前一个节点
    if(p==NULL) return false;

    DLNode*q=p->next;   //保存待删除节点的指针,不然无法free空间
    if(q==NULL)  return false;

    p->next=q->next;     //挂右(可以指向NULL)
    if(q->next!=NULL)   //判断删除的是否最后一个节点
    {
        q->next->prior=p;  //挂左
    }
    free(q);
    q=NULL;   //处理野指针

    return true;
}

void ShowList2(DLinkList L)//自己想的
{
    while(L->next!=NULL)
    {
        L=L->next;
        cout<<L->data<<" ";
    }
    cout<<endl;
}

int main()
{
    DLinkList DL;  //定义双链表
    DLNode* searching;  //用来保存指向第i个节点的指针,要操作的节点的前驱

    Dlist_Head_Insert(DL);   //头插法
    cout<<endl<<"------------Double linked list generated by head insertion:------------"<<endl;
    ShowList2(DL);

    //cout<<endl<<"-----------Double linked list generated by tail insertion:-----------"<<endl;
    //Dlist_Tail_Insert(DL);    //尾插法
    //ShowList2(DL);

    searching=GetElem(DL,3);  //得到第3个位置的指针
    cout<<endl<<"----------------The data element in the 3rd position is:----------------"<<endl;
    cout<<(searching->data)<<endl;  //打印第3个位置的数据元素

    DList_Front_Insert(DL,2,666);  //在第2个位置插入666
    cout<<endl<<"--------------------Insert 666 in the 2nd position:--------------------"<<endl;
    ShowList2(DL);

    DListDelete(DL,666);   //删除666
    cout<<endl<<"-------------------------------Delete 666 :------------------------------"<<endl;
    ShowList2(DL);

    //Test Data:
    //5 6 96  85 65 9999
    return 0;
}

#define与typedef的区别

关键字typedef在编译阶段有效,由于是在编译阶段,因此typedef有类型检查的功能。

#define则是宏定义,发生在预处理阶段,也就是编译之前,它只进行简单而机械的字符串替换,而不进行任何检查

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WYF19999

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值