数据结构----Java中与链表操作有关

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013132035/article/details/82664578

定义链表的结构体:

public class Linked{
    private int data;
    private Linked next;
    
    public void setData(int data){
        this.data = data;
    }
    public int getData(){
        return data;
    }

    public void setNext(Linked next){
        this.next = next;
    }
    public Linked getNext(){
        return next;
    }
}

合并两个有序链表:

//利用递归实现两个链表的合并
public static Linked mergeTwoList(Linked pHead1, Linked pHead2){
	if(pHead1==null){//如果两个链表其中有一个是空,直接返回另一个
		return pHead2;
	}else if(pHead2 == null){
		return pHead1;
	}
	Linked pHead = null;//新开辟一个链表用来存储合并后的链表
	if(pHead1.val <= pHead2.val){
		pHead = pHead1;
		pHead.next = mergeTwoList(pHead1.next, pHead2);
	}else{
		pHead = pHead2;
		pHead.next = mergeTwoList(pHead1, pHead2.next);
	}
	return pHead;
}
//利用非递归实现两个链表的合并
public static Linked mergeTwoLists(Linked pHead1, Linked pHead2){
	if(pHead1==null){//如果两个链表中有一个为空直接返回
		return pHead2;
	}else if(pHead2==null){
		return pHead1;
	}
	Linked pHead = null;//声明合并链表的头结点
    //将pHead1和pHead2中最小的节点复制给头结点
	if(pHead1.val <= pHead2.val){ 
		pHead = pHead1;
		pHead1 = pHead1.next;
	}else{
		pHead = pHead2;
		pHead2 = pHead2.next;
	}
	Linked tmp = pHead;//进行合并
	while(pHead1 != null && pHead2 != null){
		if(pHead1.val <= pHead2.val){
			tmp.next = pHead1;
			pHead1 = pHead1.next;
		}else{
			tmp.next = pHead2;
			pHead2 = pHead2.next;
		}
		tmp = tmp.next;
		tmp.next = null;
	}
	if(pHead1!=null && pHead2==null){
		tmp.next = pHead1;
	}else if(pHead2!=null && pHead1==null){
		tmp.next = pHead2;
	}
	return pHead;
}

//实现链表的逆序打印

//实现链表的逆序打印
public static void reversePrintListNode(Linked head){
	if(head == null){
		return;
	}
	Stack<Integer> stack = new Stack<Integer>();
	while(head!=null){
		stack.push(head.data);
		head = head.next;
	}
	while(!stack.isEmpty()){
		System.out.print(stack.pop()+" ");
	}
}

//在O(1)的时间内删除链表中指定节点

//删除链表中指定节点
//对于删除节点,我们的思路就是让该节点的前一个节点指向该节点的下一个节点
public static void deleteNodeForO1(Linked head, Linked toDelete){
	if(toDelete == null){
		return;
	}
	if(toDelete.next != null){//要删除的节点不是尾节点
		toDelete.data = toDelete.next.data;
		toDelete.next = toDelete.next.next;
	}else if(head == toDelete){//链表中只有一个节点即是头结点又是尾节点
		head = null;
	}else{//要删除的节点是尾节点
		Linked node = head;
		while(node.next!=toDelete){//找到倒数第二个节点
			node = node.next;
		}
		node.next = null;
	}
}

//查找单链表中倒数第k个节点或者遍历单链表将结点放入ArrayList中,最后利用list.get()方法得到

//查找单链表中倒数第k个节点
public static Linked findCountDownKNode(Linked head, int k){
	if(head == null || k <= 0){
		return null;
	}
	//都指向头结点
	Linked preNode = head;
	Linked lastNode = head;
	for(int i = 1; i < k; i++){//preNode先走k-1步
		if(preNode.next != null){
			preNode = preNode.next;
		}else{
			return null;
		}
	}
	while(preNode.next!=null){
        //然后一起走,preNode为null,lastNode即为目标
		preNode = preNode.next;
		lastNode = lastNode.next;
	}
	return lastNode;
}
//借助于外部存储ArrayList找到链表倒数第k个结点
public static Linked findCountDownKNode(Linked pHead, int k){
	if(pHead==null || k < 0){
		return null;
	}
	ArrayList<Linked> list = new ArrayList<Linked>();
	while(pHead!=null){
		list.add(pHead);
		pHead = pHead.next;
	}
	return list.get(list.size()-k);
}

 //实现单链表的逆置

//实现单链表的逆置
public static Linked reverseList(Linked head){
	if(head == null){//空直接返回null
		return null;
	}
	if(head.next == null){//一个节点直接返回头节点
		return head;
	}
	Linked pPre =  null;//记录前一个节点
	Linked p = head;
	Linked newHead = null;
	while(p!=null){
		Linked pNext = p.next;//记录当前节点的下一个节点
		if(pNext==null){
			newHead = p;
		}
		p.next = pPre;//这里的方向已经转变
		pPre = p;
		p = pNext;//将保存的后面的节点作为下一次循环的p
	}
	return newHead;
}

//删除奇数位置或者偶数位置的单链表

public static Linked deleleNode(Linked head){
	Linked l1 = new Linked();
	Linked l2 = new Linked();
	Linked p1 = l1;
	Linked p2 = l2;
	Linked p = head.next;
	int i = 1;
	while(p != null){
		if(i%2 == 1){
			p1.next = p;
			p1 = p1.next;
		}else{
			p2.next = p;
			p2 = p2.next;
		}
		i++;
		p = p.next;
	}
	p1.next = null;
	p2.next = null;
	return p1;
}

//判断一个单向链表是否形成了环形结构,定义快慢指针进行解决

public static boolean isCircleList(Linked pHead){
	if(pHead == null){
		return false;
	}
	Linked pNode = pHead;//慢指针
	Linked qNode = pHead;//快指针
	while(qNode.next!=null){
		if(qNode.next.next!=null){
			qNode = qNode.next.next;
		}else{
			return false;
		}
		if(qNode == pNode){
			return true;
		}
		pNode = pNode.next;
	}
	return false;
}

//找到两个链表中的第一个公共结点,利用栈的先进后出特性找到第一个公共结点

//找到两个链表中的第一个公共结点,利用栈的先进后出特性找到第一个公共结点
public static Linked findCommonLinkedNode(Linked pHead1, Linked pHead2){
	if(pHead1 == null || pHead2 == null){//如果有一个链表为空直接返回
		return null;
	}
	//借助于栈存储两个链表
	Stack<Linked> stack1 = new Stack<Linked>();
	Stack<Linked> stack2 = new Stack<Linked>();
	while(pHead1!=null){//将链表1的结点放入栈中
		stack1.push(pHead1);
		pHead1 = pHead1.next;
	}
	while(pHead2!=null){//将链表2的结点放入栈中
		stack2.push(pHead2);
		pHead2 = pHead2.next;
	}
	Linked l3 = null;//保存公共链表的结点
	while(!stack1.isEmpty()){//利用栈的先进后出特性
		Linked l1 = stack1.peek();
		Linked l2 = stack2.peek();
		if(l1==l2){
			l3 = stack1.pop();//保存公共结点
			stack2.pop();
			continue;
		}
		return l3;//最后一个公共结点
	}
	return null;
}

//复制复杂链表

public class Node {
	public int m_nValue;
	public Node m_pNext;
	public Node m_pSibling;
	public Node() {}
	public Node(int m_nValue) {
		super();
		this.m_nValue = m_nValue;
	}
}
public Node clone(Node pHead) {
	if (pHead == null) {
		return null;
	}
	HashMap<Node, Node> map = new HashMap<Node, Node>();
	Node pClonedHead = new Node(pHead.m_nValue);//复制链表的头结点
	Node pNode = pHead, pClonedNode = pClonedHead;
	map.put(pNode, pClonedNode);
	// 第一步,hashMap保存,原链表节点映射复制链表节点
	while (pNode.m_pNext != null) {
		pClonedNode.m_pNext = new Node(pNode.m_pNext.m_nValue);
		pNode = pNode.m_pNext;
		pClonedNode = pClonedNode.m_pNext;
		map.put(pNode, pClonedNode);
	}
	// 第二步:找到对应的m_pSibling
	pNode = pHead;
	pClonedNode = pClonedHead;
	while (pClonedNode != null) {
		pClonedNode.m_pSibling = map.get(pNode.m_pSibling);
		pNode = pNode.m_pNext;
		pClonedNode = pClonedNode.m_pNext;
	}
	return pClonedHead;
}

//删除链表中重复的结点

//删除链表中重复的结点
public static Linked deleteRepeatNode(Linked pHead){
	if(pHead == null){//如果链表为空直接返回
		return null;
	}
	Linked preNode = null;
	Linked node = pHead;
	while(node!=null){
		if(node.next!=null && node.val==node.next.val){
			int val = node.val;//结点重复
			while(node.next!=null && node.next.val==val){
				node = node.next;
			}
			if(preNode == null){
				pHead = node.next;
			}else{
				preNode.next = node.next;
			}
		}else{//不重复继续向下走
			preNode=node;
		}
		node = node.next;//指向下一个结点
	}
	return pHead;
}

//利用快慢指针找到链表的中间结点

//利用快慢指针找到链表的中间结点
public static Linked getMidNode(Linked pHead){
	if(pHead == null){
		return null;
	}
	Linked pNode = pHead;//慢指针
	Linked qNode = pHead;//快指针
	while(qNode.next!=null){
		if(qNode.next.next!=null){
			pNode = pNode.next;
			qNode = qNode.next.next;
		}else{
			pNode = pNode.next;//处理只有两个结点的情况
		}
	}
	return pNode;
}

//判断链表中环的入口

public Linked EntryNodeOfLoop(Linked pHead) {
	HashSet<Linked> set = new HashSet<Linked>();
	while (pHead != null) {
		if (!set.add(pHead)) {
			return pHead;
		}
		pHead = pHead.next;
	}
	return null;
}
public Linked EntryNodeOfLoop1(Linked pHead) {
	if (pHead == null || pHead.next == null)
		return null;
	Linked p1 = pHead;
	Linked p2 = pHead;
	while (p2 != null && p2.next != null) {
		p1 = p1.next;
		p2 = p2.next.next;
		if (p1 == p2) {
			p2 = pHead;
			while (p1 != p2) {
				p1 = p1.next;
				p2 = p2.next;
			}
			if (p1 == p2)
		    	return p1;
		}
	}
	return null;
}

猜你喜欢

转载自blog.csdn.net/u013132035/article/details/82664578