关于链表的一些题目

1.删除链表中的重复元素

前一个与后一个比较,相同就删除结点,并释放内存。

void DeleteEqual(PNODE &pHead){		//删除链表中的重复元素
	PNODE p,q,prev;
	if (p=pHead->next){
		prev=p;
		p=p->next;
	}
	while (p){
		if (p->data==prev->data){
			q=p;
			p=p->next;
			prev->next=p;
			free(q);
		}
		else
		{
			prev=p;
			p=p->next;
		}
	}
}

运行结果:

在这里插入图片描述
返回顶部

2.删除递增有序链表中大于min,小于max的元素

先找到两个前驱,释放中间结点,并且将链表重新链起来。

void DeleteSelect(PNODE &pHead,int min,int max){		//删除递增有序链表中大于min,小于max的元素
	
	PNODE p=pHead,minPrev,maxPrev;
	 	
	int flag=0;
	while (p->next){
		if(p->next->data>min&&!flag){
			minPrev=p;
			flag=1;	
		}
			
		if(p->next->data>=max){
			maxPrev=p;
			break;
		}
			
		p=p->next;
	}
	
	PNODE temp,start;
	start=minPrev->next;
	while(start->data!=maxPrev->data){
		temp=start;
		start=start->next;
		free(temp);
		temp=NULL; 
	}
	minPrev->next=maxPrev->next;
	free(maxPrev);
	maxPrev=NULL;
}

运行结果:

在这里插入图片描述
返回顶部

3.逆置链表

第一种策略(三指针):

 public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode current = head;

        while(current!=null){
            ListNode next = current.next;
            current.next = pre;
            pre = current;
            current = next;
        }

        return pre;
    }

第二种策略(递归):

总是做相同的事,就可以考虑递归的方法。

PNODE re_list(NODE *node) {      //递归       
    if (node == NULL|| node->next == NULL)  return node;  
    else{     
        NODE *head = re_list(node->next);  //一直到最后一个,head为最后一个的引用,下面的语句反向 
        node->next->next = node;  
        node->next = NULL;  		//逆置后的最后一个指向空 
        return head;  
    }  
}

void LinkListReverse2(PNODE &pHead){			//逆置链表 
    if (pHead == NULL || pHead->next == NULL){  
        return ;  
    }  
	NODE *tmp = re_list(pHead); 
    pHead = tmp;   
} 

返回顶部

4. 合并两个链表

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode head = new ListNode(-1);
        ListNode p = head;
        while(l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                p.next = l1;
                l1 = l1.next;
            } else {
                p.next = l2;
                l2 = l2.next;
            }
            p = p.next;
        }
        if (l1 != null) {
            p.next = l1;
        } else if (l2 != null) {
            p.next = l2;
        }
        return head.next;
    }

4. 合并n个链表(分治法)

 public ListNode mergeKLists(ListNode[] lists) {
        int len = lists.length;
        if (len == 0) {
            return null;
        }    
        // 将n个链表以中间为对称,两两合并 
        while(len>1) {
            for (int i=0; i<len/2; i++) {
                lists[i] = mergeTwoLists(lists[i], lists[len-1-i]);
            }
            len = (len+1)/2;
        }
        return lists[0];
    }

测试代码:

#include<iostream> 
#include <stdlib.h>
#include <string.h>
using namespace std;

typedef struct Node//结点
{
	int data;//数据域
	struct Node *next;//指针域
}NODE, *PNODE;//NODE等价于struct Student st||PNODE等价于struct Node *next

PNODE InputStudent(void)
{
	int len;
	NODE stu;
	PNODE pHead = (PNODE)malloc(sizeof(NODE));//定义一个头结点并且为头结点分配内存
	if(NULL == pHead)	//判断内存是否为空
	{
		printf("内存分配失败,程序终止!\n");
		exit(-1);
	}
	PNODE pTail = pHead;//定义一个指向头结点的指针
	pTail->next = NULL;//清空指针域
	printf("请输入个数:");
	scanf("%d",&len);
	for(int i=0; i<len; i++)
	{
		printf("请输入第%d个:\n", i+1);
		cin>>stu.data;

		PNODE pNew = (PNODE)malloc(sizeof(NODE));	//为新节点分配内存
		if(NULL == pNew)	//判断内存是否为空
		{
			printf("内存分配失败,程序终止!\n");
			exit(-1);
		}

		pNew->data = stu.data;//初始化结点的数据域	
		pTail->next = pNew;//将新结点挂到老结点后
		pNew->next = NULL;//清空新结点的指针域
		pTail = pNew;//将pTail移到新结点上
	}
	return pHead;
}

void OutputStudent(PNODE pHead)//输出链表
{
	PNODE p = pHead->next;//定义一个指针用于遍历
	printf("\n数据如下:\n");	
	while(NULL != p)
	{
		printf("%d ", p->data);
		p = p->next;
	}
}

void DeleteEqual(PNODE &pHead){		//删除链表中的重复元素
	PNODE p,q,prev;
	if (p=pHead->next){
		prev=p;
		p=p->next;
	}
	while (p){
		if (p->data==prev->data){
			q=p;
			p=p->next;
			prev->next=p;
			free(q);
		}
		else
		{
			prev=p;
			p=p->next;
		}
	}
}

void DeleteSelect(PNODE &pHead,int min,int max){		//删除递增有序链表中大于min,小于max的元素
	
	PNODE p=pHead,minPrev,maxPrev;
	 	
	int flag=0;
	while (p->next){
		if(p->next->data>min&&!flag){
			minPrev=p;
			flag=1;	
		}
			
		if(p->next->data>=max){
			maxPrev=p;
			break;
		}
			
		p=p->next;
	}
	
	PNODE temp,start;
	start=minPrev->next;
	while(start->data!=maxPrev->data){
		temp=start;
		start=start->next;
		free(temp);
		temp=NULL; 
	}
	minPrev->next=maxPrev->next;
	free(maxPrev);
	maxPrev=NULL;
}

void LinkListReverse(PNODE &L){			//逆置链表 
	PNODE pre,current,nextNode;			//三个指针维持实现逆置 
	pre=L->next;
	current=pre->next;
	nextNode=current->next;
	pre->next=NULL;						//逆置之后为最后一个 
	
	while(nextNode->next){				//三指针依次后移实现逆置 
		current->next=pre;
		pre=current;
		current=nextNode;
		nextNode=nextNode->next;
	}
	//循环出来后,最后的指针逆置 
	current->next=pre;
	nextNode->next=current;
	L->next=nextNode;					//头结点放上就行了 
}

PNODE re_list(NODE *node) {      //递归       
    if (node == NULL|| node->next == NULL)  return node;  
    else{     
        NODE *head = re_list(node->next);  //一直到最后一个,head为最后一个的引用,下面的语句反向 
        node->next->next = node;  
        node->next = NULL;  		//逆置后的最后一个指向空 
        return head;  
    }  
}

void LinkListReverse2(PNODE &pHead){			//逆置链表 
    if (pHead == NULL || pHead->next == NULL){  
        return ;  
    }  
	NODE *tmp = re_list(pHead); 
    pHead = tmp;   
} 
int main(){
	PNODE L= InputStudent();
	cout<<endl<<"输入的数据如下:";
	OutputStudent(L);
	
//	DeleteEqual(L);
//	cout<<endl<<"删除后:";
//	OutputStudent(L);
	
//	LinkListReverse2(L->next);
//	cout<<endl<<"逆置后:";
//	OutputStudent(L);

	DeleteSelect(L,2,10);
	cout<<endl<<"删除后:";
	OutputStudent(L);
	return 0;
}

返回顶部

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值