您的位置:首页 > 其它

链表只翻转一部分

2017-07-24 00:54 197 查看
题目描述:

链表翻转。给出一个链表和一个数k,比如链表1→2→3→4→5→6,k=2,翻转后2→1→4→3→6→5,若k=3,翻转后3→2→1→6→5→4,若k=4,翻转后4→3→2→1→5→6,用程序实现Node* RotateList(Node* list, size_t k).

(提示:这个题是链表逆置的升级变型)

难点分析:

在原来链表逆置的基础上添加了k作为新的限制条件而已。

思路:

由题目要求可知:

k=0或1时,相当于没有修改链表,可以直接返回。

k>1时,需要断开并重新连接k-1条链,另外还需一条链来连接前k个节点与后面节点

主要还是分为

1,链表我空或只有一个节点。

2,链表有2个以上节点。

特别给出其中一种情况示意图,其他情况类似。



实现代码:

//头结点信息
typedef int DataType;
typedef struct ListNode
{
ListNode(DataType data = DataType())
: m_data(data)
, m_pNext(nullptr)
{}
DataType m_data;
ListNode *m_pNext;
}Node;

Node* RotateList(Node* list, size_t k)
{
//注:当k大于等于链表节点个数时,看做是把链表全翻转

//当链表为空,或只有一个节点,或k为0或1
if (nullptr == list || nullptr == list->m_pNext || 0 == k || 1 == k)
return list;

//处理节点个数大于等于2,并且k>1 的情况
//通过三个指针来翻转链表
Node *pPre = list;
Node *pCur = pPre->m_pNext;
Node *pTail = pCur->m_pNext;

//将链表遍历一次,或者循环k-1次
while (pCur && k>1)
{
pCur->m_pNext = pPre;

pPre = pCur;
pCur = pTail;

//当pTail为NULL,pCur=NULL,表示最后一个节点已经翻转过了,下次循环跳出。
if (pTail)
pTail = pTail->m_pNext;

--k;  //翻转了一个节点
}

//当pTail不为nullptr时,此时k=1,表示函数传入的k值小于节点个数,此时pTail指向第k+1个节点。
//当pTail为nullptr时,此时k>=1,表示链表节点个数小于等于k,当做全翻转处理
//所以,不管pTail为不为NULL,list->m_pNext都要指向pCur来连接两部分。
list->m_pNext = pCur;

//此时pCur指向新的头结点
return pPre;
}


测试代码:

//打印单链表
void PrintList(Node *pHead)
{
while (pHead)
{
printf("%d->", pHead->m_data);
pHead = pHead->m_pNext;
}

printf("NULL\n");
}

int main()
{
int i = 0;
Node node[10] = { 0 }; //建立10个node用来做实验
Node *pHead = &node[0]; //指向头结点

//给node赋值
for (; i < 10; ++i)
node[i].m_data = i+1;
//构成一个单链表
for (i = 0; i < 9; ++i)
node[i].m_pNext = &node[i + 1];
node[9].m_pNext = NULL; //注意,最后一个节点指向NULL

cout << "翻转前:";
PrintList(pHead);   //打印旧的单链表

//翻转前k个节点
int k = 3;
pHead = RotateList(pHead, k);

cout << "翻转前:";
PrintList(pHead); //打印新的单链表

system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息