线性表

一.模板:对类或函数的数据类型的抽象,是参数的多态性工具
1.函数模板
定义:
 template<模板形参表>​
​        返回值类型  函数名(参数表)
        {
                函数体
        }
模板形参表=引导词+模板参数(类型名)
Ex:
template<template/class T>
T abs(T a)
{
return a<0?-a:a>;
}
使用时需实例化
int main
{
int x=2;
double y=-5:
abs(x);
ans(y);
}
2.类模板
其中的成员函数自动成为函数模板
template<模板形参表>
class 类模板名

成员的声明
};
类外函数的定义
template<模板形参表>
返回值类型 类模板名<形参名表>::成员函数名(参数表)

成员函数体

模板:对类或函数的数据类型的抽象,是参数的多态性工具
1.函数模板
定义:
 template<模板形参表>​
​返回值类型  函数名(参数表)
 {
    函数体
 }
模板形参表=引导词+模板参数(类型名)
Ex:
template<template/class T>
T abs(T a)
{
return a<0?-a:a>;
}
使用时需实例化
int main
{
int x=2;
double y=-5:
abs(x);
ans(y);
}
2.类模板
其中的成员函数自动成为函数模板
template<模板形参表>
class 类模板名

成员的声明
};
类外函数的定义
template<模板形参表>
返回值类型 类模板名<形参名表>::成员函数名(参数表)

成员函数体

二·顺序表的实现

const int Maxsize=100;

template

class SeqList{

private:

T data[MaxSize]; // 存放数据元素的数组

int length; // 线性表的长度

public:

SeqList ( ) ;// 无参构造函数

SeqList ( T a[ ], int n ) ; // 有参构造函数

~SeqList( ) { } // 析构函数为空

int Length ( ) {return length;} // 求线性表的长度

有参构造函数的实现

template

SeqList:: SeqList(T a[], int n)

{

if
(n>MaxSize) throw “参数非法”;

for (int i=0;
i<n; i++)

data[i]=a[i];

length=n;

}

插入算法的实现

template

void SeqList::Insert(int i, T x){

int j;

if
(length>=MaxSize) throw “上溢”;

if (i<1
|| i>length+1) throw “位置”;

for
(j=length; j>=i; j–)

data[j]=data[j-1];

data[i-1]=x;

length++;

}

按值查找

template

int SeqList::Locate(T x){

for (int i=0; i<length; i++)

if (data[i]==x)

return i+1 ;  //下标为i的元素等于x,返回其序号i+1

return 0; 
//退出循环,说明查找失败

}

顺序表的特点

(1) 可方便地随机存取表中的任一元素。

(2) 插入或删除运算不方便,

除表尾的位置外,在表的其它位置上进行插入或删除操作都必须移动大量的结点,其效率较低;

(3) 由于顺序表要求占用连续的存储空间,存储分配只能预先进行静态分配,因此当表长变化较大时,难以确定合适的存储规模。

三.单链表

1·链表结点数据类型的定义(结点类)

在C++中,可以用结构类型来描述单链表的结点 ,由于结点的元素类型不确定,所以采用C++的模板机制。

template

struct Node

{

T data;

Node
*next;      //此处也可以省略

}

2·带头节点的单链表

头结点:如果链表有头节点,则链式结构中的第一个节点称为头结点:其数据域可以存储一些附加信息,如链表长度;其指针域指向链表中的第一个节点。

单链表的实现(重点)

template

class LinkList {

public:

LinkList ( ) {first=new Node; first -> next=
NULL ;}

LinkList ( T a[
], int n ) ;

~LinkList ( ) ;

int Length ( ) ;

T Get ( int i ) ;

int Locate ( T x ) ;

void Insert ( int i, T x ) ;

T Delete ( int i ) ;

void PrintList ( ) ;

private:

Node  *first; // 单链表的头指针  , 可以省略

};

单链表的构造-头插法(先修改远端)

template

LinkList:: LinkList(T a[ ], int n) {

first=new
Node;   //生成头结点

first->next=NULL;

Node
*s;

for (int i=0;
i<n; i++){

s=new
Node;

s->data=a[i];  //为每个数组元素建立一个结点

s->next=first->next;

first->next=s;

}

}

单链表的构造-尾插法

template

LinkList:: LinkList(T a[ ], int n) {

Node *r,*s;      //尾指针

first=new
Node;   //生成头结点

r=first;

for (int
i=0; i<n; i++) {

s=new
Node;

s->data=a[i];  //为每个数组元素建立一个结点

r->next=s; r=s;      //插入到终端结点之后

}

r->next=NULL;    //单链表建立完毕,将终端结点的指针域置空

}

单链表的遍历

template

LinkList:: PrintList()

{

Node *p;

p=first->next;

while§

{

cout<data;

p=p->next;

}

}

单链表中按位置查找

template

T LinkList::Get(int i) {

Node *p; int j;

p=first->next;  j=1; 
//或p=first;  j=0;

while (p && j<i) {

p=p->next;       //工作指针p后移

j++;

}

if (!p) throw “位置”;

else return p->data;

}

单链表的插入操作(按位置进行插入)

1 工作指针p初始化,计数器初始化

2 查找第i-1个节点,并使工作指针p指向该节点

3 若查找不成功(P==NULL),说明位置错误,抛出位置异常,否则

3.1 生成一个元素值为x的新节点s

3.2  将s插入到p之后

template

void LinkList::Insert(int i, T x){

Node
*p; int j;

p=first ;
j=0;    //工作指针p初始化

while (p
&& j<i-1)   {

p=p->next;   //工作指针p后移

j++;

}

if (!p) throw
“位置”;

else {

Node *s;

s=new
Node;

s->data=x; 
//向内存申请一个结点s,其数据域为x

s->next=p->next;       //将结点s插入到结点p之后

p->next=s;

}

}

单链表中节点的删除(删除编号是i的结点)

template

T LinkList::Delete(int i){

Node
*p; int j;

p=first ;
j=0;  //工作指针p初始化

while (p
&& j<i-1) {  //查找第i-1个结点

p=p->next;

j++;

}

if (!p ||
!p->next) throw “位置”;  //结点p不存在或结点p的后继结点不存在

else {

Node *q; T x;

q=p->next; x=q->data;  //暂存被删结点

p->next=q->next;  //摘链

delete
q;

return x;

}

}

析构函数

template

LinkList:: ~LinkList()

{

Node
*q;

while (first)

{

q=first->next;

delete
first;

first=q;

}

}

三·循环链表

将单链表或者双链表的头尾结点链接起来,就是一个循环链表。

首尾相接的链表。

可以从任一节点出发,访问链表中的所有节点。

判断循环链表中尾结点的特点:

q->next==first

循环链表的定义:

template

class CycleLinkList{

public:

CycleLinkList( );

CycleLinkList(T a[ ], int n);

CycleLinkList(T a[ ], int n,int i);

~CycleLinkList();

int Length();

T Get(int
i);

void
Insert(int i, T x);

T Delete(int
i);

void
PrintList( );

private:

Node
*first;

};

空表的构造

template

CycleLinkList:: CycleLinkList( )

{

first=new Node; first->next=first;

}

尾插法构造循环链表

template

CycleLinkList:: CycleLinkList(T a[ ], int n)
{

first=new
Node;   //生成头结点

Node
*r,*s;

r=first;          //尾指针初始化

for (int
i=0; i<n; i++) {

s=new Node;

s->data=a[i];

r->next=s;

r=s;

}

r->next=first;    //单链表建立完毕,将终端结点的指针域指向头结点

}

头插法构造循环链表

template

CycleLinkList:: CycleLinkList(T a[ ], int
n,int k)

{

first=new
Node;   //生成头结点

first->next=first;

Node
*s;

for (int i=1;
i<n; i++)

{

s=new
Node;

s->data=a[i];  //为每个数组元素建立一个结点

s->next=first->next;

first->next=s;

}

}

将非循环的单链表改造成循环的单链表

p=first;

while(p->next)

{

p=p->next;

}

p->next=first

双链表

增加一个指向前驱的指针

template

struct  DNode{

T  data;

DNode
*llink;

DNode *rlink;

};

双链表的结构特点

由于在双向链表中既有前向链又有后向链,寻找任一个结点的直接前驱结点与直接后继结点变得非常方便。设指针p指向双链表中某一结点,则有下式成立:

p->llink->rlink = p = p->rlink->llink ;

双向链表的实现

template

class DoubleLink {

private:

Node
*head;

public:

DoubleLink() ;

~DoubleLink();

void Append(T
data);

void
Display();

void
Insert(int locate , T data);

T    Get(int locate);

T   Delete(int locate);

};

双向链表的构造-空表的构造

template

DoubleLink ::DoubleLink(){

head=new
Node;

head->rlink=NULL;

head->llink=NULL;

}

追加(头插):Append(T data)

template

void DoubleLink::Append(T data){

Node *s;

s=new Node;

s->data=data;

s->rlink=head->rlink;

head->rlink=s;

s->llink=head;

if
(s->rlink)

s->rlink->llink=s;

return;

}

遍历

template

void DoubleLink::Display(){

Node
*p;

p=head->rlink;

while§ {

cout<data<<"   ";

p=p->rlink;

}

cout<<endl;

return;

}

析构

template

DoubleLink::~DoubleLink(){

Node  *p,*q;

p=head;

while§

{

q=p->rlink;

delete
p;

p=q;

}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值