链表的基本操作之插入、删除、逆置

上一篇写了有关链表的创建和遍历等相关内容,今天就来讲讲有关链表的其他操作吧。
提到链表,无非就是指针指来指去,最终连成一个链。好多人困惑的地方就在于p->next=r->next,指针到底是如何指向的,弄清楚这个,删、查、排的操作也就很容易弄懂了。大家都知道‘=’是赋值运算符吧,它左边是变量,右边是常量,既然了解了这些,那么让我们回到p->next=r->next这个表达式上,p->next既然是变量,它表示p这个指针的next的指向,而r->next是常量,它代表的是r指针的next的指向的位置,综合一下左右两端,就是p这个指针的下一个指向是r指针的next的指向的位置。可能这样有点绕,但你画个图,结合这句话,相信你一定会懂得。
先来讲一下插入吧,前面不是创建链表时讲了头插和尾插法嘛,其实就是那样的思想,只不过这只是插一个元素,插完后就要将链表连起来,注意一定要先连接的是后面。插入分为三种,头插、尾插、在中间随机插。在这儿我们就以不带头结点的创建链表的方式为例吧,在这儿就只写插入的代码吧。

struct Node *Insert(struct Node *head)//头插法 
{
    struct Node *p;
    p=(struct student *)malloc(sizeof(struct student));
    scanf("%d",&p->date);
    p->next=head;
    head=p;
    return head;
 }
struct Node *Insert(struct Node *head)//尾插法 
{
    struct Node *p,*t=head;
    while(t&&t->next!=NULL){
        t=t->next;
    } 
    p=(struct student *)malloc(sizeof(struct student));
    scanf("%d",&p->date);
    t->next=p;
    p->next=NULL;
    return head;
 }
struct Node *Insert(struct Node *head,int Date)//在链表中插入 
{
    struct Node *p,*t=head;
    while(t&&t->date!=Date){
        t=t->next;
    } 
    p=(struct student *)malloc(sizeof(struct student));
    scanf("%d",&p->date);
    p->next=t->next;
    t->next=p; 
    return head;
 }

至于用头插法和尾插法创建的链表,我们就需要做点小小的改动,因为我们知道它们创建的链表的头结点都是空的,没有数据域,因此我们在对它们操作时,就要从head->next 开始,这样插入的头插法就有点变动了,有点类似在链表中插入,具体的可以自己试试,万一还是搞不定,可以留言哦!
现在我们来说说删除吧,删除我们要关心的两个方面是:一、数据重复,二、数据不存在,以前一直用循环遍历链表,当它是否和要删除的结点一致,这样我们就忽略了这两点,当你不知道链表的数据时,如果用这样的删除方式,后果很严重的哦!现在就来看看删除的代码.

Linklist *delect(Linklist *h,int m)
{
    Linklist *p=h,*t;
    while(p->next!=NULL){
        if(p->date != m){
            t=p;
            p=p->next;  
        }
        else{
            t->next=p->next;
            p=t->next;  
        }
    }
    return h;
}

接下来就来说说逆置的操作吧,之前一直强调只要弄明白链表的指针指向,这些问题都会迎刃而解的。逆置的操作就是我先将链表拆封开,将head和最后的NULL连接起来,然后通过一个循环一直在head前插入,每次将新插入的点定义为head,最后整个链表又会重新连接起来,成为一个逆置的链表。思路就是这样的,但是链表的创建方式不同,具体操作也会有点小的变动。以下代码就是根据带头结点的创建方式逆置的。

struct Node *reserve(struct Node *h)
{
    struct Node *p,*t;
    p=h->next;
    t=p->next;
    p->next=NULL;
    while(t!=NULL){
        p=t->next;
        t->next=h->next;
        h->next=t;
        t=p;
    }
    return h;
}

至于链表的排序,我也不知道具体该咋讲,都得靠自己对于链表的指针指向的正确理解。搞不懂的时候就得在纸上画出它的指向究竟是咋样的。这里就先给出选择排序的算法吧。

Linklist *sort(Linklist *head)/*选择排序*/
{
    Linklist *temp1,*temp2,*q,*p;
    for(q=head;q->next!=NULL;q=q->next)
        for(p=q->next;p->next!=NULL;p=p->next)
        {
            if(p->next->data<q->next->data)
                if(q->next==p)//当他们是相邻结点的情况
                {
                    temp1=p->next;
                    p->next=p->next->next;
                    temp1->next=q->next;
                    q->next=temp1;
                    p=temp1;
                }
                else
                {
                    temp1=p->next;
                    temp2=q->next;
                    p->next=p->next->next;
                    q->next=q->next->next;
                    temp1->next=q->next;
                    q->next=temp1;
                    temp2->next=p->next;
                    p->next=temp2;
                }
        }
    return head;
}

好了,今天就说这么多吧,可能我的理解也有错误,还需各位指正啊!

你可能感兴趣的:(C语言)