数据结构-3单向链表

单向链表

单向链表:注意和NULL指针的比较
typedef struct list{
    int data;                //数据区
    struct list *next;       //地址区
                    //程序顺序执行,这时不能使用Plist和List *
}List,*Plist;

1.创建头节点

Plist create_list()
{
    Plist p=malloc(sizeof(List));//Plist p=(Plist)malloc(sizeof(List))
           //void *malloc(size_t size),malloc没有具体类型返回值,要转换后使用,
           //有的编译器有隐式转换就可以不写(Plist),但是否具有隐式转换编译器有差异,没有的写(Plist)
    if(NULL==p)            //判断头节点是否创建成功
    {
        puts("create err");
        return NULL;    
    }
    p->next=NULL;         //防止野指针
}

2.插入(头插)

int insert_head(Plist P)    //链表插入(头插法)
{
    if(NULL==p)
        return -1;
    Plist q=malloc(sizeof(List));    //新建一个要插入的节点
    if(NULL==q)
    {
        puts("malloc err");
        return -1;    
    }
    q->next=p->next;           //17、18行不能交换顺序,否则会造成内存泄漏 
    p->next=q;
    return 0;
}

(尾插)

int insert_tail(Plist p)
{
    if(NULL==p)            //判断指针是否有指向
        return -1;        
  
    while(p->next!=NULL)  //找出尾指针,相当于在遍历链表,但最后指针指向尾指针而不是NULL
    {
        p=p->next;   
    }    //while(p->next=p->next->next)//可阅读性不好    
                    //类似于while(i=i+1)即while(i++)
   
    Plist q=malloc(sizeof(List));    //开辟一个新的节点用于插入尾部
    if(NULL==q)                      //新节点是否开辟成功
    {    
        perror("malloc");
        return -1;    
    }
    q->next=p->next;        //新的节点指向p->next(NULL) //q->next=NULL
    p->next=q;              //原来尾节点的next指向新节点  
    return 0;
}

(按位置插入)

int insert_pos(Plist p,int pos,int data)
{
    if(NULL==p) return -1;    //判断合法性
            //准备新节点
    Plist q=(Plist)malloc(sizeof(List));
    if(NULL==p)
         return -1;
    q->data=data;
    q->next=NULL;    
            //移动
    Plist tmp=p;     //定义一个指针指向pos-1的位置
    while(pos--)
        tmp=tmp->next;    //将tmp指向了pos-1的节点        //指向了要插入的位置:不算头节点再从0开始
            //插入新节点
    q->next=tmp->next;
    tmp->next=q;
    return 0;
}

3.删除节点

int delete_list(Plist p,int pos)  //删指定节点
{
    if(NULL==p||empty(p))
    {
        puts("del err");
        return -1;
    }
    while(--pos)        // --pos !!!!不是pos--因为删除一个节点,p应该在其上一个节点
    {
        p=p->next;
    }
    Plist q=p->next;     //定义一个指针记录要删除的节点
    p->next=q->next;     //p->next=p->next->next
    free(q);             //释放删除节点的空间
    return 0;
}
int delete_data(Plist p, int data)   //删指定数据
{
    if(NULL == p || empty_list(p))
    {
        puts("delete arg err");
        return -1;
    }
    //p = p->next;   //因为头节点不存数据,所以跳过头节点
    while(p->next != NULL)
    {
        if(p->next->data == data)
        {
            Plist q = p->next;
            p->next = q->next; //p->next = p->next->next;
            free(q);
        }
        else
        {
            p = p->next;
        }
    }


}
while(p)              //最后p指向NULL
while(p->next)        //p指向最后一个节点
while(p->next->next)  //p指向倒数第二个节点,常用与清除链表

3.改数据

int change_data(Plist p, int src_data, int dst_data)
{                        //源数据       想改为的数据
    if(NULL == p)
    {
        puts("change arg err");
        return -1;
    }
    while(p->next)
    { 
        if(p->next->data == src_data)    //判断是否是一个要修改的节点
        {
            p->next->data = dst_data;
        }       
        p = p->next;     //指针向后移动一位,若只改第一个出现的,直接break
    }
    return 0;
}

4.查数据

int select_list(Plist p,int pos)
{
    if(NULL==p||empty(p))
    {
        puts("select err");
        return -1;
    }
    while(pos--)    //pos--!!!在pos的地方停止//删除用的--pos,在pos节点前一个节点停止
    {
        p=p->next;
    }
    printf("%d\n",p->data);
    return 0;
}

5.show链接

void show(Plist p)    //show出链表中所有元素
{
    if(NULL == p || empty_list(p)){
        return ;
    }
    p = p->next;    //忽略掉头节点未赋值的数据0
    while(p != NULL)
    {
        printf("%d ", p->data);
        p = p->next;
    }
    puts("");
}

6.判断是否为空链表

int empty(Plist p)
{
    if(NULL==p)            //说明没传入
    {
        puts("emp err");
        return -1;
    }
    else if(NULL==p->next)    // 头节点的next为NULL即空链表
    {
        return 1;
    }
    else
    {
        return 0;
    }


}

7.清除链表

Plist clear_list(Plist p)
{
  
    if(NULL==p||empty(p))
    {
        puts("clear err");
        return NULL;
    }
    Plist q=NULL;
    if(!empty(p))
    {
        while(p->next)
        {
            q=p->next;
            p->next=p->next->next;    //p->next=q->next;
            free;        
        }    
    }
    return p;
    }
Plist clear_list(Plist p)
{
    int len=0;
    if(NULL==p||empty(p))
    {
        puts("clear err");
        return NULL;
    }
    Plist h=p;
    while(p->next)
    {
        p=p->next;
        len++;
    }
    p=h;
    while(len--)
    {
        p=h;
        while(p->next->next)
       {
            p=p->next;
        }
        Plist q=p->next;
        p->next=NULL;
        free(q);
    }
    return p;


}

8.主函数调用

int main(int argc, char *argv[])
{
   
    Plist p=crete_head();     //创建头节点
    Plist h=p;                //给头节点标志
    while(1)                  //一直输入int型数据,直到输入非数字字符结束
    {   
        int ret=scanf("%d",&data);    //ret表示scanf读取成功的个数,非数字就是0
        if(0>=ret)            //数字字符返回1,非数字返回其他
             break;
        insert_list(p,data);  //确认是数字,插入(头插)节点后
        p=p->next;
            //节点往后移
        //insert_tail(p,data);  //尾插,后面就不用加p=p->next了
    }   
    getchar();                //用于吃掉前面输入的非数字字符
    p=h;
                      //p重新指向头节点
    show(p);                  //查看自己创建的链表
    
     
    puts("please delete data :");
    scanf("%d",&pos);        //输入删除的节点
    delete_list(p,pos);
    show(p);

单向循环链表

注意判断条件NULL为phead即可(注意和头节点的比较)

1.创建链表头

Plist creat_head()
{
    Plist p=malloc(sizeof(List));
    if(NULL==p)
    {
        perror("create malloc");
        return NULL;    
    }
    p->next=p;   //循环的链表头
    return p;
}

2.尾插

int insert_tail(Plist p)
{
    if(NULL==p)
    {
        puts("head insert arg err");
        return -1;    
    }
    Plist phead=p;
    while(p->next!=phead)    //找到尾节点
        p=p->next;
        
    Plist q=malloc(sizeof(List));
    if(NULL==q)                
    {
        perror("insert malloc err");
        return -1;    
    }
    q->data = data;  //数据赋值
    q->next = p->next;  //q->next = phead;
    p->next = q;
    return 0;
}

3.删除数据

int delete_data(Plist p, int data)
{
    if(NULL == p || empty_list(p))
    {
        puts("delete arg err");
        return -1;
    }
    Plist phead = p;
    while(p->next != phead)        //p是头节点,p->next是第一个节点
    {
        if(p->next->data == data)
        {
            Plist q = p->next;
            p->next = q->next; //p->next = p->next->next;
            free(q);
        }
        else
        {
            p = p->next;
        }
    }

    return 0;
}

4.修改数据

int change_data(Plist p, int src_data, int dst_data)
{
    if(NULL == p)
    {
        puts("change arg err");
        return -1;
    }
    Plist phead = p;
    while(p->next != phead)    
    { 
        //判断是否是一个要修改的节点
        if(p->next->data == src_data)
        {
            p->next->data = dst_data;
        }
        //指针向后移动一位
        p = p->next;
    }
    return 0;
}

5.查找数据

Plist select_data(Plist p, int data)
{
    if(NULL == p || empty_list(p))
    {
        puts("select arg err");
        return NULL;
    }
    Plist phead = p;
    while(p->next != phead)
    {
        if(p->next->data == data){
            return p->next;
        }
        p = p->next; 
    }
    return NULL;
}

6.判断是否为空

int empty_list(Plist p)
{
    if(NULL == p){
        puts("empty arg err");
        return -1;
    }
    if(p == p->next)
        return 1;
    else
        return 0;

}

7.show

void show(Plist p)
{
    if(NULL == p || empty_list(p)){
        return ;
    }
    p = p->next;
    while(p != NULL){
        printf("%d ", p->data);
        p = p->next;
    }
    puts("");
}

7.清除链表(不去除头节点)

int clear_list(Plist p)
{
    if(NULL == p)
    {
        puts("clear arg err");
        return -1;
    }
    Plist q = NULL, phead = p;
    if(!empty_list(p))
    {
        while(p->next != phead)
        {
            q = p->next;
            p->next = p->next->next; //p->next = q->next;
            free(q);
        }
    }

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值