链表的各种基本操作

1. 链表定义。

#ifndef _LISTNODE_
#define _LISTNODE_

struct ListNode
{
	int m_value;
	ListNode * m_pNext;
};

#endif

2. 初始化链表。

void InitList(ListNode * L)
{
	L = nullptr;
	cout << "InitList Success! " << endl;
}

3. 创建链表。共三种方法。

// ------创建线性表 1: 头结点插入法,头结点不放数据------
ListNode * CreateListFromHead()
{
	ListNode * pHead = new ListNode;
	pHead->m_pNext = nullptr;
	if (pHead == nullptr)
	{
		cout << "分配内存失败!" << endl;
		return nullptr;
	}

	int input;
	
	while (cin>>input && input != -1)
	{
		ListNode *pTmp = new ListNode;
		pTmp->m_value = input;
		pTmp->m_pNext = pHead->m_pNext;   //将节点插入到表头,这是头插法
		pHead->m_pNext = pTmp;
		pTmp = nullptr;
	}

	//pTmp = nullptr;
	return pHead;
}
// ------创建线性表 2: 尾插法,头结点不放数据------
ListNode * CreateListFromTail2()
{
	ListNode * pHead = new ListNode;
	if (pHead == nullptr)
	{
		cout << "分配内存失败!" << endl;
		return nullptr;
	}
	pHead->m_pNext = nullptr;

	ListNode *pTail = new ListNode;
	pTail = pHead;

	int input;

	while (cin>>input && input != -1)
	{
		ListNode *pTmp = new ListNode;
		pTmp->m_value = input;
		pTail->m_pNext = pTmp;   //尾插法
		pTail = pTmp;
		pTmp = nullptr;
	}
	pTail->m_pNext = nullptr;

	return pHead;
}
// ------创建线性表 3: 尾插法,无头结点------
ListNode * CreateListFromTail()
{
	/*ListNode * pHead = new ListNode;
	if (pHead == nullptr)
	{
		cout << "分配内存失败!" << endl;
		return nullptr;
	}*/
	ListNode *pHead = nullptr;

	ListNode *pTail = pHead;

	int input;

	while (cin>>input && input != -1)
	{
		ListNode *pTmp = new ListNode;
		pTmp->m_value = input;

		if (pHead == nullptr)
			pHead = pTmp;
		else
			pTail->m_pNext = pTmp;   //尾插法
		pTail = pTmp;

		pTmp = nullptr;
	}
	if (pTail != nullptr)
		pTail->m_pNext = nullptr;

	return pHead;
}

4. 插入。共两种方法。

// -------------------在pos位置的前方插入-----------------------------
void InsertListNodeFromFront(ListNode *&L, int pos, int value)  //可能需要改变头结点,因此L要取&
{
	ListNode *tmp = new ListNode;
	tmp->m_value = value;
	if (L == nullptr || pos == 0)
	{
		tmp->m_pNext = L;
		L = tmp;
		return;
	}

	if ( pos >= ListLen(L) || pos < 0)
	{
		cout << "Error input pos."<< endl;
		return;
	}

	ListNode *pInsert = L;
	while (--pos)
	{
		pInsert = pInsert->m_pNext;
	}
	tmp->m_pNext = pInsert->m_pNext;
	pInsert->m_pNext = tmp;

	return;
}
// -----------------在pos后插入--------------------
void InsertListNodeFromBack(ListNode *&L, int pos, int value)
{
	ListNode *tmp = new ListNode;
	tmp->m_value = value;
	if (L == nullptr || pos == 0)
	{
		tmp->m_pNext = L;
		L = tmp;
		return;
	}
	
	if ( pos >= ListLen(L) || pos < 0)
	{
		cout << "Error input pos."<< endl;
		return;
	}

	ListNode *pInsert = L;
	while (pos--)
	{
		pInsert = pInsert->m_pNext;
	}
	tmp->m_pNext = pInsert->m_pNext;
	pInsert->m_pNext = tmp;

	return;
}

5. 删除。

void DeleteListNode(ListNode *&L, int value)
{
	if (L == nullptr)
	{
		cout << "Error input L.";
		return;
	}

	ListNode *pDelete = L;
	if (L->m_value == value)
	{
		L = L->m_pNext;
		delete pDelete;
		return;
	}
	
	ListNode *pFront = nullptr;
	while (pDelete != nullptr && pDelete->m_value != value)
	{
		pFront = pDelete;
		pDelete  = pDelete->m_pNext;
	}

	if (pDelete == nullptr)
	{
		cout << "Not found value in L.";
		return;
	}
	if (pDelete->m_value == value)
	{
		pFront->m_pNext = pDelete->m_pNext;
		delete pDelete;
	}

	return;
}

6. 翻转。

ListNode * ReverseList(ListNode *L)
{
	if(L == nullptr || L->m_pNext == nullptr)
		return nullptr;

	ListNode * pCurrent = nullptr;

	while (L != nullptr)
	{
		ListNode * tmp = L->m_pNext;
		L->m_pNext = pCurrent;
		pCurrent = L;
		L = tmp;
	}

	/*DisplayList(L);
	DisplayList(pCurrent);*/
	return pCurrent;
}

7. 打印。

void DisplayList(ListNode * L)
{
	ListNode * list = L;

	while (list != nullptr)
	{
		cout << list->m_value << " -> ";
		list = list->m_pNext;
	}
	cout << "null" << endl;
}

8. 链表长度。

int ListLen(ListNode *L)
{
	int len = 0;

	while (L != nullptr)
	{
		L = L->m_pNext;
		++len;
	}

	return len;
}

9. 找到链表倒数第k个节点。

ListNode *FindKthNode(ListNode *L, int k)
{
	if (ListLen(L) < k)
		return nullptr;

	ListNode *pFront = nullptr, *pBack = nullptr;

	pFront = pBack = L;

	int ii = 0;
	while (ii++ < k-1)
	{
		pFront = pFront->m_pNext;
	}

	while (pFront->m_pNext != nullptr)
	{
		pFront = pFront->m_pNext;
		pBack = pBack->m_pNext;
	}

	return pBack;
}

10. 合并两排序的链表。

ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
        if (pHead1 == nullptr)
		  return pHead2;
	  if (pHead2 == nullptr)
		  return pHead1;

	  ListNode *pNewHead = nullptr, *pNewTail = nullptr;
	  ListNode *pNode1 = pHead1, *pNode2 = pHead2;

	  while (pNode1 != nullptr && pNode2 != nullptr)
	  {
		ListNode *pTmp = nullptr;

		if (pNode1->val < pNode2->val)
		{
			pTmp = pNode1;
			pNode1 = pNode1->next;
		}
		else
		{
			pTmp = pNode2;
			pNode2 = pNode2->next;
		}

		if (pNewHead == nullptr)
		{
			pNewHead = pNewTail = pTmp;
		}
		else
		{
			pNewTail->next = pTmp;
			pNewTail = pNewTail->next;
		}
	  }

	  if ( pNode1 == nullptr )  //和归并排序时的判断条件不一样。
	  {
		pNewTail->next = pNode2;
	  }
	  if ( pNode2 == nullptr )
	  {
		pNewTail->next  = pNode1;
	  }

	  return pNewHead;
}

11. 删除链表中重复的节点. 180420

ListNode* deleteDuplication(ListNode* pHead)
{
	if(pHead == nullptr)
		return nullptr;
	if (pHead->next == nullptr)
		return pHead;
	if (pHead->val == pHead->next->val && pHead->next->next == nullptr)
		return nullptr;

	ListNode *pNewNode = new ListNode(-1);
	pNewNode->next = pHead;
	
	ListNode *pLastNode = pNewNode;
	ListNode *pCurNode = pHead;
	ListNode *pNextNode = pHead->next;
	int flag = 0;

	while (pNextNode != nullptr)
	{
		while (pNextNode && pCurNode->val == pNextNode->val)
		{
			pNextNode = pNextNode->next;
			pCurNode->next = pNextNode;
			flag = 1;
		}
		
		if ( flag )
		{
			pCurNode = pNextNode;
			pLastNode->next = pCurNode;
			flag = 0;

			if (pNextNode)
				pNextNode = pNextNode->next;
		}

		if (pNextNode && pCurNode->val != pNextNode->val)
		{
			pLastNode = pLastNode->next;
			pCurNode = pCurNode->next;
			pNextNode = pNextNode->next;
		}

	}

	return pNewNode->next;
}

12. 找两个链表第一个公共节点。 180424

struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2)
{
      if (pHead1 == nullptr || pHead2 == nullptr)
      return nullptr;
        
      ListNode *pNode1 = pHead1, *pNode2 = pHead2;
	int cnt1 = 0, cnt2 = 0;
	while (pNode1)
	{
		cnt1++;
		pNode1 = pNode1->next;
	}
	while (pNode2)
	{
		cnt2++;
		pNode2 = pNode2->next;
	}

	pNode1 = (cnt1>cnt2) ? pHead1 : pHead2;
	pNode2 = (cnt1>cnt2) ? pHead2 : pHead1;

	for (int ii=0; ii!=abs(cnt1-cnt2); ++ii)
		pNode1 = pNode1->next;

	ListNode * pRet = nullptr;
	while (pNode1 && pNode2)
	{
		if (pNode1 == pNode2)
		{
			pRet = pNode1;
			break;
		}
		else
		{
			pNode1 = pNode1->next;
			pNode2 = pNode2->next;
		}
	}

	return pRet;
}

13. 复杂链表的复制。180424

struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
// ---------------牛客网大神通过的版本---------------
RandomListNode* Clone(RandomListNode* pHead )
{
	if(!pHead)
		return NULL;
	RandomListNode *currNode = pHead;

	while(currNode)
	{
		RandomListNode *node = new RandomListNode(currNode->label);
		node->next = currNode->next;
		currNode->next = node;
		currNode = node->next;
	}
	currNode = pHead;
	while(currNode)
	{
		RandomListNode *node = currNode->next;
		if (currNode->random)
			node->random = currNode->random->next;

		currNode = node->next;
	}
	//拆分
	RandomListNode *pCloneHead = pHead->next;
	RandomListNode *tmp;
	currNode = pHead;

	while(currNode->next)
	{
		tmp = currNode->next;
		currNode->next =tmp->next;
		currNode = tmp;
	}

	return pCloneHead;
}
// ------------ 自己的版本,未通过,错误尚未找出-------------
RandomListNode* Clone(RandomListNode* pHead)
{
        if (pHead == nullptr)
		  return nullptr;

	  // ------------ 拷贝----------------
	  RandomListNode *pNode = pHead;
	  while (pNode)
	  {
		RandomListNode *pTmp = new RandomListNode(*pNode);
		pTmp->next = pNode->next;
		pNode->next = pTmp;

		if (pNode->random)
			pTmp->random = pNode->random->next;

		pNode = pTmp->next;
		pTmp = nullptr;
	  }

	  // ------------- 拆分-----------------
	  pNode = pHead;
	  RandomListNode *pNewHead = pHead->next;
	  RandomListNode *pProcNode = pNewHead;

	  if (pNode)   // 要让pNode走在pProcNode的前面。
	  {
		pNode->next = pProcNode->next;
		pNode = pNode->next;
	  }

	  while (pProcNode && pNode)
	  {
		pProcNode->next = pNode->next;  // pNode后面不会是空,所以这样赋值可以确保pProcNode后面不会是空
		pProcNode = pProcNode->next;
		pNode->next = pProcNode->next;
		pNode = pNode->next;
	  }

	  return pNewHead;
}

14. 寻找链表中环的入口节点。180425

ListNode* EntryNodeOfLoop(ListNode* pHead)
{
	if(pHead == nullptr || pHead->next == nullptr)
		return nullptr;

	ListNode *pFast = pHead, *pLow = pHead;

	// ----------- 获取环的大小------------
	int cnt = 0;
	pFast = pFast->next;
	pFast = (pFast==nullptr) ? pFast : pFast->next;
	pLow = pLow->next;
	++cnt;

	while (pFast != pLow && pFast)
	{
		pFast = pFast->next;
		pFast = (pFast==nullptr) ? pFast : pFast->next;
		pLow = pLow->next;
		++cnt;
	}

	if (pFast == nullptr)
		return nullptr;

	// --------获取环的入口-----------
	pFast = pLow = pHead;
	ListNode *pRet = nullptr;
	for (int ii=0; ii != cnt; ++ii)
		pFast = pFast->next;
	
	while (pFast != pLow)
	{
		pFast = pFast->next;
		pLow = pLow->next;
	}
	pRet = pFast;

	return pRet;
	
}

15. 主函数测试。

int main(int argc, char **argv)
{
	ListNode * L = new ListNode;
	InitList(L);

	cout << "请输入链表节点,以-1结束:" << endl;
	L = CreateListFromTail();
	DisplayList(L);

	int pos = 1, value = 10;
	cout << "在指定位置 " << pos << " 前方插入节点:" << value << endl;
	InsertListNodeFromFront(L, pos, value);
	DisplayList(L);

	pos = 2; value = 20;
	cout << "在指定位置 " << pos << " 后方插入节点:" << value << endl;
	InsertListNodeFromBack(L, pos, value);
	DisplayList(L);

	cout << "删除值为 " << value << " 的节点:"  << endl;
	DeleteListNode(L, value);
	DisplayList(L);

	cout << "翻转链表:" << endl;
	ListNode *R = ReverseList(L);
	DisplayList(R);

	getchar();getchar();
	return 0;
}

测试结果:





猜你喜欢

转载自blog.csdn.net/weixin_38984102/article/details/79708742