zoukankan      html  css  js  c++  java
  • 实战数据结构(3)_两个单链表间的合并操作

    /************************************************************************/
    /* 要求:
    链表a非递减,链表b非递减
    现在要求:
    1.实现两个链表的合并,并且元素也是非递减
    2.不能占用多余节点,即只能用已有的节点,不能开辟额外的节点
    exp:
    list a:2 4 4 5 7 8 
    list b:3 4 6 9 
    则合并后:
    list a: 2 3 4 4 4 5 6 7 8 9 
                                  */
    /************************************************************************/
    /************************************************************************/
    /* 问题:
      1.还是不能一次写对代码,还是要考编译器来查找错误,指针使用很容易内存泄露
      2.还是在最后一个节点时候,scur=NULL了。就不能引用了scur->data内存泄露
    
                                                                      */
    /************************************************************************/
    
    
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct node
    {
    	int data;
    	struct node *next;
    }listnode;
    
    
    void CreateList(listnode *head,int nodenum,int *data);
    void printflist(listnode *head);
    void DeleElement(listnode *lista,listnode *listb,int *leave,int dataa);
    void mergelist(listnode *head1,listnode *head2,int length_a,int length_b);
    
    void main()
    {
    	int dataa[]={2,4,4,5,7,8};
    	int datab[]={3,4,6,9,11,25,69,78};
    	listnode *head1=(listnode *)malloc(sizeof(listnode));
    	listnode *head2=(listnode *)malloc(sizeof(listnode));
    	if(head1==NULL|| NULL==head2)
    	{
    		printf("头结点malloc分配失败
    ");
    		exit(-1);
    	}
    	 int length_a=sizeof(dataa)/sizeof(dataa[0]);
    	 int length_b=sizeof(datab)/sizeof(datab[0]);
    	CreateList(head1,length_a,dataa);
    	printf("链表A的元素有%d个:
    ",length_a);
    	printflist(head1);
    	CreateList(head2,length_b,datab);
    	printf("链表B的元素有%d个:
    ",length_b);
    	printflist(head2);
    	mergelist(head1,head2,length_a,length_b);
    }
    
    void CreateList(listnode *head,int nodenum,int *data)
    {
    	
        listnode *h=head,*pre=h,*newnode;   
        for(int i=0;i<nodenum;i++)  
        {     
            if(NULL==(newnode=(listnode *)malloc(sizeof(listnode))))//开辟一个新节点  
            {  
                printf("malloc申请失败");  
                return ;  
            }  
    		newnode->data=data[i];
            pre->next=newnode;  
            pre=newnode;  
        }  
        pre->next=NULL;  
        return ;  
    
    }
    
    void printflist(listnode *head)
    {
    	listnode *p=head->next;
    	while(p!=NULL)
    	{	
    		printf("%4d",p->data);
    		p=p->next;
    	}
    	printf("
    ");
    	return ;	
    }
    
    void DeleElement(listnode *lista,listnode *listb,int *leave,int dataa)
    {
    	//链表a删除b在a中出现的元素
    	listnode *cur_a=lista->next,*pre_a=lista,*cur_b=listb->next;
    	int count=0;
    	while(cur_a!=NULL) //控制整个流程
    	{
    		while(cur_b!=NULL && cur_a->data!=cur_b->data )		//将链表b中的元素在a中遍历
    				cur_b=cur_b->next;
    		if(NULL!=cur_b)		//找到了 将a中此节点 删除
    		{
    			pre_a->next=cur_a->next;
    			free(cur_a);
    			cur_a=pre_a->next; //这里漏掉了    当前元素也要后继一下
    			count++;
    		}
    		else	//当前a指向的元素在b中都没有,cur_a向后移动一位
    		{	
    			pre_a=cur_a;
    			cur_a=cur_a->next;
    		}
    			cur_b=listb->next; //不管查找了没有 b都需要从新开始匹配
    	}
    	*leave=dataa-count; //返回剩下a中元素个数
    	return ;
    }
    
    void mergelist(listnode *head1,listnode *head2,int length_a,int length_b)
    {
    	printf("合并两个链表后元素个数为%d且不递减顺序为:
    ",length_a+length_b);
    	listnode *long_head=(length_a>=length_b)? head1:head2;
    	listnode *short_head=(length_a<length_b)? head1:head2;//先比较两个链表的长度,短的用来控制主流程 时间复杂度低
    	listnode *lpre=long_head,*scur=short_head->next; //lpre指向long的头结点,scur指向short第一个节点
    	listnode *lcur=lpre->next; //lcur指向long的第一个节点
    	listnode *temp;
    	while(scur!=NULL) //short控制主流程 当short NULL时结束
    	{
    		while( lcur!=NULL && (scur->data > lcur->data)) //当short>long时,long 后继一位
    		{	//当遇到最后一个节点时候,lcur==NULL了,不能再lcur->data了。这里 lcur!=NULL要放到逻辑前
    			lpre=lcur;
    			lcur=lcur->next;
    		}
    		if(NULL==lcur)	//要插入的节点为最后一个节点 直接插入到最后
    		{	
    			lpre->next=scur; //直接插入
    			scur=scur->next;	//到了最后一个节点了,short也应该是最后一个节点了 要scur=NULL
    		}
    		else 
    		{
    			if(scur->data <= lcur->data) //当short遇到不大于的数了 此时lcur就是要插入的点
    			{	
    				temp=scur->next;	//记录short下一个节点
    				lpre->next=scur;
    				scur->next=lcur;    //将scur插入到long中
    				lpre=lpre->next;	//这里lpre后继一位 保持在lcur前一个节点
    				scur=temp;		//scur 后继一位
    			}
    		}
    	}
    	free(short_head);		//注意要释放短的头节点
    	printflist(long_head);
    }
    


  • 相关阅读:
    PyTorch神经网络的设计,尺寸数据的计算
    PyTorch数据处理,datasets、DataLoader及其工具的使用
    opencv、PIL.Image、matplotlib.pyplot 读图、显示、相互转换
    python安装opencv
    VS2019开发python
    【转载】pytorch常用损失函数
    5、实战:CIFAR-10分类
    【转载】Halcon小技巧之保存带有region的图片
    采用管道进行通讯的例子
    给定一个数组,找出不在数组中的最小的那个数字
  • 原文地址:https://www.cnblogs.com/pangblog/p/3278531.html
Copyright © 2011-2022 走看看