直接上代码,在操作的过程中需要注意的是:在对节点操作过程中,对第一个节点和其他位置的节点操作方式不一样。
目前包含以下几种面试经常会碰到的函数:
void reverseList(); //节点的倒置
NODE* reverseGet(int pos); //获取倒数第几个数据
NODE* getMidNode(); //获取中间的节点
NODE* hasCircle(); //检查一个链表里面有没有环
实现代码如下:
头文件
/*************************************************************************
> File Name: testlist.h
> Author: qiaozp
> Mail: qiaozongpeng@163.com
> Created Time: 2014-9-25 10:00:36
> Attention: 本段代码中第几个位置 默认是从1开始算的 而非0
************************************************************************/
//链表中的节点
typedef struct _NODE
{
char name[100];
int age;
struct _NODE* next;
void clear()
{
memset(name, 0, 100);
age = 0;
next = NULL;
}
_NODE()
{
clear();
}
}NODE;
//链表的操作类
class LIST
{
public:
LIST();
~LIST();
void clear(); //清空操作
int getCnt(); //获取当前链表个数
void insetNode(NODE& inNode); //在尾部插入节点
void insetNode(int pos, NODE& inNode); //在某一个位置插入节点
void show(); //展示链表中的数据
void deleteNode(int pos); //删除节点
void reverseList(); //节点的倒置
NODE* reverseGet(int pos); //获取倒数第几个数据
NODE* getMidNode(); //获取中间的节点
NODE* hasCircle(); //检查一个链表里面有没有环
private:
NODE* node;
int iCnt;
};
CPP文件
/*************************************************************************
> File Name: testlist.c
> Author: qiaozp
> Mail: qiaozongpeng@163.com
> Created Time: 2014-9-25 10:00:36
> Attention: 本段代码中第几个位置 默认是从1开始算的 而非0
************************************************************************/
#include <string.h>
#include <iostream>
#include "testlist.h"
using namespace std;
LIST::LIST():node(NULL), iCnt(0)
{
}
LIST::~LIST()
{
NODE* pNode;
while (this->node != NULL)
{
pNode = node->next;
delete node;
node = pNode;
}
}
void LIST::clear()
{
NODE* pNode;
while (this->node != NULL)
{
pNode = node->next;
delete node;
node = pNode;
}
}
int LIST::getCnt()
{
return iCnt;
}
void LIST::insetNode(NODE& inNode)
{
NODE* pNode = node;
//为空的情况下,直接插入
if(node == NULL)
{
node = new NODE();
node->age = inNode.age;
strncpy(node->name, inNode.name, strlen(inNode.name));
node->next = NULL;
}
else
{
//非空的情况下,找到最后一个位置插入
NODE* newNode = new NODE();
newNode->age = inNode.age;
strncpy(newNode->name, inNode.name, strlen(inNode.name));
while (pNode->next != NULL)
{
pNode = pNode->next;
}
newNode->next = NULL;
pNode->next = newNode;
}
++iCnt;
}
void LIST::insetNode(int pos, NODE& inNode)
{
if (getCnt() == 0)
{
cout << "空链表" << endl;
return ;
}
if ((pos < 0) || (pos > getCnt()))
{
cout << "插入的位置不对" << endl;
return ;
}
NODE* pNode = node;
NODE* newNode = NULL;
newNode = new NODE();
newNode->age = inNode.age;
strncpy(newNode->name, inNode.name, strlen(inNode.name));
//没有前驱数据的下的操作
if ((node == NULL) || (pos == 1))
{
newNode->next = node;
node = newNode;
}
else
{
//有前驱数据情况下的操作
while ((--pos) > 1)
{
pNode = pNode->next;
}
newNode->next = pNode->next;
pNode->next = newNode;
}
++iCnt;
}
void LIST::show()
{
NODE* pNode = node;
while (pNode != NULL)
{
cout << pNode->name << " : " << pNode->age << endl;
pNode = pNode->next;
}
}
void LIST::deleteNode(int pos)
{
if((pos < 0) || (pos > getCnt()))
{
cout << "超出选择范围" << endl;
return ;
}
if(this->getCnt() == 1)
{
//只有一个节点的话直接删除
delete node;
node = NULL;
--iCnt;
}
else
{
//有多个节点的情况下需要保存删除节点中的数据
NODE* pNode = node;
while((--pos) > 1)
{
pNode = pNode->next;
}
NODE* tmp = pNode->next;
pNode->next = pNode->next->next;
delete tmp;
--iCnt;
}
}
void LIST::reverseList()
{
if (this->getCnt() == 0)
{
return ;
}
//A-->B-->C--D ==> A<--B<--C<--D
//就是指向的转变
//以当前节点为基础,找到下面一个节点,转换指针,然后往后移
NODE* pre = NULL;
NODE* next = NULL;
while(node != NULL)
{
next = node->next;
node->next = pre;
pre = node;
node = next;
}
node = pre;
}
NODE* LIST::getMidNode()
{
//reverseGet()函数机制类似
//两个指针,一个一次走两步,一个一次走一步,走两步的到尾了,走一步的正好到中间
if (node == NULL)
{
cout << "链表是空的,取毛啊." << endl;
return NULL;
}
NODE* fast = node;
NODE* slow = node;
while((fast != NULL) && (fast->next != NULL))
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
NODE* LIST::reverseGet(int pos)
{
if ((pos > iCnt) || (pos < 0))
{
cout << "获取的数据超过最大限制" << endl;
return NULL;
}
//获取倒数第几个数据
//方法:定义两个变量fasrt slow同时指向头,
//然后fast先走pos步,然后一起走,当fast到尾的时候,slow就是倒数第pos个
NODE* fast;
NODE* slow;
fast = slow = node;
int tmp = pos;
for (; tmp > 0 && fast != NULL; --tmp)
{
fast = fast->next;
}
while (fast != NULL)
{
slow = slow->next;
fast = fast->next;
}
return slow;
}
NODE* LIST::hasCircle()
{
//原理和getMidNode reverseGet 差不多,利用两个节点产生距离查找交集
NODE* fast = node;
NODE* slow = node;
while ((fast != NULL) && (fast->next != NULL))
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
{
return fast;
}
}
return NULL;
}
int main()
{
LIST l;
NODE node;
strcat(node.name, "MJ");
node.age = 12;
l.insetNode(node);
node.clear();
strcat(node.name, "qiaozp");
node.age = 13;
l.insetNode(node);
node.clear();
strcat(node.name, "zhuh");
node.age = 15;
l.insetNode(2, node);
node.clear();
strcat(node.name, "Json");
node.age = 16;
l.insetNode(1, node);
cout << "倒置之前的数据 : " << endl;
l.show();
l.reverseList();
cout << "倒置之后的数据 : " << endl;
l.show();
cout << "删除第三个节点后的数据 : " << endl;
l.deleteNode(3);
l.show();
NODE* rNode = l.reverseGet(2);
if (rNode == NULL)
{
return -1;
}
cout << "获取的倒数第二个数据为: 名字: " << rNode->name << ". 年龄:" << rNode->age << endl;
rNode = NULL;
rNode = l.getMidNode();
if (rNode == NULL)
{
return -1;
}
cout << "获取到的中间的数据为: 名字: " << rNode->name << ". 年龄:" << rNode->age << endl;
//倒转数据之后进行打印
return 0;
}