1.在类中嵌套链表,保存学生的姓名和学号可以按照链表的操作对其进行操作,但是要求在类外除了使用公共函数接口和友元函数可以调用数据内容外其他的函数都不可以对其进行相关的操作。
为什么要用类去写链表而不使用c语言结构体去书写链表呢?
个人认为用类去书写链表一个优点在于,它可以对链表的函数进行封装即外部不可以去调用类中关于链表的函数,因为结构体和类的默认成员不同,类中默认成员为private。
第二个优点是在类的外部不可以使用其他函数(除类的接口)去更改链表中的相关内容,它可以确保链表中的内容不会被轻易更改!
该类的结构如下所示:
class List{
typedef struct Node{ //类中的结构体嵌套
string name;
string num;
struct Node *next;
}Node;
public:
List();
~List();
void print()const; //输出链表
bool insert(int pos); //链表的插入
bool Delete(int pos); //链表的删除
void seek(int pos)const; //链表的查询
void seek(string name)const;
void seek2(string num)const;
void fixed(string name); //链表的修改
void exchange(List L); //对链表进行排序
int getlen(); //得到链表的长度
protected:
Node * head; //受保护的对象,指向结构体的指针(头指针)
};
该类中使用了类与结构体的嵌套,在类中又定义了一个受保护的数据指向结构体的指针,也就是这里的结构体的头指针。公共函数中包含了关于列表的一些简单操作即增删改查等操作。
构造函数和析构函数:
构造函数和析构函数在此的作用分别是对链表进行初始化,对链表进行逐一的删除操作。
List::List() //类的构造函数,也就是链表的初始化
{
head = new Node;
head->name='0';
head->num='0';
head->next=NULL;
}
List::~List() //类的析构函数,也就是对每一个元素结点进行删除
{
Node *temp;
temp=head;
while(head)
{
head=head->next;
delete temp;
}
head=NULL;
}
输出以及插入函数如下:
输出和插入函数即链表的简单输出函数,因为它不会更改其内容所以在函数后面设置const,使得程序可以运行相对于快一点。插入函数则说明了在哪一个位置插入什么值。
void List::print()const //对类中结构体链表进行注意的输出
{
Node *p;
p = head ->next;
cout<<"按照成员名称和成员学号顺序输出:\n";
while(p)
{
cout<<p->name<<" "<<p->num<<endl;
p = p->next;
}
}
bool List::insert(int pos) //向链表中插入数据
{
Node *s,*t;
int i;
string name,num;
if(pos<=0) //如果输入的位置小于等于0说明不插入即输入位置不正确
{
cout<<"您输入的位置不正确!\n";
return false;
}
i=0;
s=head; //定义一个结构体指针指向头指针
while(i<pos-1&& s!=NULL) //查找要插入的位置
{
s=s->next;
i++;
}
if(s==NULL) //如果插入的位置的前一个位置为空则说明您输入的位置超过了范围
{
cout<<"您输入的位置超过了范围!\n";
return false;
}
t = new Node;
cout<<"请按照名字和学号顺序输入:\n"; //然后输入您要插入的数据
cin>>name>>num;
t->name=name;
t->num=num;
t->next=s->next; //进行插入操作
s->next=t;
return true;
}
删除以及查找函数如下:
删除函数则指定了在某一个位置对其进行删除的操作,与普通链表的删除类似。
查找函数这里分别对姓名和学号还有位置设置了不同的查找函数可以对代码进行运行后进行观察。
bool List::Delete(int pos) //按照位置进行删除操作
{
int i;
Node *p,*q;
if(pos<=0) //如果要删除的位置小于等于0则说明输入的位置不正确
{
cout<<"您输入的位置不正确!\n";
return false;
}
i=0;
p=head;
while(i<pos-1&&p!=NULL) //找到要删除元素的前一个结点
{
p=p->next;
i++;
}
if(p==NULL)
{
cout<<"您输入的位置超过了范围!\n";
return false;
}
q=p->next;
p->next=q->next;
delete q;
return true;
}
void List::seek(string name)const //按照名字进行查找数据
{
int flag=0;
Node *t;
t=head->next;
while(t) //循环链表查找内容
{
if(t->name == name)
{
cout<<"您要找的成员为:\n";
cout<<t->name<<" "<<t->num;
flag=1;
}
t=t->next;
}
if(flag==0)
cout<<"没有找到您要查找的数据!\n";
}
void List::seek2(string num)const //按照学号查找内容
{
int flag=0;
Node *t;
t=head->next;
while(t)
{
if(t->num == num)
{
cout<<"您要找的成员为:\n";
cout<<t->name<<" "<<t->num;
flag=1;
}
t=t->next;
}
if(flag==0)
cout<<"没有找到您要找的数据!\n";
}
void List::seek(int pos)const //按照位置查找内容
{
Node *t;
t=head;
int i;
while(i<pos&&t!=NULL)
{
t=t->next;
i++;
}
if(t==NULL)
{
cout<<"您输入的数字超过了范围!\n";
}
cout<<"您找到的成员为:\n";
cout<<t->name<<" "<<t->num;
}
修改以及排序、长度计算的函数如下:
修改是因为学生会因为转专业或其他事情而发生学号的更改所以这里设置了对一个人的学号进行修改。
排序是因为在班级中打印班级人姓名是大部分学习都是按照名字的顺序来进行排序的所以这里也进行了相关的排序操作。
void List::fixed(string name) //因为有些人会因为转专业或学校而更改了自己的学号
{
Node *t;
string m_num;
t=head;
while(t)
{
if(t->name==name)
{
cout<<"请输入修改后的学号:";
cin>>m_num;
t->num = m_num;
}
t=t->next;
}
}
void List::exchange(List L)
{
Node *t,*s;
int n;
string name,num;
t=head->next;
s=t->next;
n=L.getlen();
for(int i=0;i<n-1;i++)
{
for(int j=0;j<n-2-i;j++)
{
if(t->name < s->name)
{
name=t->name;
num=t->num;
t->name=s->name;
t->num=s->num;
s->name=name;
s->num=num;
}
s=s->next;
}
t=t->next;
}
L.print();
}
int List::getlen()
{
int i=1;
Node *t;
t=head->next;
while(t)
{
t=t->next;
i++;
}
return i;
}
整体操作的运行代码如下所示:(借走请留言谢谢!学生付出不容易)
#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;
class List{
typedef struct Node{ //类中的结构体嵌套
string name;
string num;
struct Node *next;
}Node;
public:
List();
~List();
void print()const;
bool insert(int pos);
bool Delete(int pos);
void seek(int pos)const;
void seek(string name)const;
void seek2(string num)const;
void fixed(string name);
void exchange(List L);
int getlen();
protected:
Node * head; //受保护的对象,指向结构体的指针(头指针)
};
List::List() //类的构造函数,也就是链表的初始化
{
head = new Node;
head->name='0';
head->num='0';
head->next=NULL;
}
List::~List() //类的析构函数,也就是对每一个元素结点进行删除
{
Node *temp;
temp=head;
while(head)
{
head=head->next;
delete temp;
}
head=NULL;
}
void List::print()const //对类中结构体链表进行注意的输出
{
Node *p;
p = head ->next;
cout<<"按照成员名称和成员学号顺序输出:\n";
while(p)
{
cout<<p->name<<" "<<p->num<<endl;
p = p->next;
}
}
bool List::insert(int pos) //向链表中插入数据
{
Node *s,*t;
int i;
string name,num;
if(pos<=0) //如果输入的位置小于等于0说明不插入即输入位置不正确
{
cout<<"您输入的位置不正确!\n";
return false;
}
i=0;
s=head; //定义一个结构体指针指向头指针
while(i<pos-1&& s!=NULL) //查找要插入的位置
{
s=s->next;
i++;
}
if(s==NULL) //如果插入的位置的前一个位置为空则说明您输入的位置超过了范围
{
cout<<"您输入的位置超过了范围!\n";
return false;
}
t = new Node;
cout<<"请按照名字和学号顺序输入:\n"; //然后输入您要插入的数据
cin>>name>>num;
t->name=name;
t->num=num;
t->next=s->next; //进行插入操作
s->next=t;
return true;
}
bool List::Delete(int pos) //按照位置进行删除操作
{
int i;
Node *p,*q;
if(pos<=0) //如果要删除的位置小于等于0则说明输入的位置不正确
{
cout<<"您输入的位置不正确!\n";
return false;
}
i=0;
p=head;
while(i<pos-1&&p!=NULL) //找到要删除元素的前一个结点
{
p=p->next;
i++;
}
if(p==NULL)
{
cout<<"您输入的位置超过了范围!\n";
return false;
}
q=p->next;
p->next=q->next;
delete q;
return true;
}
void List::seek(string name)const //按照名字进行查找数据
{
int flag=0;
Node *t;
t=head->next;
while(t) //循环链表查找内容
{
if(t->name == name)
{
cout<<"您要找的成员为:\n";
cout<<t->name<<" "<<t->num;
flag=1;
}
t=t->next;
}
if(flag==0)
cout<<"没有找到您要查找的数据!\n";
}
void List::seek2(string num)const //按照学号查找内容
{
int flag=0;
Node *t;
t=head->next;
while(t)
{
if(t->num == num)
{
cout<<"您要找的成员为:\n";
cout<<t->name<<" "<<t->num;
flag=1;
}
t=t->next;
}
if(flag==0)
cout<<"没有找到您要找的数据!\n";
}
void List::seek(int pos)const //按照位置查找内容
{
Node *t;
t=head;
int i;
while(i<pos&&t!=NULL)
{
t=t->next;
i++;
}
if(t==NULL)
{
cout<<"您输入的数字超过了范围!\n";
}
cout<<"您找到的成员为:\n";
cout<<t->name<<" "<<t->num;
}
void List::fixed(string name) //因为有些人会因为转专业或学校而更改了自己的学号
{
Node *t;
string m_num;
t=head;
while(t)
{
if(t->name==name)
{
cout<<"请输入修改后的学号:";
cin>>m_num;
t->num = m_num;
}
t=t->next;
}
}
void List::exchange(List L)
{
Node *t,*s;
int n;
string name,num;
t=head->next;
s=t->next;
n=L.getlen();
for(int i=0;i<n-1&&t!=NULL;i++)
{
for(int j=0;j<n-2-i&&s!=NULL;j++)
{
if(t->name < s->name)
{
name=t->name;
num=t->num;
t->name=s->name;
t->num=s->num;
s->name=name;
s->num=num;
}
s=s->next;
}
t=t->next;
}
L.print();
}
int List::getlen()
{
int i=1;
Node *t;
t=head->next;
while(t)
{
t=t->next;
i++;
}
return i;
}
int main()
{
List L;
int n,t,x;
char c;
string name,num;
cout<<"请输入要保存几个数据:";
cin>>n;
for(int j=1;j<=n;j++)
{
L.insert(j);
}
L.print();
cout<<"您是否想使用删除操作:\n";
cin>>c;
if(c=='y'||c=='Y')
{ cout<<"请输入您要删除几次:";
cin>>x;
while(x)
{
cout<<"请输入您要删除的位置:";
cin>>t;
L.Delete(t);
L.print();
x--;
}
}
cout<<"您是否想使用查找操作:\n";
cin>>c;
if(c=='y'||c=='Y')
{ cout<<"请输入您要查找几次:";
cin>>t;
while(t)
{
cout<<"请输入您要按照什么方式查找内容:1.姓名 2.位置 3.学号:";
cin>>x;
if(x==1)
{
cout<<"请输入您要查找的姓名:";
cin>>name;
L.seek(name);
}
else if(x==2)
{
cout<<"请输入您要查找的位置:";
cin>>t;
L.seek(t);
}
else if(x==3)
{
cout<<"请输入您要查找的学号:";
cin>>num;
L.seek2(num);
}
else
cout<<"您输入的数据有问题!\n";
cout<<endl;
t--;
}
}
cout<<"您是否想要修改学生的学号:";
cin>>c;
if(c=='y'||c=='Y')
{
cout<<"请输入您要修改几个人的学号:";
cin>>t;
while(t)
{
cout<<"请输入要修改人的姓名:";
cin>>name;
L.fixed(name);
cout<<"修改后的内容为:\n";
L.print();
t--;
}
}
cout<<"排序后的列表内容为:\n";
L.exchange(L);
return 0;
}
下面是对上述程序的运行,图片如下:
上述内容就是所有的关于类链表的一些实际操作。
2.使用类来书写一个类数组存储一些名言名句(英文)可以进行一些比较操作。其中需要包含一些友元函数和重载运算符的函数。
该实例操作考查了自己对友元函数、重载函数的相关应用还有静态数据成员和静态数据函数的理解,静态数据成员不与对象有关,所有对象都只对应同一个静态成员。静态函数可以对静态成员进行一些操作。静态成员如果为公有类型则可以在类外使用限定符进行引用
下面是该类的结构:
class String{
private:
char * str;
int len;
static int num_strings;
static const int CINLIM = 80; //限制的长度
public:
String(); //默认构造函数
String(const char *s); //构造函数
String(const String &); //复制构造函数
~String(); //析构函数
int length()const {return len;}; //计算长度的函数
String & operator =(const String &); //重载赋值运算符等于对象的
String & operator =(const char *s); //重载赋值运算符等于一个字符指针所指的字符串
const char & operator [](int i)const; //重载取值运算符,取出对象中某个位置的内容
char & operator [](int i);
friend bool operator<(const String &st,const String &st2); //重载对象大于对象的运算符
friend bool operator>(const String &st1,const String &st2);
friend bool operator ==(const String &st,const String &st2); //重载等于运算符
friend ostream & operator<<(ostream &os,const String &st);
friend istream & operator>>(istream &is,String &st);
static int HowMany(); //计算有多少个内容
};
整体性的代码如下:
其中包含一些相同函数名但调用的参数不同所以类对象可以根据参数的不同来调用不同的函数,因为这里在类中的成员为char指针类型所以不可以输入汉字如果大家想使用输入汉字则可以将其改为string类型,将相关的内容都更改为string类型即可。希望大家借走这个代码的时候可以在评论区留个言或点个赞,大学生写代码十分不容易!
#include <iostream>
#include <ctime>
#include <cstring>
#include <cstdlib>
using namespace std;
const int ArSize = 10;
const int MaxLen = 80;
class String{
private:
char * str;
int len;
static int num_strings;
static const int CINLIM = 80; //限制的长度
public:
String();
String(const char *s);
String(const String &);
~String();
int length()const {return len;};
String & operator =(const String &);
String & operator =(const char *s);
const char & operator [](int i)const;
char & operator [](int i);
friend bool operator<(const String &st,const String &st2);
friend bool operator>(const String &st1,const String &st2);
friend bool operator ==(const String &st,const String &st2);
friend ostream & operator<<(ostream &os,const String &st);
friend istream & operator>>(istream &is,String &st);
static int HowMany();
};
int String::num_strings=0;
int String::HowMany()
{
return num_strings;
}
String::String(const char *s)
{
len = strlen(s);
str = new char [len+1];
strcpy(str,s);
num_strings++;
}
String::String()
{
len = 4;
str = new char [1];
str = '\0';
num_strings++;
}
String::String(const String &st)
{
num_strings++;
len = st.len;
str = new char [len+1];
strcpy(str,st.str);
}
String::~String()
{
--num_strings;
delete [] str;
}
String & String::operator =(const String &st)
{
if(this == &st)
return *this;
delete [] str;
len = st.len;
str = new char [len+1];
strcpy(str,st.str);
return *this;
}
String & String::operator =(const char *s)
{
delete [] str;
len = strlen(s);
str = new char [len+1];
strcpy(str,s);
return *this;
}
char & String::operator [](int i)
{
return str[i];
}
const char & String::operator [](int i) const
{
return str[i];
}
bool operator>(const String &st1,const String &st2)
{
return (strcmp(st1.str,st2.str)<0);
}
bool operator<(const String &st1,const String &st2)
{
return (strcmp(st1.str,st2.str)>0);
}
bool operator==(const String &st1,const String &st2)
{
return (strcmp(st1.str,st2.str) == 0);
}
ostream & operator<<(ostream &os,const String &st)
{
os << st.str;
return os;
}
istream & operator>>(istream &is,String &st)
{
char temp[String::CINLIM];
is.get(temp,String::CINLIM);
if(is)
st = temp;
while(is&&is.get() !='\n')
continue;
return is;
}
int main()
{
String name;
cout<<"你好,你是谁?\n";
cin>>name;
cout<<name<<"请输入"<<ArSize<<"个短句不允许空行\n";
String sayings[ArSize];
char temp[MaxLen];
int i;
for(i=0;i<ArSize;i++)
{
cout<<i+1<<":";
cin.get(temp,MaxLen);
while(cin&&cin.get()!='\n')
continue;
if(!cin||temp[0]=='\0')
break;
else
sayings[i] = temp;
}
int total=i;
if(total>0)
{
cout<<"您所输入的俗话为:\n";
for(i=0;i<total;i++)
cout<<sayings[i][0]<<":"<<sayings[i]<<endl;
int shorts = 0;
int first =0;
for(i=1;i<total;i++)
{
if(sayings[i].length() < sayings[shorts].length())
shorts = i;
if(sayings[i] < sayings[first])
first=i;
}
cout<<"最短的俗话为:"<<sayings[shorts]<<endl;
cout<<"第一句话为:"<<sayings[first]<<endl;
cout<<"这个程序一共使用了"<<String::HowMany()<<"个对象\n";
cout<<"这个程序到这里就运行结束了!\n";
}
else
cout<<"没有输入数据,程序结束!";
return 0;
}
程序的运行结构如下图所示:
本人想说不要觉得自己不好,自己都没有自信别还怎么尊重你,为自己而活该解释的解释。不该解释的不必多说! 多看看自己能做什么,过自己的生活就好。