head_LinkNode.h
/*单链表类的头文件*/
#include<assert.h>
#include"compare.h"
typedef int status;//整形的状态值
#define OK 1;//status参数
#define ERROR 0;//status参数
template <class type>
class LinkNode
{
protected:
LinkNode* head;
public:
void out();//输出函数
LinkNode()//对象初始化
{
data=0;
next=NULL;
head=NULL;
}
void menu();//菜单
LinkNode<type> operator=(LinkNode<type> right);
private:
void sort();//排序
void putin(int a);//输入函数
status insert(int a,type b);//插入函数
void clear();//清空
void inversion();//倒置节点
status delc(type a);//删除所有指定data节点
status find(type a);//查找(通过参数号)
status del(int a);//删除函数(指定位号)
status locateELem(type e,status (*compare)(type,type));
//成员变量
type data;
LinkNode<type> *next;
static int n;//当前单链表元素个数
//成员变量
typedef LinkNode * nodepoint;//指向节点的指针(在类内不用给出类型 在对象生成时类型确定)
};
template <class type>
int LinkNode<type>::n=0;//只能在类外初始化
/*
功能:运算符重载
方法:先置空 左边 后通过滑动不断用右边赋值左边
*/
template <class type>
LinkNode<type> LinkNode<type>::operator=(LinkNode<type> right)
{
nodepoint p=NULL;//指向左边的单链表当前节点为空
nodepoint rp=right.head;//指向右边的单链表当前节点
nodepoint s;//在赋值过程中左边可能需要的新节点
if(this!=&right)
{
clear();//清空左边
while(rp)
{
s= new LinkNode;
assert(s!=0);
s->data=rp->data;
if(!head)
head=s;
else
p->next=s;
p=s;
rp=rp->next;
}
if(p)
p->next=NULL;
}
return *this;
}
/*
功能:在第a个节点前插入一个节点
方法:先判断一种特殊情况(在头部插入) 并且特殊处理 对于普通情况采用先用循环滑动到指定节点前再做处理
*/
template <class type>
status LinkNode<type>::insert(int a,type b)
{
int j=1;//表示当前单链表的序号
nodepoint p=head;//从第一个节点开始循环;
nodepoint s;//用于插入
if(a==1)//在头部插入情况
{
s= new LinkNode;
assert(s!=0);
(*s).data=b;
(*s).next=head;
head=s;
n++;
return OK;
}
if(a>n)
return ERROR;
while(p&&j<a-1)//从头节点开始滚动到指定插入点的前一个节点
{
p=p->next;
j++;
}
s= new LinkNode;
assert(s!=0);
s->data=b;
s->next=p->next;
p->next=s;
n++;
char u='y';
cout<<"是否排序?(y or n?)"<<endl;
cin>>u;
if(u=='y')
sort();
return OK;
}
/*
功能:输入
方法:通过插入和倒置函数实现
*/
template <class type>
void LinkNode<type>::putin(int a)
{
clear();
type b;
cout<<"输入开始"<<endl;
for(;a>0;a--)
{
cin>>b;
insert(1,b);
}
inversion();
}
/*
功能:输出单链表
方法:通过next指针不断滑动输出节点DATA
*/
template <class type>
void LinkNode<type>::out()
{
nodepoint p=head;
cout<<"当前单链表"<<endl;
while(p)
{
cout<<p->data<<' ';
p=p->next;
}
cout<<endl;
}
/*
功能:删除指定节点(指定位号)
方法:滑动前驱节点和当前结点到指定位号 使前驱结点直接连接后继节点
*/
template <class type>
status LinkNode<type>::del(int a)
{
nodepoint p=head;//当前节点
nodepoint r=NULL;//前驱节点
int i=1;
if(a>n)
return ERROR;
if(a==1)//特殊处理删除第一个节点
{
head=p->next;
p=NULL;
n--;
return OK;
}
while(p&&i!=a)
{
r=p;
p=(*p).next;
i++;
}
if(a==n)//特殊处理删除尾节点
{
r->next=NULL;
p=NULL;
n--;
return OK;
}
r->next=p->next;
n--;
p=NULL;
return OK;
}
/*
功能:返回查找的节点
方法:滑动当前结点到指定位号 返回data
*/
template <class type>
status LinkNode<type>::find(type a)
{
nodepoint p=head;
int i=1;
while(p)
{
if(a==p->data)
{
cout<<a<<"是单链表中的第"<<i<<"个节点"<<endl;
return OK;
}
i++;
p=p->next;
}
return ERROR;
}
/*
功能:清空单链表
方法:以单链表节点数n为基准通过不断的调用del函数删除第一个节点从而清空单链表
*/
template <class type>
void LinkNode<type>::clear()
{
int i=1;
while(head!=NULL&&i<=n)
{
del(1);
i--;
}
n=0;
}
/*
功能:倒置单链表
方法:先把next指针从链向后变为链向前 然后通过变换前驱、当前、后继的指向重复变换next 及完成倒置
*/
template <class type>
void LinkNode<type>::inversion()
{
if(n==0)
return;
nodepoint p=head;
nodepoint r=NULL;
nodepoint q=p->next;
while(p)
{
p->next=r;
r=p;
p=q;
if(q)//保证后继指针q不会出表
q=p->next;
}
head=r;
}
/*
功能:删除所有指定data节点
方法:从头滚动到链尾找到与参数a相等的data就利用del函数删除这个节点
*/
template <class type>
status LinkNode<type>::delc(type a)
{
nodepoint p=head;
int i=1;
int c=ERROR;
while(i<=n)
{
if(p->data==a)
{
del(i);
i=i-1;//删除后从上一位开始找
c=OK;
}
p=p->next;
i++;
}
return c;
}
/*菜单*/
template <class type>
void LinkNode<type>::menu()
{
char p='y';
int a;
for(;;)
{
cout<<"****************************处理菜单****************************"<<endl;
cout<<"1.输入"<<endl;
cout<<"2.输出"<<endl;
cout<<"3.插入"<<endl;
cout<<"4.倒置"<<endl;
cout<<"5.查找"<<endl;
cout<<"6.删除指定位号节点"<<endl;
cout<<"7.删除指定元素在单链表中的所有节点"<<endl;
cout<<"8.清空单链表"<<endl;
cout<<"9.排序"<<endl;
out();
cout<<"****************************处理菜单****************************"<<endl;
cout<<"请选择:";
cin>>a;
switch(a)
{
case 1:{
int b;
cout<<"请输入你要输入节点的个数"<<endl;
cin>>b;
putin(b);
};break;
case 2:{
out();
};break;
case 3:{
type c;
int y;
cout<<"请输入你要插在那位节点前面"<<endl;
cin>>y;
cout<<"请输入你要插入的元素"<<endl;
cin>>c;
if(insert(y,c))
cout<<"OK"<<endl;
else
cout<<"ERROR";
};break;
case 4:{
inversion();
};break;
case 5:{
type y;
cout<<"请输入你要查找的数据"<<endl;
cin>>y;
if(find(y))
cout<<"OK"<<endl;
else
cout<<"ERROR"<<endl;
};break;
case 6:{
int y;
cout<<"请输入你要删除的节点位号"<<endl;
cin>>y;
if(del(y))
cout<<"OK"<<endl;
else
cout<<"ERROR";
};break;
case 7:{
type y;
cout<<"请输入你要删除的元素"<<endl;
cin>>y;
if(delc(y))
cout<<"OK"<<endl;
else
cout<<"ERROR";
};break;
case 8:{
clear();
};break;
case 9:{
sort();
};break;
}
getchar();//接受回车
cout<<"是否继续处理?(n退出)"<<endl;
p=getchar();
system("cls");
if(p=='n')
break;
}
}
/* 功能:排序
方法:使用冒泡排序通过不断滚动对比data交换data达到排序目的
*/
template <class type>
void LinkNode<type>::sort()
{
nodepoint p=head;
nodepoint q=p->next;
type s;
for(int i=0;i<n;i++)
{
p=head;
q=p->next;
for(int c=0;c<n-i-1;c++)
{
if(p->data>q->data)
{
s=p->data;
p->data=q->data;
q->data=s;
}
p=p->next;
q=p->next;
}
}
}
LinkNode.cpp
#include"head_LinkNode.h"
#include<iostream>
#include<string>
using namespace std;
int main()
{
int a;
char p='y';
for(;;)
{
cout<<"请输入你要处理的数据类型(char(1) int(2) float(3) double(4) )"<<endl;
cin>>a;
switch(a)
{
case 1: {LinkNode<char> sq;
sq.menu();
}break;
case 2: {LinkNode<int> sq;
sq.menu();
}break;
case 3: {LinkNode<float> sq;
sq.menu();
}break;
case 4: {LinkNode<double> sq;
sq.menu();
}break;
default: cout<<"错误请重新输入"<<endl;
}
cout<<"是否继续处理其他类型顺序表? 请输入 任意字符继续或n结束"<<endl;
getchar();
p=getchar();
if(p=='n')
break;
}
system("pause");
}