【数据结构】链表总结

一、链表逆置

1、题目、已知一链表,求将其逆置后的链表
2、代码实现

#include<iostream>
using namespace std;

struct ListNode
{
	int val;
	ListNode *next;
};

class solution
{
public:
	ListNode* reverseList(ListNode* head)
	{
		ListNode* newhead =NULL ;
		while( head )
		{
			ListNode* pNode = head->next ;
			head->next = newhead;
			newhead = head;
			head = pNode;
		}
		return newhead;
	}

};

int main()
{
	ListNode a;
	ListNode b;
	ListNode c;
	ListNode d;
	ListNode e;
	ListNode f;
	ListNode g;
	a.val =1;
	b.val =2;
	c.val =3;
	d.val =4;
	e.val =5;
	f.val =6;
	g.val =7;
	a.next =&b;
	b.next =&c;
	c.next =&d;
	d.next =&e;
	e.next =&f;
	f.next =&g;
	g.next =NULL;
	solution solve;
	printf("原链表长度为:");
	ListNode*phead = &a;
	while(phead)
	{
		printf("%d ",phead->val );
		phead = phead->next ;
	}
	printf("\n逆序后链表为:");
	phead = solve.reverseList (&a);
	while(phead)
	{
		printf("%d ",phead->val );
		phead = phead->next ;
	}
	return 0;
}

3、程序结果

1.2.1、题目:已知一链表,将从m到n之间的节点逆置,并打印逆置后链表

1.2.2程序实现

#include<iostream>
using namespace std;

struct ListNode
{
	int val;
	ListNode *next;
};

class solution
{
public:
	ListNode* reverseList(ListNode* head,int m,int n)
	{
		int change_len =  n - m +1;
		ListNode* result = head;
		ListNode* pre = NULL;

		while(head && --m)
		{
			pre = head;
			head = head->next ;
		}
		ListNode* newhead = NULL;
		ListNode* modify_list_tail = head;
		while( head && change_len)
		{
			ListNode* pNode = head->next ;
			head->next = newhead;
			newhead = head;
			head = pNode;
			change_len--;
		}

		modify_list_tail->next = head;

		if(pre)
		{
			pre->next = newhead;
		}

		return result;
	}

};

int main()
{
	ListNode a;
	ListNode b;
	ListNode c;
	ListNode d;
	ListNode e;
	ListNode f;
	ListNode g;
	a.val =1;
	b.val =2;
	c.val =3;
	d.val =4;
	e.val =5;
	f.val =6;
	g.val =7;
	a.next =&b;
	b.next =&c;
	c.next =&d;
	d.next =&e;
	e.next =&f;
	f.next =&g;
	g.next =NULL;
	solution solve;
	printf("原链表打印为:");
	ListNode*phead = &a;
	while(phead)
	{
		printf("%d ",phead->val );
		phead = phead->next ;
	}
	printf("\n逆序后链表为:");
	phead = solve.reverseList (&a,3,6);
	while(phead)
	{
		printf("%d ",phead->val );
		phead = phead->next ;
	}
	return 0;
}

1.2.3程序结果

二、求两个链表的交点

2、题目:已知链表A的头节点head1,链表B的节点head2,两个链表相交,求相交节点

2.1.1程序实现

#include<iostream>
#include<set>
using namespace std;

struct ListNode
{
	int val;
	ListNode *next;
	ListNode(int x)
		:val(x)
		,next(NULL)
	{}
};

class solution
{
public:
	ListNode* FindTheCrossPoint(ListNode* head1,ListNode* head2)
	{
		std::set<ListNode*> node_set;
		while(head1)
		{
			node_set.insert(head1);
			head1 = head1->next ;
		}
		while(head2)
		{
			if( ( node_set.find(head2) )!= node_set.end())
			{
				return head2;
			}
			head2 = head2->next ;
		}
	    return NULL;
	}
	
};
void print(ListNode*head)
{
	while(head)
	{
		printf("%d ",head->val );
		head = head->next ;
	}

}
int main()
{
	ListNode a(1);
	ListNode b(2);
	ListNode c(3);
	ListNode d(4);
	ListNode e(5);
	ListNode f(6);
	ListNode g(7);

	a.next =&b;
	b.next =&c;
	c.next =&d;
	d.next =NULL;
	e.next =&f;
	f.next =&g;
	g.next =&c;
	solution solve;
	
	ListNode*phead1 = &a;
	printf("phead1打印为:");
	print(phead1);

	ListNode* phead2 = &e;
	printf("\nphead2打印为:");
	print(phead2);

	printf("\n相交链表为:");
	ListNode* phead = solve.FindTheCrossPoint(phead1,phead2);
	print(phead);
	return 0;
}

2.1.2程序结果

2.2第二种解法
2.2.1程序实现

#include<iostream>
#include<set>
using namespace std;

struct ListNode
{
	int val;
	ListNode *next;
	ListNode(int x)
		:val(x)
		,next(NULL)
	{}
};

class solution
{
public:
	int Length(ListNode* head)
	{
		int count  = 0;
		while(head)
		{
			++count;
			head = head->next ;
		}
		return count;
	}

	ListNode* Forward(int Long_len ,int Short_len, ListNode* head)
	{
		int dis = Long_len - Short_len;
		while(head && dis)
		{
			head = head->next ;
			--dis;
		}
		return head;
	}
	ListNode* FindTheCrossPoint(ListNode* head1,ListNode* head2)
	{
		
		int len_head1 = Length(head1);
		int len_head2 = Length(head2);

		if(len_head1 > len_head2)
		{
			head1 = Forward(len_head1, len_head2, head1);
		}
		else
		{
			head2 = Forward(len_head2,len_head1, head2);
		}

		while(head1 && head2)
		{
			if(head1 == head2)
			{
				return head1;
			}

			head1 = head1->next ;
			head2 = head2->next ;
		}
		return NULL;
	}
	
};
void print(ListNode*head)
{
	while(head)
	{
		printf("%d ",head->val );
		head = head->next ;
	}

}
int main()
{
	ListNode a(1);
	ListNode b(2);
	ListNode c(3);
	ListNode d(4);
	ListNode e(5);
	ListNode f(6);
	ListNode g(7);

	a.next =&b;
	b.next =&c;
	c.next =&d;
	d.next =NULL;
	e.next =&f;
	f.next =&g;
	g.next =&c;
	solution solve;
	
	ListNode*phead1 = &a;
	printf("phead1打印为:");
	print(phead1);

	ListNode* phead2 = &e;
	printf("\nphead2打印为:");
	print(phead2);

	printf("\n相交链表为:");
	ListNode* phead = solve.FindTheCrossPoint(phead1,phead2);
	print(phead);
	return 0;
}

2.2.2程序结果

三、链表求环

3.题目:已知链表可能存在环,若有,返回环的起始节点,没有返回NULL
3.1使用STL中set实现
3.1.1程序实现

#include<iostream>
#include<set>
using namespace std;

struct ListNode
{
	int val;
	ListNode *next;
	ListNode(int x)
		:val(x)
		,next(NULL)
	{}
};

class solution
{
public:
	ListNode* FindTheCircle(ListNode* head)
	{
		std::set<ListNode*> node_set;
		while(head)
		{
			if(node_set.find(head)!= node_set.end())
			{
				head->next =NULL;
				return head ;
			}
			node_set.insert(head);
			head = head->next ;
		}
		return NULL;
	}
	
};
void print(ListNode*head)
{
	while(head)
	{
		printf("%d ",head->val );
		head = head->next ;
	}

}
int main()
{
	ListNode a(1);
	ListNode b(2);
	ListNode c(3);
	ListNode d(4);
	ListNode e(5);
	ListNode f(6);
	ListNode g(7);

	a.next =&b;
	b.next =&c;
	c.next =&d;
	d.next =&e;
	e.next =&f;
	f.next =&g;
	g.next =&c;
	solution solve;
	
	ListNode*phead1 = &a;
	printf("\n环的入口节点为:");
	ListNode* head = solve.FindTheCircle(phead1);
	print(head);
	return 0;
}

3.1.2程序结果

3.2使用快慢指针思想实现
3.2.1程序实现

#include<iostream>
using namespace std;
struct ListNode {
	int val;
	ListNode *next;
	ListNode(int x) : val(x), next(NULL) {}
};

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
    	ListNode *fast = head;
    	ListNode *slow = head;
    	ListNode *meet = NULL;
    	while(fast){
    		slow = slow->next;
    		fast = fast->next;
    		if (!fast){
		    	return NULL;
		    }
		    fast = fast->next;
		    if (fast == slow){
    			meet = fast;
    			break;
    		}
	    }
	    if (meet == NULL){
    		return NULL;
    	}
    	while(head && meet){
	    	if (head == meet){
	    		return head;
	    	}
	    	head = head->next;
	    	meet = meet->next;
	    }
        return NULL;
    }
};

int main(){
	ListNode a(1);
	ListNode b(2);
	ListNode c(3);
	ListNode d(4);
	ListNode e(5);
	ListNode f(6);
	ListNode g(7);
	a.next = &b;
	b.next = &c;
	c.next = &d;
	d.next = &e;
	e.next = &f;
	f.next = &g;
	g.next = &c;
	Solution solve;
	ListNode *node = solve.detectCycle(&a);
	if (node){
		printf("%d\n", node->val);
	}
	else{
		printf("NULL\n");
	}
	return 0;
}

3.2.2程序结果

四、链表划分

4.1题目:已知链表的头指针head与数值X,将所有小于X的数,全部放在大于X或者等于X的节点前,并且保持这些节点的原来相对位置。
4.1.2程序实现

#include<iostream>
using namespace std;

struct ListNode
{
	int val;
	ListNode* next;
	ListNode(int x)
		:val(x)
		,next(NULL)
	{}
};

class solution
{
public:
	ListNode* partion(ListNode* head,int x)
	{
		ListNode less_head(0);//注意
		ListNode more_head(0);
		ListNode* less_ptr = &less_head;//注意
		ListNode* more_ptr = &more_head;

		while(head)
		{
			if(head->val >= x )
			{
				more_ptr->next = head;
				more_ptr = head;
			}
			else
			{
				less_ptr->next = head;
				less_ptr = head;
			}

			head = head->next ;
		}
		less_ptr->next = more_head.next ;
		more_ptr->next = NULL;
		return less_head.next  ;
	}
	
};
void print(ListNode*head)
{
	while(head)
	{
		printf("%d ",head->val );
		head = head->next ;
	}

}
int main()
{
	ListNode a(1);
	ListNode b(4);
	ListNode c(3);
	ListNode d(2);
	ListNode e(5);
	ListNode f(2);
	a.next = &b;
	b.next = &c;
	c.next = &d;
	d.next = &e;
	e.next = &f;
	f.next = NULL;
	printf("原链表打印为:");
	print(&a);
	solution solve;
	printf("\n链表划分应为:");
	ListNode*head = solve.partion(&a,3);
	print(head);
	

	return 0;
}

4.1.2程序结果

五、复杂链表的深度拷贝

5.1题目:已知一个复杂链表,每个节点有两个指针,一个指向下一个节点,另一个是指向本链表的任意一个节点的随机指针,求这个链表的深度拷贝
5.2程序实现

#include<iostream>
#include<map>
#include<vector>
using namespace std;

struct ListNode
{
	int val;
	ListNode* next;
	ListNode* random;
	ListNode(int x)
		:val(x)
		,next(NULL)
		,random(NULL)
	{}
};

class solution
{
public:
	ListNode* copyRandom(ListNode* head)
	{
		std::map<ListNode*,int> node_map;
		std::vector<ListNode*> node_vec;
		ListNode* ptr = head;
		int i = 0;
		while(ptr)//将节点装入vector中,并使得map形成地址映射
		{
			node_vec.push_back(new ListNode(ptr->val));
			node_map[ptr] = i;
			ptr = ptr->next ;
			i++;
		}
		node_vec.push_back (0);

		ptr = head;//再次遍历链表,
		i = 0;
		while(ptr)
		{
			node_vec[i] ->next = node_vec[i+1];//将节点链接起来
			if(ptr->random )//将指针指好
			{
				int id = node_map[ptr->random ];
				node_vec[i]->random = node_vec[id];
			}
			ptr = ptr->next ;
			i++;
		}
		return node_vec[0];

	}
	
};
void print(ListNode*head)
{
	while(head)
	{
		printf("%d ",head->val );
		head = head->next ;
	}

}
int main(){
	ListNode a(1);
	ListNode b(2);
	ListNode c(3);
	ListNode d(4);
	ListNode e(5);
	a.next = &b;
	b.next = &c;
	c.next = &d;
	d.next = &e;	
	a.random = &c;
	b.random = &d;
	c.random = &c;
	e.random = &d;	
	solution solve;
	ListNode *head = solve.copyRandom(&a);	
	while(head)
	{
		printf("val = %d ", head->val);
		if (head->random)
		{
			printf("rand = %d\n", head->random->val);
		}
		else
		{
			printf("rand = NULL\n");
		}
		head = head->next;
	}
	return 0;
}

5.3程序结果

六、两个链表的合并

6.1题目:已知两个已排序头节点指针head1,head2,将这两个链表合并,使得合并后链表也是有序的,并且返回合并后的头节点
6.2程序实现

#include<iostream>
using namespace std;

struct ListNode
{
	int val;
	ListNode *next;
	ListNode(int x)
		:val(x)
		,next(NULL)
	{}
};

class solution
{
public:
	ListNode* MergeTwoList(ListNode* head1,ListNode* head2)
	{
		ListNode  temp(0);
		ListNode* temp_head = &temp;

		while(head1 && head2)
		{
			if(head1->val < head2->val )
			{
				temp_head->next  = head1;
				head1= head1->next ;
			}
			else
			{
				temp_head->next = head2;
				head2 = head2->next ;
			}
			temp_head = temp_head->next ;
		}
		if(head1)
		{
			temp_head->next = head1;
		}
		if(head2)
		{
			temp_head->next = head2;
		}

		return temp.next ;
	}
	
};
void print(ListNode*head)
{
	while(head)
	{
		printf("%d ",head->val );
		head = head->next ;
	}

}
int main()
{
	ListNode a(1);
	ListNode b(3);
	ListNode c(5);
	ListNode d(7);
	ListNode e(2);
	ListNode f(4);
	ListNode g(6);

	a.next =&b;
	b.next =&c;
	c.next =&d;
	d.next =NULL;
	e.next =&f;
	f.next =&g;
	g.next =NULL;
	solution solve;
	
	ListNode*phead1 = &a;
	printf("phead1打印为:");
	print(phead1);

	ListNode* phead2 = &e;
	printf("\nphead2打印为:");
	print(phead2);

	printf("\n合并后链表为:");
	ListNode* phead = solve.MergeTwoList(phead1,phead2);
	print(phead);
	return 0;
}

6.3程序结果

##七、 k个已排序的链表合并 ##
7.1题目:已知k个已派序链表头节点指针,将这K个链表合并,合并后仍为有序的,返回合并后的头节点
7.1.1利用vector实现,将所有的链表节点都放在vector中,在将vector中的每个节点排序,最后实现

7.1.2程序实现

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

struct ListNode
{
	int val;
	ListNode *next;
	ListNode(int x)
		:val(x)
		,next(NULL)
	{}
};


void print(ListNode*head)
{
	while(head)
	{
		printf("%d ",head->val );
		head = head->next ;
	}

}

bool cmp(const ListNode *a,const ListNode* b)
{
	return a->val <b->val ;
}
int main()
{
	ListNode a(1);
	ListNode b(3);
	ListNode c(5);
	ListNode d(7);

	ListNode e(2);
	ListNode f(4);
	ListNode g(6);


	ListNode h(8);
	ListNode i(9);
	ListNode j(11);

	ListNode k(10);
	ListNode l(15);
	ListNode m(17);
	ListNode n(19);


	a.next =&b;
	b.next =&c;
	c.next =&d;
	d.next =NULL;

	e.next =&f;
	f.next =&g;
	g.next =NULL;

	h.next = &i;
	i.next = &j;
	j.next = NULL;

	k.next = &l;
	l.next = &m;
	m.next =&n;
	n.next =NULL;

	std::vector<ListNode*> node_vec;
	node_vec.push_back(&a);
	node_vec.push_back(&b);
	node_vec.push_back(&c);
	node_vec.push_back(&d);

	node_vec.push_back(&e);
	node_vec.push_back(&f);
	node_vec.push_back(&g);

	node_vec.push_back(&h);
	node_vec.push_back(&i);
	node_vec.push_back(&j);


	node_vec.push_back(&k);
	node_vec.push_back(&l);
	node_vec.push_back(&m);
	node_vec.push_back(&n);
	std::sort(node_vec.begin(),node_vec.end(),cmp);

	
	ListNode*phead1 = &a;
	printf("phead1打印为:");
	print(phead1);

	ListNode* phead2 = &e;
	printf("\nphead2打印为:");
	print(phead2);

	ListNode*phead3 = &h;
	printf("\nphead3打印为:");
	print(phead3);

	ListNode*phead4 = &k;
	printf("\nphead4打印为:");
	print(phead4);

	printf("\n合并后链表为 :");
	for(int i = 0; i<node_vec.size();i++)
	{
		printf("%d ",node_vec[i]->val );
	}
	return 0;
}

7.1.2程序结果

7.2.1使用map进行地址映射

7.2.2程序实现

#include <stdio.h>

struct ListNode {
 	int val;
	ListNode *next;
	ListNode(int x) : val(x), next(NULL) {}
};

#include <vector>
#include <algorithm>

bool cmp(const ListNode *a, const ListNode *b){
	return a->val < b->val;
}

class Solution {
public:
    ListNode* mergeKLists(std::vector<ListNode*>& lists) {
        std::vector<ListNode *> node_vec;        
        for (int i = 0; i < lists.size(); i++){
        	ListNode *head = lists[i];
        	while(head){
        		node_vec.push_back(head);
	        	head = head->next;
	        }
        }
        if (node_vec.size() == 0){
        	return NULL;
        }        
        std::sort(node_vec.begin(), node_vec.end(), cmp);
        for (int i = 1; i < node_vec.size(); i++){
        	node_vec[i-1]->next = node_vec[i];
        }
        node_vec[node_vec.size()-1]->next = NULL;
        return node_vec[0];
    }
};

int main(){
	ListNode a(1);
	ListNode b(4);
	ListNode c(6);
	ListNode d(0);
	ListNode e(5);
	ListNode f(7);
	ListNode g(2);
	ListNode h(3);
	a.next = &b;
	b.next = &c;	
	d.next = &e;
	e.next = &f;	
	g.next = &h;	
	Solution solve;	
	std::vector<ListNode *> lists;
	lists.push_back(&a);
	lists.push_back(&d);
	lists.push_back(&g);	
	ListNode *head = solve.mergeKLists(lists);
	while(head){
		printf("%d\n", head->val);
		head = head->next;
	}
	return 0;
}

7.2.3程序结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值