Chinaunix首页 | 论坛 | 博客
  • 博客访问: 29330
  • 博文数量: 7
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 50
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-10 15:39
个人简介

。。

文章分类

全部博文(7)

文章存档

2016年(7)

我的朋友

分类: C/C++

2016-06-11 16:10:16

链表.xlsx

想要弄懂链表这东东,首先要弄懂链表节点的概念以对节点的操作 (不知道为啥图片传不了,就不用图解释了)。
想要创建一个单链表,首先要创建一个节点的结构体类型:
typedef struct node {
    DATATYPE data;  //存储数据
    struct node *next; //存储下一个节点的地址
}Linknode;
单链表的表现形式:一个头节点:数据区不放数据。 一个尾节点:指针为NULL。既然如此,那我们在头节点的指针区放上NULL,这就是一个空的单链表了;

基于此,我们就知道怎么创一个空链表了:
Linknode *create_linklist()
{
    Linknode *head;//创建一个头节点,然后申请空间,指针放NULL即可。
    head = (Linknode *)malooc(sizeof(Linknode));
    if(head == NULL){
        printf("Error.No free memory exist!");
        return;
    }
    head->next = NULL;
    return head; // 记得把头节点的地址返回。
}

Linknode * L = create_linklist();// 这样就完成了一个空的链表的创建

空的链表创建完了,那我们应该往里面添加节点了吧,每一个节点都代表着一个数据的存储,单链表节点的插入有两种方式: 

第一种: 头插法(这种方法最简单,但是数据存储顺序会反过来):
void insert_head_linklist(Linknode *head,DATATYPE data)
{
    Linknode *temp;  // 分配一个节点;
    temp = (Linknode *)malloc(sizeof(Linknode));//老调,申请空间,判断堆区还有没有空间,if语句都是。我后面的都不加了。
    temp->data = data;// 数据先存放进去
    temp->next = head->next;   //体会这种节点的指针指向下一个节点的地址的思想,然后想想这句跟后面一句为什么不可以反过来;
    head->next = temp;
}

第二种:尾插法(每次都要遍历到最后一个节点,麻烦,但是顺序和储存的顺序会相同):
void insert_tail_linklist(Linknode *head,DATATYPE DATA)
{
    Linknode *temp , *p;
    temp = (Linknode *)malloc(sizeof(Linknode));
    for(p = head; p->next  != NULL ; p = p->next)//循环遍历到尾节点,找到为NULL的那个节点,然后进行连接;
        ;
    temp->data = data;
    temp->next = NULL;
    p->next = temp;
    return;
}

单链表的清空原理(保存下一个节点的地址,然后free掉该节点的地址):
void clean_linklist(Linknode *head)
{
    Linknode *current;
    while(head  != NULL){
        current = head->next;
        free(head);
        head = current;
    }
}

单链表删除数据的原理:把目标节点的next给前一个节点的next,然后free掉目标节点,实现该 节点的后面跟前面一个节点对接。当然目标数可能不止一个,所以就要遍历整个链表咯。
void delete_linklist(Linknode *head, DATATYPE data)
{
    Linklist *p, *q;
    p = head->next;
    q = head;
    while(p != NULL){
        if(p->data == data){
            q->next = p->next;
            free(p);
            p = q->next; 
        }
        else{
            q = q->next;
            p = p->next;
        }
    }
}

其实链表就这两点规则, 加入数据跟删除数据的思想;其他都是类似的思维模式,下面讲讲有序插入跟排序。
有序插入(即在插入链表的时候就找好位置,按指定的顺序排序,有序插入的本质:插入的数据先找到属于它的位置,然后进行一次插入,每次插入数据都得从头节点开始遍历)
void insert_order_linklist(Linknode *head, DATATYPE data)
{
    Linknode *p = head;
    Linknode *temp;
    temp = (Linknode *)malloc(sizeof(Linknode));
    //此处省略if判断
   
    for(; p ->next != NULL && p->next->data < data ; p = p->next)
        ;
    temp->data = data;
    temp->next = p->next;
    p->next = temp;

    return;
}

注意: 链表加入数据就遍历一个 参数,p = head->next;如果是删减最好遍历两个参数,一前一后,p = head->next; q = head; 这样较为方便,还要注意到底是q->next != NULL  还是q != NULL ; 两者有啥区别。注意区分

单链表排序的原理:把表头悬空,然后一个一个取出来,插到空的表头上去,就成了。
void sort_linklist(Linknode *head)
{
    Linknode *p;
    Linknode *t;
    Linknode *q;
    p = head->next;
    head->next = NULL;
   //1.断开链表
    //2.把后面节点进行有序插入
    while(p != NULL){
        for(q = head; q->next != NULL && q->next->data < p->data; ){
            q = q->next;
        }
         // 体会&&的用法。&&两边的表达式可以替换吗?
        t = p->next; // 保存下一个节点的地址
        p->next = q->next; // 插入
        q->next = p;   
        p = t;  //进入下一个节点
     }
}

单链表的逆置的原理:(悬空表头,然后一个个取出以头插法的方式插入新的链表中)
void reverse_linklist(Linknode *head)
{
    Linknode *p , *t;
    p = head->next;
    head->next = NULL;
    while(p != NULL){
        t = p->next;  //保存后一个节点
        p->next = head->next;
        head->next = p;
        p = t;
    }
}


阅读(1563) | 评论(0) | 转发(0) |
0

上一篇:结构体

下一篇:linux之IO模型

给主人留下些什么吧!~~