单链表(练习)

1.设计算法,判断一个带头结点的单链表list是否非递减有序。

自己思路:遍历单链表 ,每遇到一个结点判断,当前结点的值 是否小于 等于后继结点值,若为真则结束循环,该list为非递减序列;否则指针后移,继续判断,直到下一个结点为NULL,结束循环。

简单写下:

L=(list*)malloc(sizeof(list));
list *p=L->next;
if(p==NULL)
return 0;
for(p ;p!=NULL;p=p->next)
 if(p->next) return 1;
return 0;

解法:遍历一趟链表,检查每个结点的数据值是否满足此要求。只要发现有不满足的,立即判定链表不是非递减有序的。

bool nondecrease(LinkList& list){
    //检查链表是否递减有序,是则函数返回true,否则返回false
    LinkList p=list->next; //p为检测指针,定位于首元结点
    while(p->next!=NULL)    //检测链表
        if(p->next <= p->next->data) p=p->link;
        else return false;   //发现逆序返回false
     return true;     //检测完未发现逆序返回true
}

2.在非递减有序的带头结点的单链表list中删除值相同的多余结点(值相同的仅保留第一个结点)

思路:令temp=第一个结点值,遍历单链表,从第二个开始,若当前结点的值等于temp,则删除该结点,指针后移;否则更新temp值为当前结点值,指针后移,继续判断,直到p->next==NULL

解析:因为有序列表中值相同的元素排在一块,因此只需检测相邻结点的元素值是否相同,是则删除后一个值相同的结点,否则继续向后检测。

void isSame(LinkList & list){
    LinkList p=list->next,q; //检测指针p指向首元结点
    while(p!=NULL && p->next!=NULLL)  //检测链表
        if(p->data==p->next->data){   //若相邻结点值相等
           q=p->next;
            p->link=q->link;  //删除后一个值相同的结点
            free(q);
           }else
            p=p->link;   
}

3.在一个带头结点的非 有序的带头结点的单链表list中删除值相同的多余结点(值相同的仅保留第一个结点)

解析:由于链表中结点的元素值是无序排列的,因此针对每个结点*p,需要在其前面链表检查是否有元素值与其相等的结点。如果发现有元素值相同的结点,则删除*p。注意:链表应避免元素的移动

void tidy(LinkList & list){
    LinkList pre=list->link,p=pre->link,r;
    while(p!=NULL){
        for(r=list->link;r!=p;r=r->link)
            if(r->data==p->data) break;
        if(r!=p){
        pre->link=p->link;
        free(p);
        p=pre->link;
            }
    }
}

4(★★★).已知list为带头结点的单链表的表头指针,链表中的结点中存储的都是整数,设计算法,求链表中所有整数的平均值。

个人思路:设变量len,sum,每遍历一个结点执行len++,sum=sum+当前结点值,直到结束

float Average(LinkList& list){
    LinkLIst p;
    int n;
    float sum;
    for(p=list->link,n=0,sum=0;p!=NULL;p=p->link){
        sum=sum+p->data;
        n++;
    return sum/n;
    }
}

5(★★★)用链表保存m个整数,且|data|<n(n为正整数)。设计一个时间复杂度尽可能高效的算法,对于链表中绝对值相等的结点,仅保留第一次出现的结点而删除其余绝对值相等的结点。例如,给定的单链表list如图

个人思路:类似于第3题的思路。遍历单链表,对每个结点*p需在其前面链表检查是否有元素的值的绝对值与其相等的结点,

若发现有元素的值的绝对值相等的结点,则删除*p

解析:本题未限制空间复杂度,故定义一个大小为N(N为链表中所有元素绝对值的最大值)的数组,所有元素的值初始化为0。

在遍历链表的过程中,结点data值的绝对值为下标,查相应数组元素的值是否为1,若此元素已经是1,说明此结点的元素值的绝对值在之前的的链表结点中出现过,将此结点删除,否则,保留该结点并将相应数组元素的值改为1.假设单链表带头结点,

#define N 100
void DeleteABSEqualNode(LinkNode * list){
    int a[N],i;        //a是[0/1]标志数组
    for(i=0;i<N;i++) a[i]=0; //假设所有整数都未选过
    if(list->link==NULL){
     printf("空,返回!\n");return;}
    LinkNode *pre=list,*p=list->link;  //p遍历链表,pre是其前驱结点指针
    while(p!=NULL){            //遍历单链表
        if(a[abs(p->data)]==1){    //等于*p元素绝对值的整数已有
            pre->link=p->link; free(p);  //从链中摘下*P并释放
            p=pre->link;             //p指向下一个待访问结点
}
    else {                //结点*p元素值的绝对值未访问过
        a[abs(p->data)]=1;  //作访问标志
        pre=p;
        p=p->link;  //p走到下一个结点
        }
    }
}

 

6.设有两个按元素值递增次序排列的单链表list1和list2,他们都无头结点。设计算法,将这两个单链表归并为一个按元素非递增次序排列的单链表,并要求利用原来两个链表的结点存放归并后的单链表.(注意重复元素都保留)

个人思路:建立一个新表,分别遍历两个链表,对每个结点进行比较,按插入排序的思想存入新链表

解析:使用两个指针pa和pb分别遍历两个升序链表,并设置一个初始为空的指针list作为结果链表的头指针。算法用一个循环对pa和pb所指结点进行比较,小者链入结果表的前端;当两个链表中有一个遍历完,从另一个链表中剩余部分顺序摘取结点并链入结果链表的前端,由于采用前插法生成结果链表,则结果链表必定降序

void ListMerge(LinkList list1,LinkList list2,LinkList &list){
    LinkList pa=list1,pb=list2,q;  ///所有链表都没有头结点
    list=NULL;
    while(pa!=NULL && PB!=NULL){   //两两比较对应结点
        if(pa->data < pb->data){
            q=pa;
            pa=pa->link;       //头插结果链表
             }
        else {
            q=pb;
            pb=pb->link;            
             }
        if(pa==NULL) pa=pb;      //pa指向可能的非空链表
        while(pa!=NULL){         //继续处理剩余结点
            q=pa;  pa=pa->link;
            q->link=list;  list=q;
                    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值