线性表的链式存储结构

1. 友元函数定义

        友元函数是定义在类外部的普通函数,不属于任何类,但可以直接访问类的私有成员,需要在类的内部使用friend关键字进行声明,类就会把友元函数当作类里面的成员。

#include<iostream>
using namespace std;
 
class Date
{
    //友元函数
    friend ostream& operator<<(ostream& out, const Date& d);
    friend istream& operator>>(istream& in, Date& d);
 
public:
	//构造函数
	Date(int year = 2022, int month = 4, int day = 8)
	{
		_year = year;
		_month = month;
		_day = day;
	}
 
private:
	int _year;
	int _month;
	int _day;
};
 
ostream& operator<<(ostream& out,const Date& d)
{
	out << d._year << "-" << d._month << "-" << d._day << endl;
	
	return _cout;
}
 
istream& operator>>(istream& in, Date& d)
{
	in >> d._year;
	in >> d._month;
	in >> d._day;
 
	return in;
}
 
int main()
{
	Date d1;
	cin >> d1;
	cout << d1 <<endl;
 
	return 0;
}

 1.1 友元函数的特性

(1)友元函数可访问类的私有和保护成员,但不是类的成员函数

(2)友元函数不能用const修饰(const修饰this指针指向的内容,友元函数作为全局函数没有this指针)

(3)友元函数可以在类定义的任何地方声明,不受类访问限定符限制

(4)一个函数可以是多个类的友元函数

(5)友元函数的调用与普通函数的调用和原理相同

2. 友元类

2.1 友元类的定义

        友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。如下Date类是Time类的友元类,Date类要访问Time类,就要把Date类定义成Time类的友元:

class Date; // 前置声明
class Time
{
	friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变量
public:
	Time(int hour = 0, int minute = 0, int second = 0)
		: _hour(hour)
		, _minute(minute)
		, _second(second)
	{}
 
private:
	int _hour;
	int _minute;
	int _second;
};
 
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
	void SetTimeOfDate(int hour, int minute, int second)
	{
		// 直接访问时间类私有的成员变量
		_t._hour = hour;
		_t._minute = minute;
		_t._second = second;
	}
 
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};
 
int main()
{
	return 0;
}

2.2 友元类的特性

(1)友元关系是单向的,不具有交换性。

        在Time类中,声明Date 类是其友元类,可以在Date类中直接访问Time类的私有成员。但不能在Time中访问Date类中的私有成员。

(2)友元关系不能传递

        A是B的友元,B是C的友元,但A不是C的友元。

3. 内部类

        一个类定义在另一个类的内部,这个内部类就叫做内部类。

内部类和外部类关系: 

(1)内部类不属于外部类,更不能通过外部类的对象调用内部类。外部类对内部类没有任何优越的访问权限。

(2)内部类是外部类的友元类,内部类可以通过外部类的对象参数来访问外部类的所有成员,但外部类不是内部类的友元。

3.1 内部类的特性

(1)内部类可以定义在外部类的public、protected、private都是可以的。

(2)注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名。

(3)sizeof(外部类)=外部类,和内部类没有任何关系

A无论是类还是全局函数,只要A被定义为B的友元,A就可以访问B的非公有成员。

4. 线性表的链式存储

4.1链表的定义

        链式存储和顺序存储的不同在于顺序存储用的是连续的地址,但是链式存储是用一组任意的存储单元存储数据的,地址可以是连续的也可以是不连续的。
        为了能表示(存储)元素之间的逻辑关系(线性),在存放每个元素的同时,也存放相关元素的信息(相关元素的存储地址),即用指针来表示元素之间的逻辑关系。

4.2 链表的实现

        我们用两个类来实现对链表的定义以及操作,一个是链表节点类LinkNode,用来定义一些指针节点以及初始化和分配内存;另一个是链表类,用来定义一些对于链表的操作。(链表类是链表节点类的友元)

#include <iostream>
#include <stdio.h>

using namespace std;

typedef int T;

class LinkList;
class LinkNode
{
    friend class LinkList;
private:
    LinkNode *link;
    T data;
public:
    LinkNode(LinkNode *ptr=NULL)
    {
        link=ptr;
    }
    LinkNode(const T &item,LinkNode *ptr=NULL)
    {
        data=item;
        link=ptr;
    }
    ~LinkNode() {};
};

class LinkList
{
private:
    LinkNode *first;
public:
    LinkList();//构造函数
    ~LinkList();
    int Length();//返回链表的长度
    bool Insert(int i,T x);//向链表中插入元素
    LinkNode *Locate(int i);//返回链表i出的节点值
    void Input(T endTag);//按条件输入(顺序)
    void Input2(T endTag);//按条件输入(逆序)
    void PrintList();//打印链表
    bool Delete(T &x);//删除值为x的节点
    void Search(T &x);//按值查找
    bool Find(T x);//查询链表中是否存在x
    void Cross(LinkList &A,LinkList &B,LinkList &C);//链表的交操作
    void Union(LinkList &A,LinkList &B);//链表的并操作
    void Sort();//对链表进行排序
};

LinkList::LinkList()
{
    first = new LinkNode;
    first->data = 0;
    first->link = NULL;
}


LinkNode *LinkList::Locate(int i)
{
    LinkNode *p=first;
    int j=0;
    if(i<0)
    {
        return NULL;
    }
    while(p!=NULL&&j<i)
    {
        p=p->link;
        j++;
    }
    return p;
}

LinkList::~LinkList()
{
    delete first;
}

bool LinkList::Insert(int i,T x)
{
    LinkNode *p=Locate(i-1);
    if(p==NULL)
    {
        return false;
    }
    LinkNode *newNode=new LinkNode(x);
    newNode->link=p->link;
    p->link=newNode;
}

void LinkList::Input(T endTag)
{
    LinkNode *newNode,*r;
    T val;
    cin>>val;
    r=first;
    while(val!=endTag)
    {
        newNode=new LinkNode(val);
        r->link=newNode;
        r=newNode;
        cin>>val;
    }
    r->link=NULL;
}

void LinkList::Input2(T endTag)
{
    LinkNode *newNode,*r;
    T val;
    cin>>val;
    r=first;
    while(val!=endTag)
    {
        newNode=new LinkNode(val);
        newNode->link=r->link;
        r->link=newNode;
        cin>>val;
    }
}

void LinkList::PrintList()
{
    LinkNode *p=first->link;
    while(p!=NULL)
    {
        cout<<p->data<<" ";
        p=p->link;
    }
    cout<<endl;
}

bool LinkList::Delete(T &x)
{
    LinkNode * p, *q = NULL;
    p = first->link;
    if (p == NULL)
    {
        return false;
    }
    while (p->data!=x&&p->link!=NULL)
    {
        q = p;
        p = p->link;
    }
    if (p->data == x)
    {
        q->link = p->link;
        delete p;
    }

}

int LinkList::Length()
{
    int i=0;
    LinkNode *p=first->link;
    while(p!=NULL)
    {
        i++;
        p=p->link;
    }
    return i;
}

void LinkList::Search(T &x)
{
    LinkNode *p=first->link;
    int count=1,flag=0;
    while(p!=NULL)
    {
        if(p->data==x)
        {
            flag=1;
            break;
        }
        count++;
        p=p->link;
    }
    if(flag)
    {
        cout<<x<<" is located at index of "<<count<<endl;
    }
    else
    {
        cout<<x<<" is not found"<<endl;
    }
}

bool LinkList::Find(T x)
{
    LinkNode *p=first;
    while(p!=NULL)
    {
        if(p->data==x)
        {
            return true;
        }
        p=p->link;
    }
    return false;
}

void LinkList::Cross(LinkList &A,LinkList &B,LinkList &C)
{
    T t;
    for(int i=1; i<=B.Length(); i++)
    {
        t=B.Locate(i)->data;
        if(A.Find(t))
        {
            C.Insert(C.Length()+1,t);
        }
    }
}

void LinkList::Union(LinkList &A,LinkList &B)
{
    T t;
    for(int i=1; i<=B.Length(); i++)
    {
        t=B.Locate(i)->data;
        if(!A.Find(t))
        {
            A.Insert(A.Length()+1,t);
        }
    }
}

void LinkList::Sort()
{
    LinkNode *p=first,*q=NULL;
    while(p!=q)
    {
        while(p->link!=q)
        {
            if(p->data>p->link->data)
            {
                int t=p->data;
                p->data=p->link->data;
                p->link->data=t;
            }
            p=p->link;
        }
        q=p;
        p=first;
    }
}

int main()
{
    int n,m,t=0,a[10000],x1,y1,x2,x3,x4;
    cin>>n;
    LinkList p,q,r;
    p.Input(n);
    cout<<"A is created as: ";
    p.PrintList();
    cin>>x1>>y1;
    p.Insert(x1,y1);
    cout<<"After inserted A is ";
    p.PrintList();
    cin>>x2;
    p.Delete(x2);
    cout<<"After deleted A is ";
    p.PrintList();
    cin>>x3;
    p.Search(x3);
    cin>>x4;
    p.Search(x4);
    cin>>m;
    q.Input(m);
    cout<<"B is created as: ";
    q.PrintList();
    p.Cross(p,q,r);
    cout<<"A cross B is ";
    r.PrintList();
    p.Union(p,q);
    cout<<"A union B is ";
    p.PrintList();
    p.Sort();
    cout<<"A union B in sequence is ";
    p.PrintList();
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林家小院

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值