链表部分代码练习

1、遍历及输出

void ListVisit(Linklist L){

        LNode *p=L->next;

        while(p!=NULL){

                printf("%d",p->data);

                p=p->next;

        }

}

2、查找单链表中第i个位置,若存在,则返回该结点的指针;不存在,则返回NULL

LNode* Seek_i(LinkList L,int i){

        if(i<1)

                return NULL;

        LNode *p=L->next;

        int k=1;

        while(p!=NULL && K<i){

                p=p->next;

                k++;

        }

        return p;

}

3、 查找单链表中第一个结点数据值为e的元素,若存在则返回该节点的指针;若不存在,则返回NULL

LNode * Seek_e(LinkList L,int e){

        LNode *p=L->next;

        while(p!=NULL && p->data!=e)

                p=p->next;

        return p;

}

4、 采用头插法在头指针为L处建立一个带头结点的单链表,输入-1表示结束,结果返回建立的单链表

LinkList InitList(LinkList &L){

        L=(LNode*)malloc(sizeof(LNode));//分配一个头结点

        L->next=NULL;

        LNode *s;

        int x;

        scanf("%d",&x);

        while(x!=-1){

                s=LNode*)malloc(sizeof(LNode));

                s->data=x;

                s->next=L->next;

                L->next=s;

                scanf("%d",&x);

        }

        return L;

}

5、采用尾插法在头指针为L处建立一个带头结点的单链表,输入-1表示结束,结果返回建立的单链表

LinkList InitList(LinkList &L){

        L=(LNode *)malloc(sizeof(LNode));

        L->next=NULL;

        LNode *r=L;//设置一个尾指针

        LNode *s;

        int x;

        scanf("%d",&x);

        while(x!=-1){

                s=(LNode *)malloc(sizeof(LNode));

                s->data=x;

                s->next=r->next;

                r->next=s;

                r=s;

                scanf("%d",&x);

        }

        return L;

}

6、将带头结点的单链表L就地逆置

思路:就地逆置就是说不能再创建一个新的链表来放置逆置后的链表

tips:如果链表改变很大,不是简单的插入删除操作的话并且不允许增加新的空间,则让头结点指向空,让一个新的指针指向第一个结点,以此断开链表和与原来链表中内容的关系

 

void Reverse(LinkLIst &L){

        LNode *s=L->next;

        LNode *r;

        L->next=NULL;

        while(s!=NULL){

                r=s->next; 

                s->next=L->next;

                L->next=s;

                s=r;

        }

        return L;

}

7、在一个单链表中寻找结点值为e的结点,在其后插入一个节点值为x的结点,返回该链表(结点值为e的结点唯一存在)

思路:先找到值为e的结点,然后在该结点后插入x

LinkList Insert_x(LinkList & L,int e){  

        LNode *p=L->next;

        LNode *s=(LNode *)malloc(sizeof(LNode));

        s->data=x;

        while(p!=NULL && p->data!=e)

                p=p->next;

        s->next=p->next;

        p->next=s;

        return L;

}

8、删除单链表L中结点值为e的结点,结点唯一

tips:要找到它前面的那个结点,因此一个遍历指针是不够的,还需要一个pre指针

void Del_e(LinkList L,int e){

        LNode *p=L->next;

        LNode *pre=L;

        while(p!=NULL && p->data!=e){

                p=p->next;

                pre=pre->next;

        }

        pre->next=p->next;

        free(p);

}

9、删除单链表L中结点值为e的结点,结点唯一(无头结点

  • 特殊讨论要删除结点是第一个结点的情况

void Del_e(LinkList L,int e){

        LNode *p=L;

        LNode *pre;

        while(p!=NULL && p->data!=e){

                pre=p;

                p=p->next;

        }

        if(p==L){//需要特殊讨论此种情况

                L=L->next;

                free(p);

        }else{

                pre->next=p->next;

                free(p);

       }

}

  • 自己造一个头结点head

void Del_e(LinkList L,int e){

        LNode *head=(LNode *)malloc(sizeof(LNode));

        head->next=L;

        LNode *p=head->next;

        LNode *pre=head;

        while(p!=NULL && p->data!=e){

                p=p->next;

                pre=pre->next;

        }

        pre->next=p->next;

        free(p);

        L=head->next;//重新让L指向原处,防止要删除的是第一个结点,把L删没了

        free(head);

}

10、删除单链表L中所有结点值为e的结点,结点不唯一

void Del_e(LinkList &L,int e){

        LNode *p=L->next;

        LNode *pre=L;

        while(p!=NULL){

                if(p->data!=e){//不等于e就往后走

                        p=p->next;

                        pre=pre->next;

                }

                else{//等于e就删除

                        pre->next=p->next;

                        free(p);

                        p=pre->next;

                }//else

        }//while

}//void

11、删除单链表L中的最小值结点,最小值结点唯一

思路:先找到最小值结点(需要两个指针),再删除(需要两个指针)

void Del_min(LinkList &L){

        LNode *p=L->next;//遍历指针

        LNode *pre=L;//当前指针的前一个指针

        LNode *min=L->next;//最小值结点指针,初始化为第一个结点

        LNode *mpre=L;//min的前一个指针

        while(p!=NULL){

                if(min->data>p->data){

                        min=p;

                        mpre=pre;

                p=p->next;

                pre=pre->next;

        }

        mpre->next=min->next;

        free(min);

}

12、设一个单链表L,L中结点非递减有序排列,设计一个算法删除单链表L中数值相同的结点,使单链表中不再有重复的结点

思路:相同的结点是相邻的,因此用两个指针一前一后,如果值相同,就删除后面的

void Del_equ(LinkList &L){

        LNode *p=L->next->next;

        LNode *pre=L->next;

        while(p!=NULL){

                if(pre->data==p->data){

                        pre->next=p->next;

                        free(p);

                        p=pre->next;

                }else{

                        pre=p;

                        p=p->next;

                }//else

        }//while

}//void

13、将一个带头结点的单链表A分解为两个带头结点的单链表A和B,使得A表中含有原表中序号为奇数的元素,而B表中含有原表中序号为偶数的元素,且保持相对顺序不变,最后返回B表。

思路:先创建一个B,再让A头结点与原链表内容断开,因为要保持相对顺序不变,因此把元素依次尾插到A或B中

LinkList Change_A(LinkList &A){

        LinkList B=(LinkList)malloc(sizeof(LNode));//先创建一个B链表

        B->next=NULL;

        LNode *ra=A, *rb=B;//两个尾指针

        LNode *p=A->next;//遍历指针

        A->next=NULL;//将A与原链表断开

        int k=1;//用作计数,来判断奇偶

        while(p!=NULL){

                if(k%2!=0){//第奇数个元素尾插到A后面

                        ra->next=p;

                        ra=p;

                        p=p->next;

                }else{//第偶数个元素尾插到B后面

                        rb->next=p;

                        rb=p;

                        p=p->next;

                }

                k++;

        }

        ra->next=NULL;

        rb->next=NULL;

        return B;

}

14、假设有两个按元素值递增次序排列的线性表,均以单链表形式存储,请编写算法将这两个带头结点的单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来两个单链表的结点存放归并后的单链表。

思路:从两个递增序列归并成一个递减序列,顺序发生了改变,所以要用头插

两个链表的长度不一定相等,因此短的链表中的元素全部头插完之后,循环比较结束,再将长的链表内的剩余元素依次头插到归并链表中

LinkList Merge_AB(LinkList &A, LinkList &B){

        LNode *p=A->next, *q=B->next;

        A->next=NULL;//断开头结点A与原链表内容,用于存放归并后的元素

        LNode *r;//A和B都能用,用于指向当前要头插元素的下一个结点

        while(p!=NULL && q!=NULL){//谁小就先头插谁

                if(p->data<=q->data){

                        r=p->next;

                        p->next=A->next;

                        A->next=p;

                        p=r;

                }else{

                        r=q->next;

                        q->next=B->next;

                        A->next=q;

                        q=r;

                }

        }

        while(p!=NULL){//A链表比较长,剩余元素依次头插               

                r=p->next;

                p->next=A->next;

                A->next=p;

                p=r;

        }

        while(q!=NULL){//B链表比较长,剩余元素依次头插

                r=q->next;

                q->next=B->next;

                A->next=q;

                q=r;

        }

        free(B);

        return A;

}

未完待续...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值