//这一次补上链表的注释,代码是空闲的时候敲出来的,如果有错,希望帮忙纠正
//部分给出了详细说明,这里只选取了基本操作,因为更复杂的链表操作太繁琐,这里就不写了
//如果有什么不懂的地方,可以随时询问
#include <iostream>
using namespace std;
typedef int Elemtype;
struct Node
{
Elemtype data;
Node *next;
};
void Init(Node **L) //主函数里面定义Node型指针变量plist,储存单链表的头指针
{
//Node *L;
// L=new Node;
*L=NULL;
cout<<"初始化成功!\n";
}
//初始化函数形参要给二级指针,相应的主函数里面实参则是对头指针的引用
void Clear_List(Node *head) //清空函数
{
Node *flag;
if(head==NULL)
{
cout<<"链表为空!\n";
return;
}
while(head->next!=NULL)
{
flag=head->next;
delete(head);
head=flag;
}
cout<<"链表已经清空!\n";
}
//加一个标记,移动头指针后赋值flag保存下一个位置,然后删除当前节点
Node *Creat_list(Node *head) //赋值函数
{
//int n=0;
Node *p1,*p2;
p1=new Node;
p2=new Node;
//head=NULL;
cout<<"请输入链表元素,以0结束输入:"<<endl;
cin>>p1->data;
p1->next=NULL;
while(p1->data!=0)
{
//n=n+1;
//if(n==1)
if(head==NULL)
head=p1;
else
p2->next=p1;
p2=p1;
p1=new Node;
cin>>p1->data;
p1->next=NULL;
}
//cout<<head->data;
return head;
}
//读入链表元素,在while循环里面每次将当前指针保存下来,然后不断向后更新
void List_length(Node *head)
{
int i=0;
while(head!=NULL)
{
i++;
head=head->next;
}
cout<<"链表长度length: "<<i<<endl;
}
void Out_list(Node *head)
{
// cout<<head->data;
if(head==NULL)
cout<<"链表为空!\n";
else
{
while(head!=NULL)
{
cout<<head->data<<" ";
head=head->next;
}
cout<<endl;
}
}
Elemtype Get_elem(int index,Node *head) //给定下标,求节点元素
{
int j=0;
//Node *p;
while(head!=NULL)
{
j++;
if(j==index)
break;
head=head->next;
}
if(j<index)
{
cout<<"选取的范围超出链表长度!\n";
return 0;
}
return head->data;
}
//给定的下标index,只需遍历链表,当节点数符合要求时即可
int locate_elem(Node *head,Elemtype _First) //给定节点元素,求第一个下标(也可以扩展求多个点的下标)
{
int n=1;
while(head!=NULL)
{
if(head->data==_First)
return n;
else
n++;
head=head->next;
}
cout<<"单链表里不存在这个元素!\n";
}
//同理,遍历查找出给定元素,然后直接返回下标
bool Insert_elem(Node *head,Elemtype insert_elem,int index)
{
Node *p,*q;
if(index<1)
{
cout<<"输入下标有误!\n";
return false;
}
int i=1;
while(head!=NULL)
{
i++;
head=head->next;
if(i==index-1)
{
p=q=new Node;
q=head;
//head=head->next;
(*p).data=insert_elem;
//这里调试了好久。。。开始我是想定义一个节点和一个指针的,输出的时候会报错
//最后还是觉得都定义指针吧,p那里不加括号的话也会报错
(*p).next=head->next;
q->next=p;
//p->next=head->next;
//p->data=insert_elem;
return true;
}
}
return false;
}
//插入步骤稍微多些,要另外定义两个指针,思路就是遍历到给定下标的前一个下标,同时指针q记录下位置
//而另外一个指针p储存节点数据,并且使它指向头指针下一个点的地址,最后使q指向p即可
bool delete_Node(Node *head,int index)
{
int i=1;
if(index<1)
{
cout<<"输入下标值有误!\n";
return false;
}
while(head!=NULL)
{
i++;
head=head->next;
if(i==index-1)
{
Node *p;
p=new Node;
p=head;
head=head->next;
p->next=head->next;
return true;
}
}
return false;
}
//操作类似于插入,不多说
bool Change_Node_Elem(Node *head,int index,Elemtype Example3)
{
int i=1;
if(head==NULL||index<1)
{
cout<<"输入错误或链表为空!\n";
return false;
}
while(head!=NULL)
{
i++;
head=head->next;
if(i==index)
{
head->data=Example3;
return true;
}
}
return false;
}
//也是遍历链表找到给定位置,然后更新数据
int main()
{
//Node *plist=NULL;
Node *plist;
Elemtype Example1=5,Example2=7,Example3=9;
cout<<"创建一个单链表(plist):\n";
Init(&plist); //初始化
plist=Creat_list(plist); //创建单链表,给单链表赋值,返回头指针
cout<<"打印原始链表:\n";
Out_list(plist);
cout<<endl;
cout<<"链表第三个节点的元素值为: "<<Get_elem(3,plist)<<endl;
cout<<endl;
//调用Get_elem函数,返回链表第三个节点内元素值
//cout<<"输出链表长度:\n";
List_length(plist);
cout<<endl;
cout<<"链表plist第一次出现 "<<Example1<<" 值的下标:"<<locate_elem(plist,Example1)<<endl;
cout<<endl;
//调用locate_elem函数,返回链表内第一个出现Example1元素的节点数
cout<<"将元素 "<<Example2<<" 插入链表第四个节点上:"<<endl;
if(Insert_elem(plist,Example2,4))
cout<<"Insert is OK!\n";
else
cout<<"Insert is not OK!\n";
cout<<"改变后的链表为:"<<endl;
Out_list(plist);
cout<<endl;
cout<<"将链表第七个节点删除:"<<endl;
if(delete_Node(plist,7))
cout<<"Delete is OK!\n";
else
cout<<"Delete is not OK!\n";
cout<<"改变后的链表为:"<<endl;
Out_list(plist);
cout<<endl;
cout<<"将链表plist中第三个节点的元素换成 "<<Example3<<endl;
if(Change_Node_Elem(plist,3,Example3))
{
cout<<"改变后的链表为:\n";
Out_list(plist);
}
else
cout<<"数值改变失败!\n";
cout<<endl;
cout<<"执行清空函数:"<<endl;
Clear_List(plist);
return 0;
}