您的位置:首页 > 其它

我对单向链表的学习

2015-09-11 16:13 155 查看
本文章主要是记述我对单向链表的理解:1.有头节点和无头结点链表的理解 2.有头结点链表的创建 ,显示,插入,删除,冒泡排序,逆置。

我对链表的理解就是将一个个结构体串联起来。一个个结构体在一个链表中就是一个节点,节点之间是由结构体指针联系起来的,也就是他们结构体中会包含一个同类型的*next指针,用来指向下一个节点的地址,这个就是节点的指针域,里面其他类型的数据就是节点的数据域。 头结点就是数据域为空(0),指针域是指向一个有效数据的一个结构体,它是一个节点,由malloc跟它分配了内存。

下面我用代码来分析:

首先创建一个结构体

typedef struct list
{
    int  data;//数据域
    struct list *next;//指针域
}node;


下面就是各个功能函数

1.创建一个带头结点的链表:

node *creat_link_list(int n)
{
    node *head,*p,*pre;
    int i;
    head=(node*)malloc(sizeof(node));//创建一个头结点
    head->next=NULL;
    pre=head;//用一个指针来指向这个头结点,这个指针是各个结点连接起来的关键

    for(i=0;i<n;i++)
    {
        p=(node*)malloc(sizeof(node));//创建我们需要的数据结点
        printf("input the %d data\n",i+1);
        scanf("%d",&p->data);
        pre->next=p;//将pre指向的结点和数据结点连接起来
        pre=p;//再把第一个数据结点的位置给pre指针
    }//如此循环,直到创建完你需要的结点
   
    p->next=NULL;    //然后将最后一个数据结点指向null,结束此单向链表
    return head;//返回头结点的地址

}




2.显示链表的数据

void printlist(node *head)
{
    node *p;
     
    p=head->next;//因为我们是有头结点的链表,所以head头结点的数据域为0,我们不需要,所以得把它的next地址给它

    int i=1;

    while(p)
    {
        printf("the (%d)data= %d\n",i,p->data);
        i++;
        p=p->next;
    }
    
}
按照上面的程序,一直打印出各个结点的信息(除了头结点的),直到我们的链表结束,null。

3.链表插入结点(这个函数的功能是插在某个结点的后面)

void insertlist(node *head,int i,int is_data,int n)
{
    node *p,*q;
    int j=0;
    p=head;
         
    while(j<i)        
    {     
        p=p->next;         //遍历这个链表,找到你需要插的那个结点,第一个数据结点的下标我给的1,所以才是j=0,j<i这样设置遍历条件,大家慢慢体会,也可以自己画图,如果是想在头结点后面插一个数据,则i就输入0。
        j++;        
    }    
    q=(node *)malloc(sizeof(node));//创建我们要插入的结点
    q->data=is_data;
    q->next=p->next;//找到位置后将这个结点的next给我们创建的结点,然后再将这个位置结点的next指向我们创建的结点
    p->next=q;
    
}








3.链表删除结点:

void delietelist(node *head,int i)
{
    node *p,*q;
    int j=0;
    p=head;

    while(j<i-1)//我们还是进行遍历,找到我们需要删除的结点的前一个结点位置,当然这里我们不能删除头结点,跟插入一样第一个数据结点我给的下标还是1,所以你想删除第一个数据结点的时候就只需要输入i=1
    {
        p=p->next;
        j++;
    }
    q=p->next;
    p->next=q->next;
    free(q);

}


这里为什么要找到删除结点的前一个位子呢?因为我们删了这个结点,但是还需要把这个结点的前后连接起来,组成一个链表,不然这里就断了,而且这个链表是单向的。

结点的删除很简单,只不过需要注意的是我们必须得把要删除的结点free掉,不然会造成内存泄露



4.链表的冒泡排序(按从小到大)

node * sort(node *head)
{
    node *p,*q;
    int temp;

    p=head->next;

    for(;p->next!=NULL;p=p->next)
    {
        for(q=p->next;q!=NULL;q=q->next)
        {
            if(p->data>q->data)
            {
                temp=q->data;
                q->data=p->data;
                p->data=temp;

            }
        }

    }
   return head;

}
这个没什么说的,思路就是冒泡的思想,实现的时候只需要将数据换乘链表的形式即可。

思路:就是将所有数据进行比较,小的放前面,第一次是所有数据比,最小的放第1个,然后是除了第一个数据的后面的再比较,最小的放第2个,以此类推。n个数据比较,

最多是比较n(n-1)/2,最少比较0次 ps:10个数据比较,最多就是9+8+7+.....+1,通项公式是前面那个式子。

5.链表的逆置(逆置后我仍然把它做成一个带头结点的链表,所以给创建了一个新的头结点new_h,把以前的那个free掉了)

node * reverse_list(node *head)
{
    node *p,*q,*r,*new_h;

    r=NULL;
    q=NULL;

    new_h=(node*)malloc(sizeof(node));

    p=head->next;

    while(p)
    {
        
        q=p->next;
        p->next=r;
        r=p;
        p=q;

    }
    head=NULL;
    new_h->next=r;
    return new_h;

}



q=p->next;

p->next=r;



r=p;

p=q;

第一次循环结束;

接下来继续循环



q=p->next;

p->next=r;



r=p;

p=q;

到最后逆置完所有数据



别忘记了我们还要插入头结点和将以前的那个头结点设置为null,这里有一点我改过的就是我以前将head结点free掉,现在是将其设置为null,如果是前者他们这个链表就没有null结束了,但是运行结果还是正确的,这里是我不懂的,反正2种方法最后运行还是可以的。



下面是我的main函数

int main(int argc,char *argv[])
{
    node * head;
    int i,data,n;
    
    printf("please input the number of the data list: \n");
    scanf("%d",&n);
    head=creat_link_list(n);
    printf("list elements:\n");
    printlist(head);
        
    printf("input the position of insert elements:\n");
    scanf("%d",&i);
    
    if(i>n)
    
    {    
        printf("lager than the ranger\n");
        
        exit(0);
    }
    
    else 
        printf("input data :\n");
        scanf("%d",&data);
    
        insertlist(head,i,data,n);
    
        printf("list elements\n");
    
        printlist(head);
        

        printf("input the position of delete elements:\n");
        scanf("%d",&i);
        delietelist(head,i);
        printlist(head);
        printf("sort the list\n");
        
        head=sort(head);
        printlist(head);

        printf("list the reverse list:\n");
        head=reverse_list(head);
        printlist(head);

    
        return 0;

}


下面是运行结果:



程序比较简单,应该会有bug,只是为了简单的学习一点链表。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: