单链表在插入、删除时较为方便,平时做题或者面试也会遇到很多,下面对单链表的操作做一些介绍。
本文参考了一些blog,不过只记得下面这个啦:
http://blog.csdn.net/puqutogether/article/details/39990419
定义一个结构体:
struct Node
{
int data;
Node* next;
};
在 运算前先定义一个全局变量 head:
Node* head=NULL;
1.创建一个有头结点的链表
bool CreateLink()//创建链表
{
head=new Node;
if(head==NULL)
return false;
else
{
head->data=0;
head->next=NULL;
return true;
}
}
2.增加节点
bool AddNode(Node *addNode)//增加节点
{
Node *p=head->next;
Node *q=head;
while(p!=NULL)//往后查找,直到找到最后的位置
{
q=p;
p=p->next;
}
q->next=addNode;
addNode->next=NULL;
return true;
}
3.计算节点总数
int CountNode()//计算节点
{
Node *p=head->next;
int count=0;
while(p!=NULL)
{
count++;
p=p->next;
}
return count;
}
4.查找节点
int Search(int x)//查找节点的元素值为x的下标
{
Node *p=head->next;
for(int j=1;p&&p->data!=x;j++)
p=p->next;
if(p)
return j;
return -1;
}
5.插入节点
bool Insert(int i,int x)//在a[i]节点后面插入x(节点从a[0]开始标记)
{
Node *p=head;
for(int j=0; j<=i; j++)
p=p->next;
Node *q=new Node;
q->data=x;
q->next=p->next;//在p后面插入q,无需区分头结点和一般节点
p->next=q;
return true;
}
6.删除节点
bool Delete(int i)//删除第i个节点
{
Node *q=head,*p;
for(int j=0; j<i; j++)
{
q=q->next;
}
p=q->next;
q->next=p->next;
delete p;
return true;
}
7.链表反转
每次都将第一个节点之后的节点放在head后面。tmp指向第一个节点,p指向第二个节点,再把第二个节点放在head与第一个节点之间,就完成了第一次交换,顺序就变成了Head-结点2-结点1-结点3-结点4-NULL。同样下次再把结点3放在head与结点之间,以此类推。
void ReverseLink()//链表反转
{
Node *tmp=NULL;
Node *p=NULL;
tmp=head->next;
while(tmp->next!=NULL)
{
p=tmp->next;
tmp->next=p->next;
p->next=head->next;
head->next=p;
}
}
8.查找倒数第k个节点
给两个指针p和q,让其中一个指针p领先q指针k步,然后再同时移动p和q指针,当领先的指针p先到达链表尾部时,后面的指针q所指向的节点恰好为倒数第k个节点。
Node* GetKthNode(int k)
{
Node *p=head;
Node *q=head;
while(k>1 && p->next!=NULL)
{
p=p->next;
k--;
}
if(k>1 || p==NULL)
return NULL;
while(p->next!=NULL)
{
q=q->next;
p=p->next;
}
return q;
}
9.判断链表是否成环
这里使用两个指针q和p,一个指针走两步(p),一个指针走一步(q)。如果成环,两个指针会在O(n)内相遇 ,否则先走的会指向空。
bool Iscircle(Node *head)//判断是否有环
{
Node *p=head;
Node *q=head;
while(p!=NULL && p->next!=NULL)
{
p=p->next->next;
q=q->next;
if(p==q)
return true;
}
return false;
}