114
线线线 线线线 线线线 线线线 线线线线 线线线线 线线线 线线线

线性表 顺序表 稀疏矩阵 字符串

  • Upload
    von

  • View
    144

  • Download
    0

Embed Size (px)

DESCRIPTION

第二章 数组. 线性表 顺序表 稀疏矩阵 字符串. 一、线性表. 线性表 相同数据类型的元素的有限序列 叫线性表。 ( a 1 , a 2 , … ,a n-1 , a n ) a 1 为 首元 , a n 为 末元 , n 叫 线性表的 长度 a i 的 后继 是 a i+1 , i=1, …,n-1. a n 没有后继 。 a i 的 前驱 是 a i-1 , i=2, …,n. a 1 没有前驱 。 a i 可以是基本数据类型也可以是 struct 类型。 没有数据的线性表叫 空表 。空表的长度 n=0 。. - PowerPoint PPT Presentation

Citation preview

Page 1: 线性表 顺序表  稀疏矩阵 字符串

线性表线性表顺序表 顺序表 稀疏矩阵稀疏矩阵字符串字符串

Page 2: 线性表 顺序表  稀疏矩阵 字符串

一、线性表线性表 相同数据类型的元素的有限序列 叫线性表。 ( a1, a2, … ,an-1, an )a1 为首元, an 为末元, n 叫线性表的长度 ai 的后继是 ai+1, i=1, …,n-1. an 没有后继。ai 的前驱是 ai-1, i=2, …,n. a1 没有前驱。ai 可以是基本数据类型也可以是 struct 类型。没有数据的线性表叫空表。空表的长度 n=0 。a1 a2 a3 a4 a5 a6

Page 3: 线性表 顺序表  稀疏矩阵 字符串

线性表是最简单的也是最基本的数据结构。

线性表可以用来构造字符串,集合,栈,队列,用来排序。

线性表可以顺序表示用一组地址连续的存储单元一次存储数据元素。

线性表也可以用线性链表表示。

Page 4: 线性表 顺序表  稀疏矩阵 字符串

二、顺序表——线性表的顺序表示

可以用通用数组定义通用线性表。

通用数组是可变长度的数组,也叫安全数组。

Page 5: 线性表 顺序表  稀疏矩阵 字符串

类模版 通用数据类型//array.h 例 . 通用数组 抽象数组类型 template <class T>

class Array

{ T *alist; // 指针数据 表示一个数组 int size; // 表示数组长度 public:

Array(int s=50) // 构造函数 Array(const Array<T>&X); // 拷贝构造函数 ~Array( ){delete[ ] element;} // 析构函数 Array<T>&operator=(const Array<T>&X);// 赋值函数重载 T& operator[ ](int i) ; // 一元运算 [ ] 重载 下标函数 operator T*( )const; // 强制类型转换 , 将当前 // 对象变成指向它的首地址的指针, int ArraySize( )const; // 取数组长 void Resize(int sz); // 数组长重定义 friend ostream& operator<<(ostream&, const Array<T>&);

// 输出操作重载 } ;

Page 6: 线性表 顺序表  稀疏矩阵 字符串

#include <array.h>

template<class T>class SeqList{ Array<T>listitem; //list storage array int size; public: SeqList(void); // constructor 构造函数 // list access methods 线性表的访问操作 int ListSize(void) const; // 取线性表的长 int ListEmpty(void)const; // 问表是否空表 int Find (T& item) const; // 查找一个元素 T GetData(int pos) const; // 取线性表中元素

Page 7: 线性表 顺序表  稀疏矩阵 字符串

// list modification methods 线性表的修改操作

void Insert(const T& item);// 表尾插入元素 void Insert(const T& item , int i); // 在第 i 个位插入一个新元素 void Delete(const T& item);// 删除一个元素 T DeleteFront(void); // 删除首元 void ClearList(void); // 清空};

Page 8: 线性表 顺序表  稀疏矩阵 字符串

// constructor. set size to 0

template<class T>SeqList<T>::SeqList(void): listite

m(size),size(0) { }

Page 9: 线性表 顺序表  稀疏矩阵 字符串

// return number of elements in list

template<class T>int SeqList<T>::ListSize(void) const{ return size;}

Page 10: 线性表 顺序表  稀疏矩阵 字符串

// tests for an empty list

template<class T>int SeqList<T>::ListEmpty(void) const{ return size == 0;}

Page 11: 线性表 顺序表  稀疏矩阵 字符串

// clears list by setting size to 0

template<class T>void SeqList<T>::ClearList(void){ size = 0;}

Page 12: 线性表 顺序表  稀疏矩阵 字符串

// Take item as key and search the list. //return True if item is in the list

and // false otherwise. If found, assign the list // element to the reference parameter item.

template<class T>int SeqList<T>::Find(T& item) const{ int i = 0; if (ListEmpty())return 0; // return False when list empty

Page 13: 线性表 顺序表  稀疏矩阵 字符串

while(i<size &&!(item==listitem[i])) i++; if (i < size) { item = listitem[i]; // assign list element to item return 1; // return True } else

return 0; // return false}

Page 14: 线性表 顺序表  稀疏矩阵 字符串

// insert item at the rear of the list.

template<class T>void SeqList<T>::Insert(const T& item){ // 如果超长,扩大内存

if (size+1 > listitem.ListSize( )) listitem.Resize(size+1); // index of rear is current value of //size. insert at rear listitem[size] = item; size++; // increment list size }

Page 15: 线性表 顺序表  稀疏矩阵 字符串

template<class T> // 在第 i 位插入

void SeqList<T>::Insert(const T& item, int i){ if (i<0)

{cout<<“’i’can not be negative!"; return;}

if(i>=size){Insert(item);return;} if (size+1 > listitem.ListSize( )) listitem.Resize(size+1); int k=size-1;

Page 16: 线性表 顺序表  稀疏矩阵 字符串

//shift the tail of the list //to the right one position

while (k >= i) { listitem[k+1] = listitem[k]; k--; } listitem[i] = item; size++; // increament list size}

Page 17: 线性表 顺序表  稀疏矩阵 字符串

//search for item in the list //and delete it if found

template<class T>void SeqList<T>::Delete(const T& item){ int i = 0; // search for item while (i < size && !(item == listitem[i])) i++; if (i < size) // successful if i < size {

Page 18: 线性表 顺序表  稀疏矩阵 字符串

// shift the tail of the list //to the left one position

while (i < size-1) { listitem[i] = listitem[i+1]; i++; } size--; // decreament size }}

Page 19: 线性表 顺序表  稀疏矩阵 字符串

//delete element at front of list and return // its value. terminate the

program with // an error message if the list is empty. template<class T> T SeqList<T>::DeleteFront(void) { T frontItem; // list is empty if size == 0 if (size == 0) { cerr << "Attempt to delete the front / of an empty list!" << endl; exit(1); }

Page 20: 线性表 顺序表  稀疏矩阵 字符串

frontItem = listitem[0]; // get value from position 0. Delete(frontItem); // delete the first item and shift terms

return frontItem; // return the original value

}

Page 21: 线性表 顺序表  稀疏矩阵 字符串

// return value at position pos in list. // if pos is not valid list position,// teminate program with an error message.template<class T>T SeqList<T>::GetData(int pos) const{ // terminate program if pos out of range if (pos < 0 || pos >= size) {cerr << "pos is out of range!" << endl; exit(1); } return listitem[pos];}

Page 22: 线性表 顺序表  稀疏矩阵 字符串

测试 #include “ iostream.h” #include “aseqlist.h”void main(void){ SeqList<int> a,b; int x; for(int i=0;i<20;i++) {a.Insert(i);

cout<<"input "<<i’s<<“ integer:"; cin>>x; b.Insert(x+1);} for(i=0;i<20;i++) cout<<a.GetData(i)<<' '; cout<<endl;

Page 23: 线性表 顺序表  稀疏矩阵 字符串

for(i=0;i<20;i++) cout<<b.GetData(i)<<' '; cout<<endl; a.Insert(99,0); a.Insert(98,10); a.Insert(97,20); a.Insert(96,30); int k=a.ListSize( ); for(i=0;i<k;i++) cout<<a.GetData(i)<<' '; cout<<endl;}

Page 24: 线性表 顺序表  稀疏矩阵 字符串

顺序表应用的例:

1. 用顺序表做插入 , 选择排序 .

2. 合并两个已排序的线性表 3. 用顺序表做集合 : 只插入不重复的元素 4. 求两个集合的交合并 5. 表示一个多项式 6. 求多项式的和差积商 , 微分 , 积分 7. 存储一个矩阵 , 求矩阵的和 , 积 , 逆

Page 25: 线性表 顺序表  稀疏矩阵 字符串

顺序线性表复杂度分析 1. 从已建立的顺序表中“取表长” ,“取第

i 个元素”的复杂性是 O(1),2. 在表长 n 的顺序表第 i 位前插入一个元素,

要把表尾 n-i+1 个元素后移一格。 假设每一位都插入一个数,从第 1 位到末

尾第 n+1 位,总移动次数是: Σi=1

i=n+1(n-i+1)=1+2+…+n=n*(n+1)/2

平均复杂度为 O(n/2).3. 删除第 i 位元素,要把表尾 n-i 个元素前移

一格。假设每一位都删除一个数,从第 1位到末尾第 n 位,总移动次数是:

Σi=1i=n+1(n-i)=1+2+…+(n-1)=n*(n-1)/2

平均复杂度为 O((n-1)/2).

Page 26: 线性表 顺序表  稀疏矩阵 字符串

一个阶数很高的矩阵中如果有许多相等的元素,或零元素,成为特殊矩阵。

对特殊矩阵可以进行压缩存储

三、稀疏矩阵

Page 27: 线性表 顺序表  稀疏矩阵 字符串

特殊矩阵

对称矩阵 上(下)三角矩阵 对角矩阵 稀疏矩阵

Page 28: 线性表 顺序表  稀疏矩阵 字符串

对称矩阵

矩阵 A=(aij)n,n

aij= aji , 0≤i,j≤n

每一对元素分配一个存储空间,可以 将 n2 个元素存储到 n(n+1)/2 个空间中

Page 29: 线性表 顺序表  稀疏矩阵 字符串

下三角矩阵 a11

a21a22

a31a32 a33

……

an1an2 an3 ……ann

1+2+3+ ……+n=n(n+1)/2T s[n(n+1)/2];

0 1 2 3 4 5 6 k

s a11 a21 a22 a31 a32 a33

k=i(i-1)/2+j-1; i≥j; k=j(j-1)/2+i-1; i<j.

s[12]=aij=aji; i=4, j=3

s[0]=a11; s[1]=a21; s[k]=ai

j

Page 30: 线性表 顺序表  稀疏矩阵 字符串

对角矩阵   a11 a12

   a21 a22 a23

     · · ·          · · ·

· · an-1n

      ann-1 ann

a11 a12 a21 a22 a23 s[k]

s[k]=aij; k=3(i-1)+j; j=k%3; i=(k-j)/3

Page 31: 线性表 顺序表  稀疏矩阵 字符串

稀疏矩阵 Sparse Matrix

m*n 阶矩阵 A=(aij)mn 中有 t 个非零元素 , 如果 δ=t/(m*n)≤5%,

称 A 为稀疏矩阵 0 12 9 0 0 0 0

0 0 0 0 0 0 0

-3 0 0 0 0 14 0

0 0 24 0 0 0 0

0 18 0 0 0 0 0

15 0 0 -7 0 0 0

Page 32: 线性表 顺序表  稀疏矩阵 字符串

//smatrix.dat

6 7 8 1 2 12 1 3 9 3 1 –3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7

Page 33: 线性表 顺序表  稀疏矩阵 字符串

稀疏矩阵的存储

row col elem 1 2 12 1 3 9 3 1 –3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7

Page 34: 线性表 顺序表  稀疏矩阵 字符串

template<class T>

class Triple

{ public:

int row, col;

T elem;

SetVal(int r,int c,T d)

{elem=d;row=r;col=c;}

};

稀疏矩阵元素的类 TRiple

Page 35: 线性表 顺序表  稀疏矩阵 字符串

稀疏矩阵类的定义#define MAXSIZE 500template<class T>class SparseMatrix{ Triple<T> data[MAXSIZE+1]; int mu, nu, tu; // 行数、列数、元素个数 public: SparseMatrix( ){mu=nu=tu=0;} SparseMatrix(char*filename); SparseMatrix<T> Transpose( ); SparseMatrix<T> Add(SparseMatrix<T> b); SparseMatrix<T> Muliply(SparseMatrix<T> b); void print( )const; };

Page 36: 线性表 顺序表  稀疏矩阵 字符串

template<class T>

SparseMatrix<T>::SparseMatrix(char *filename)

{ ifstream fin; int i,r,c; T d;

fin.open(filename, ios::in | ios::nocreate);

if (!fin){ cerr << "The maze data file " << filename

<< " cannot be opened!" << endl; exit(1); }

fin >> mu>>nu>>tu;

for (i = 1; i <= tu; i++)

{ fin >> r >> c>>d; data[i].SetVal(r,c,d);}

fin.close( );

};

Page 37: 线性表 顺序表  稀疏矩阵 字符串

矩阵的转置 T=M’

for(col=1;col<=nu;col++)

for(row=1;row<=mu;row++)

T[col][row]=M[row][col]

时间复杂度 O(mu*nu)

Page 38: 线性表 顺序表  稀疏矩阵 字符串

M

row col elem

1 2 12

1 3 9

3 1 –3

3 6 14

4 3 24

5 2 18

6 1 15

6 4 -7

M’

row col elem

2 1 12

3 1 9

1 3 –3

6 3 14

3 4 24

2 5 18

1 6 15

4 6 -7

Page 39: 线性表 顺序表  稀疏矩阵 字符串

M

row col elem

1 2 12

1 3 9

3 1 –3

3 6 14

4 3 24

5 2 18

6 1 15

6 4 -7

M’

row col elem

1 3 -3

1 6 15

2 1 12

2 5 18

3 1 9

3 4 24

4 6 -7

6 3 14

Page 40: 线性表 顺序表  稀疏矩阵 字符串

稀疏矩阵的转置 T=M’ 算法 5.1

template <class T> SparseMatrix<T> SparseMatrix<T> :: Transpose( )

{SparseMatrix<T> temp; int i, j, k=1; temp.mu=nu; temp.nu=mu; temp.tu=tu; if(tu){for(i=1;i<=nu;++i) for(j=1;j<=tu;++j) if(data[j].col==i) {temp.data[k].row=data[j].col; temp.data[k].col=data[j].row; temp.data[k].elem=data[j].elem; k++;} return temp;}

Page 41: 线性表 顺序表  稀疏矩阵 字符串

稀疏矩阵的转置的时间复杂度

O(nu*tu)

若 tu~nu*mu

O(nu*tu)=O(mu*nu*nu)

不是一个好算法!应当改进!

Page 42: 线性表 顺序表  稀疏矩阵 字符串

快速转置 依次逐个对号入座

Mrow col elem 1 2 12 1 3 9 3 1 –3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7

M’row col elem

2 1 12

3 1 9

先求出 M 中每一列(即 M’ 中每一行)元素的个数 num[col] ,确定 M’ 每行起始位置 cpot[col] 。

Page 43: 线性表 顺序表  稀疏矩阵 字符串

快速转置Mrow col elem 1 2 12 1 3 9 3 1 –3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7

col 1 2

3 4 5 6 7

num[col]

cpot[col]

1

2

3

2

5

2 7 1

8 0

8 1

9

row col elem

cpot[1]

cpot[2]

cpot[3]

cpot[4]

cpot[6]

2

1 12

3

1 9

1

3 9

6

3 14

Page 44: 线性表 顺序表  稀疏矩阵 字符串

快速转置算法 5.2

template <class T> SparseMatrix<T> SparseMatrix<T> ::Transpose( )

{SparseMatrix<T> temp; int i, j, k ; int*num=new int[nu+1]; int* cpot=new int[nu+1];

cpot[1]=1; temp.mu=nu; temp.nu=mu;temp.tu=tu; if(tu){for(i=1;i<=nu;++i)num[i]=0; for(i=1;i<=tu;++i)++num[data[i].col]; for(i=1;i<nu;++i)cpot[i+1]=cpot[i]+num[i]; for(i=1;i<=tu;++i){j=data[i].col;k=cpot[j]; temp.data[k].row=j; temp.data[k].col=data[i].row; temp.data[k].elem=data[i].elem; ++cpot[j];} } return temp;}

时间复杂性 O(nu+tu)

Page 45: 线性表 顺序表  稀疏矩阵 字符串

稀疏矩阵的加法template <class T> SparseMatrix<T> SparseMatrix<T>:: Add(SparseMatrix<T> b ){SparseMatrix<T> temp; if(mu!=b.mu||nu!=b.nu) {cerr<<“error ”<<end;return temp;} temp.mu=mu; temp.nu=nu; int i=1, j=1, k=1; while(i<=tu||j<=b.tu) {if((data[i].row<b.data[j].row) || (data[i].row==b.data[j].row) && (data[i].col<b.data[j].col)) {temp.data[k]=data[i]; k++;i++;}

Page 46: 线性表 顺序表  稀疏矩阵 字符串

else if((data[i].row==b.data[j].row)&&

(data[i].col==b.data[j].col))

{temp.data[k].row=data[i]. row;

temp.data[k].col=data[i].col;

temp.data[k].elem=data[i]. elem+ b.data[j]. elem

k++;i++;j++;}

else

{ temp.data[k]=b.data[j];k++;j++;}

temp.tu=k-1;

return temp;

}

Page 47: 线性表 顺序表  稀疏矩阵 字符串

矩阵的乘法  Amp*Bpn

(aij)*(bij)=(Σ1≤k≤paik*bkj)

2 0 0 -1

0 1 0 3

0 0 1 0

1 0 1 0 0 -1 0 0 0 2 0 1 3 0 1 0

a11*b11 a11*b12 a11*b13 a11*b14

a12*b21 a12*b22 a12*b23 a12*b24

a13*b31 a13*b32 a13*b33 a13*b34

a14*b41 a14*b42 a14*b43 a14*b44

时间复杂度 mpn

Page 48: 线性表 顺序表  稀疏矩阵 字符串

稀疏矩阵的乘法A

row col elem

1 2 12

1 3 9

3 1 –3

3 6 14

4 3 24

5 2 18

6 1 15

6 4 -7

B

row col elem rpos[row]

1 1 8 rpos[1]= 1

2 3 4 rpos[2]= 2

3 2 1 rpos[3]=3

3 5 -1

4 1 2 rpos[4]=5

4 4 -3

5 1 5 rpos[5]=7

6 2 -2 rpos[6]=8

Page 49: 线性表 顺序表  稀疏矩阵 字符串

template <class T> SparseMatrix<T> SparseMatrix<T>:: Multiply(SparseMatrix<T> b ){SparseMatrix<T> temp; if(nu!=b.mu) {cer<<“error ”<<end;return temp;}

temp.mu=mu;temp.nu=b.nu; int *num=new int[b.mu+1]; int *rpos=new int[b.mu+1]; rpos[1]=1; T ctemp[b.nu+1]; for(int i=1;i<=b.mu;i++) num[i]=0; for(i=1;i<=b.tu;i++)++num[b.data[i].row]; for(i=1;i<=b.mu;i++)rpos[i+1]=rpos[i]+num[i];

Page 50: 线性表 顺序表  稀疏矩阵 字符串

int k=1,j, r,c,t=0;

while(k<=tu)

{ for( j=1;j<=b.nu;j++) ctemp[j]=0;

r=data[k].row;

while(k<=tu&&data[k]=r)

{c=data[k].col;

for(i=rpos[c];i<rpos[c+1];i++;)

{j=b.data[i].col; ctemp[j]=ctemp[j]+data[k].elem*b.data[i].elem;}

k++;}

Page 51: 线性表 顺序表  稀疏矩阵 字符串

for(j=1;j<=b.nu;j++)

if(ctemp[j]!=0)

{t++; temp.data[t].row=r;

temp.data[t].col=j;

temp.data[t].elem=ctemp[j];}

}

temp.tu=t;

return temp;

}

Page 52: 线性表 顺序表  稀疏矩阵 字符串

稀疏矩阵乘法的时间复杂度

O(tu.*b.nu)

Page 53: 线性表 顺序表  稀疏矩阵 字符串

稀疏矩阵的输出template <class T>void SparseMatrix<T> :: print( )const{int i, j,k=1; for(i=1;i<=mu;i++) {for(j=1;j<=nu;j++) if ((i=data[k].row)&&(j=data[k].col)) {cout<<setw(4)<<data[k].elem; k++;} else cout<<setw(4)<<0; cout<<endl; }}

Page 54: 线性表 顺序表  稀疏矩阵 字符串

串串 --- 由字符组成的线性表,也叫 字符串串是非数值计算算法处理的主要对象在模式匹配,程序编译,数据处理等领域有广泛的应用

Page 55: 线性表 顺序表  稀疏矩阵 字符串

串类型的定义 串类型的实现 串的模式匹配

Page 56: 线性表 顺序表  稀疏矩阵 字符串

C 语言中有关串的函数#include <string.h>

strlen(char *s);

strcpy(char *s, char *t);

strcmp(char*s, char *t);

strcat(char *s, char *t);

strchr(char*s, char c);

strrchr(char*s, char c);

没有插入,删除不好记,不好用

Page 57: 线性表 顺序表  稀疏矩阵 字符串

串类型的定义

1 。用数组定义串 #define MAXSTRLEN 255

typedef unsigned SString[MAXSTRLEN+1];

Sstring s1, s2;

// 用 s1[0], s2[0] 存储各自的长度

Page 58: 线性表 顺序表  稀疏矩阵 字符串

2 。堆分配存储表示

typedef struct{

char *ch;

int length;

}HString;

HString s;

s.length=15;

s.ch=new char[s.length];

Page 59: 线性表 顺序表  稀疏矩阵 字符串

3. 块链存储 #define CHUNKSIZE 80typedef struct Chunk{ char ch[CHUNKSIZE]; Chunk *next; } ;typedef struct{ Chunk *head,*tail; int curlen; }LString; // 定长字符串作元素的线性链表

Page 60: 线性表 顺序表  稀疏矩阵 字符串

堆分配存储串类的实现 //“strclass.h”

#define STRING_CLASS

#include <iostream.h>

#include <string.h>

#include <stdlib.h>

#ifndef NULL

const int NULL = 0;

#endif // NULL

const int outOfMemory = 0, indexError = 1;

#ifndef STRING_CLASS

Page 61: 线性表 顺序表  稀疏矩阵 字符串

class String

{ char *str;

int size;

void Error(int errorType, int badIndex = 0) const;

public:

String(char *s = “ ” );

String(const String& s);

~String(void);

Page 62: 线性表 顺序表  稀疏矩阵 字符串

String& operator= (const String& s);

String& operator= (char *s);

int operator== (const String& s) const;

int operator== (char *s) const;

friend int operator== (char *str, const String& s);

int operator!= (const String& s) const;

int operator!= (char *s) const;

friend int operator!= (char *str, const String& s);

Page 63: 线性表 顺序表  稀疏矩阵 字符串

int operator< (const String& s) const;

int operator< (char *s) const;

friend int operator< (char *str, const String& s);

int operator<= (const String& s) const;

int operator<= (char *s) const;

friend int operator<= (char *str, const String& s);

int operator> (const String& s) const;

int operator> (char *s) const;

friend int operator> (char *str, const String& s);

Page 64: 线性表 顺序表  稀疏矩阵 字符串

int operator>= (const String& s) const;

int operator>= (char *s) const;

friend int operator>= (char *str, const String& s);

String operator+ (const String& s) const;

String operator+ (char *s) const;

friend String operator+ (char *str,const String& s);

void operator+= (const String& s);

void operator+= (char *s);

Page 65: 线性表 顺序表  稀疏矩阵 字符串

// String functions

int Find(char c, int start) const;

int FindLast(char c) const;

String Substr(int index, int count) const;

void Insert(const String& s, int index);

void Insert(char *s, int index);

void Remove(int index, int count);

char& operator[] (int n);

operator char* (void) const;

Page 66: 线性表 顺序表  稀疏矩阵 字符串

// String I/O

friend ostream& operator<< (ostream& ostr,

const String& s);

friend istream& operator>> (istream& istr,

String& s);

int ReadString(istream& is=cin,

char delimiter='\n');

int Length(void) const;

int IsEmpty(void) const;

void Clear(void);

};

Page 67: 线性表 顺序表  稀疏矩阵 字符串

void String::Error(int errorType, int badIndex) const

{ if (errorType == outOfMemory) cerr << "Memory exhausted!" << endl; else cerr << "Index " << badIndex << " out of range" << endl; exit(1);}

Page 68: 线性表 顺序表  稀疏矩阵 字符串

// constructor. allocate memory and copy in a C++String

String::String(char *s){ size = strlen(s) + 1; str = new char [size]; // terminate program if memory is exhausted.

if (str == NULL) Error(outOfMemory); strcpy(str,s);}

Page 69: 线性表 顺序表  稀疏矩阵 字符串

// copy constructor

String::String(const String& s){ // current object as length of s

size = s.size; // allocate same amount of space as s uses. copy string

str = new char [size]; if (str == NULL) Error(outOfMemory); strcpy(str, s.str);}

Page 70: 线性表 顺序表  稀疏矩阵 字符串

// destructor

String::~String(void)

{

delete [] str;

}

Page 71: 线性表 顺序表  稀疏矩阵 字符串

// assignment operator. String to String

String& String::operator= (const String& s)

{ if (s.size != size)

{ delete [] str;

str = new char [s.size];

if(str == NULL) Error(outOfMemory); // assign size to be size of s

size = s.size; } // copy s.str and return reference to current object

strcpy(str, s.str);

return *this;

}

Page 72: 线性表 顺序表  稀疏矩阵 字符串

// assignment operator. C++String to String

String& String::operator= (char *s){ int slen = strlen(s) + 1; // if sizes differ, delete current string and reallocate

if (slen != size) { delete [] str; str = new char [slen]; if (str == NULL) Error(outOfMemory); size = slen; } strcpy(str, s); return *this;}

Page 73: 线性表 顺序表  稀疏矩阵 字符串

// all relational operators use C++ string function strcmp

// String == String

int String::operator== (const String& s) const

{

return strcmp(str,s.str) == 0;

}

Page 74: 线性表 顺序表  稀疏矩阵 字符串

// String == C++String

int String::operator== (char *s) const

{

return strcmp(str,s) == 0;

}

Page 75: 线性表 顺序表  稀疏矩阵 字符串

// C++String == String. this is a friend function, since

// the left operand is a C++String.

int operator== (char *str, const String& s)

{

return strcmp(str,s.str) == 0;

}

Page 76: 线性表 顺序表  稀疏矩阵 字符串

// String != String

int String::operator!= (const String& s) const

{

return strcmp(str,s.str) != 0;

}

Page 77: 线性表 顺序表  稀疏矩阵 字符串

// String != C++String

int String::operator!= (char *s) const

{

return strcmp(str,s) != 0;

}

Page 78: 线性表 顺序表  稀疏矩阵 字符串

// C++String != String

int operator!= (char *str, const String& s)

{

return strcmp(str,s.str) != 0;

}

Page 79: 线性表 顺序表  稀疏矩阵 字符串

// String < String

int String::operator< (const String& s) const

{

return strcmp(str,s.str) < 0;

}

Page 80: 线性表 顺序表  稀疏矩阵 字符串

// String < C++String

int String::operator< (char *s) const

{

return strcmp(str,s) < 0;

}

Page 81: 线性表 顺序表  稀疏矩阵 字符串

// C++String < String

int operator< (char *str, const String& s)

{

return strcmp(str,s.str) < 0;

}

Page 82: 线性表 顺序表  稀疏矩阵 字符串

// String <= String

int String::operator<= (const String& s) const

{

return strcmp(str,s.str) <= 0;

}

Page 83: 线性表 顺序表  稀疏矩阵 字符串

// String <= C++String

int String::operator<= (char *s) const

{

return strcmp(str,s) <= 0;

}

Page 84: 线性表 顺序表  稀疏矩阵 字符串

// C++String <= String

int operator<= (char *str, const String& s)

{

return strcmp(str,s.str) <= 0;

}

Page 85: 线性表 顺序表  稀疏矩阵 字符串

// String > String

int String::operator> (const String& s) const

{

return strcmp(str,s.str) > 0;

}

Page 86: 线性表 顺序表  稀疏矩阵 字符串

// String > C++String

int String::operator> (char *s) const

{

return strcmp(str,s) > 0;

}

Page 87: 线性表 顺序表  稀疏矩阵 字符串

// C++String > String

int operator> (char *str, const String& s)

{

return strcmp(str,s.str) > 0;

}

Page 88: 线性表 顺序表  稀疏矩阵 字符串

// String >= String

int String::operator>= (const String& s) const

{

return strcmp(str,s.str) >= 0;

}

Page 89: 线性表 顺序表  稀疏矩阵 字符串

// String >= C++String

int String::operator>= (char *s) const

{

return strcmp(str,s) >= 0;

}

Page 90: 线性表 顺序表  稀疏矩阵 字符串

// C++String >= String

int operator>= (char *str, const String& s)

{

return strcmp(str,s.str) >= 0;

}

Page 91: 线性表 顺序表  稀疏矩阵 字符串

// concatention: String + String

String String::operator+ (const String& s) const{ String temp; int len; delete [] temp.str; len = size + s.size - 1; temp.str = new char [len]; if (temp.str == NULL)Error(outOfMemory); temp.size = len; strcpy(temp.str,str); // copy str to temp strcat(temp.str, s.str); // concatenate s.str return temp; // return temp}

Page 92: 线性表 顺序表  稀疏矩阵 字符串

// concatention: String + C++String. same algorithm as// String + String, with a C++String as the right operand

String String::operator+ (char *s) const{String temp; int len; delete [] temp.str; len = size + strlen(s); temp.str = new char [len]; if (temp.str == NULL) Error(outOfMemory); temp.size = len; strcpy(temp.str,str); strcat(temp.str, s); return temp;}

Page 93: 线性表 顺序表  稀疏矩阵 字符串

// concatention: C++String + String. same algorithm as

// String + String, with a C++String as the left operand

String operator+ (char *cs, const String& s){ String temp; int len; delete [] temp.str; len = strlen(cs) + s.size; temp.str = new char [len]; if (temp.str == NULL) s.Error(outOfMemory); temp.size = len; strcpy(temp.str, cs); strcat(temp.str, s.str); return temp;}

Page 94: 线性表 顺序表  稀疏矩阵 字符串

// concatenate and assign: String += String

// the current object is modified

void String::operator+= (const String& s){ char *tempstr; int len; len = size + s.size - 1; tempstr = new char [len]; if (tempstr == NULL) Error(outOfMemory); strcpy(tempstr,str); strcat(tempstr, s.str); delete [] str; str = tempstr; size = len;}

Page 95: 线性表 顺序表  稀疏矩阵 字符串

void String::operator+= (char *s)

{ int len; char *tempstr; len = size + strlen(s); tempstr = new char [len]; if (tempstr == NULL) Error(outOfMemory); strcpy(tempstr,str); strcat(tempstr, s); delete [] str; str = tempstr; size = len;}

Page 96: 线性表 顺序表  稀疏矩阵 字符串

int String::Find(char c, int start) const

{ int ret; char *p; p = strchr(&str[start], c); if (p != NULL) ret = int(p-str); else ret = -1; return ret;}

Page 97: 线性表 顺序表  稀疏矩阵 字符串

// return index of last occurrence of c in string

int String::FindLast(char c) const{ int ret; char *p; // use C++ library function strrchr. returns pointer to

// the last occurrence of a character in the string

p = strrchr(str, c); if (p != NULL) ret = int(p-str); // compute index else ret = -1; // return -1 on failure return ret;}

Page 98: 线性表 顺序表  稀疏矩阵 字符串

{ int charsLeft = size-index-1, i; String temp; char *p, *q; if (index >= size-1) return temp; if (count > charsLeft) count = charsLeft; delete [] temp.str; temp.str = new char [count+1]; if (temp.str == NULL) Error(outOfMemory); for(i=0,p=temp.str,q=&str[index];i < count;i++) *p++ = *q++; *p = 0; temp.size = count+1; return temp;}

String String::Substr(int index, int count) const

Page 99: 线性表 顺序表  稀疏矩阵 字符串

void String::Insert(const String& s, int index){ int newsize, length_s = s.size-1, i; char *newstr, *p, *q; newsize = size + length_s; newstr = new char [newsize]; if (newstr == NULL)Error(outOfMemory);

for(i=0,p = newstr, q = str; i <= index-1;i++) *p++ = *q++; strcpy(p,s.str); p += length_s; strcpy(p,&str[index]); delete [] str; size = newsize; str = newstr;}

Page 100: 线性表 顺序表  稀疏矩阵 字符串

void String::Insert(char *s, int index)

{ int newsize, length_s = strlen(s), i; char *newstr, *p, *q; newsize = size + length_s; newstr = new char [newsize]; if (newstr == NULL) Error(outOfMemory); for(i=0,p = newstr, q = str;i <= index-1;i++) *p++ = *q++; strcpy(p,s); p += length_s; strcpy(p,&str[inde

x]); delete [] str; size = newsize; str = newstr; }

Page 101: 线性表 顺序表  稀疏矩阵 字符串

void String::Remove(int index, int count){ int charsLeft = size-index-1, newsize, i; char *newstr, *p, *q; if (index >= size-1) return; if (count > charsLeft) count = charsLeft; newsize = size - count; newstr = new char [newsize]; if (newstr == NULL)Error(outOfMemory);

for(i=0,p=newstr,q=str;i <= index-1;i++) *p++ = *q++; q += count; strcpy(p,q); delete [] str; size = newsize; str = newstr;}

Page 102: 线性表 顺序表  稀疏矩阵 字符串

// String index operator

char& String::operator[] (int n)

{

if (n <0 || n >= size-1)

Error(indexError,n);

return str[n];

}

Page 103: 线性表 顺序表  稀疏矩阵 字符串

// pointer conversion operator

String::operator char* (void) const

{

return str;

}

Page 104: 线性表 顺序表  稀疏矩阵 字符串

istream& operator>> (istream& istr, String& s)

{char tmp[256]; if (istr >> tmp) { delete [] s.str; // delete existing string s.size = strlen(tmp) + 1; s.str = new char [s.size]; if (s.str == NULL) s.Error(outOfMemory); strcpy(s.str,tmp); } return istr;}

Page 105: 线性表 顺序表  稀疏矩阵 字符串

ostream& operator<< (ostream& ostr, const String& s)

{

ostr << s.str;

return ostr;

}

Page 106: 线性表 顺序表  稀疏矩阵 字符串

// read characters from istr

int String::ReadString (istream& istr, char delimiter)

{ char tmp[256]; if (istr.getline(tmp, 256, delimiter)) { delete [] str; size = strlen(tmp) + 1; str = new char [size]; if (str == NULL)Error(outOfMemory);

strcpy(str,tmp); return size-1; } else return -1; // return -1 on end of file}

Page 107: 线性表 顺序表  稀疏矩阵 字符串

int String::Length(void) const

{

return size-1;

}

Page 108: 线性表 顺序表  稀疏矩阵 字符串

int String::IsEmpty(void) const

{

return size == 1;

}

Page 109: 线性表 顺序表  稀疏矩阵 字符串

void String::Clear(void)

{ delete [] str; size = 1; str = new char [size]; if (str == NULL) Error(outOfMemory); str[0] = 0;}

#endif // STRING_CLASS

Page 110: 线性表 顺序表  稀疏矩阵 字符串

测试

#include <iostream.h>

#pragma hdrstop

#include "strclass.h"

#define TF(b) ((b) ? "TRUE" : "FALSE")

Page 111: 线性表 顺序表  稀疏矩阵 字符串

void main(void)

{ String s1("STRING "), s2("CLASS"), s3;

int i; char c, cstr[30];

s3 = s1 + s2;

cout << s1 << "concatenated with " << s2

<< " = " << s3 << endl;

cout << "Length of " << s2 << " = “

<< s2.Length( ) << endl;

cout << "The first occurrence of 'S' in " << s2

<< " = " << s2.Find('S',0) << endl;

cout << "The last occurrence of 'S' in " << s2

<< " is " << s2.FindLast('S') << endl;

Page 112: 线性表 顺序表  稀疏矩阵 字符串

cout << “Insert 'OBJECT ' into s3 at position 7.” << endl; s3.Insert("OBJECT ", 7); cout << s3 << endl; s1 = "FILE1.S"; for(i=0;i < s1.Length( );i++) { c = s1[i]; if (c >= 'A' && c <= 'Z') { c += 32; // convert c to lower case s1[i] = c; } } cout << "The string 'FILE1.S' converted to lower \ case is "; cout << s1 << endl;

Page 113: 线性表 顺序表  稀疏矩阵 字符串

cout << "Test relational operators with strings "; cout << "s1 = 'ABCDE' s2 = 'BCF'" << endl; s1 = "ABCDE"; s2 = "BCF"; cout << "s1 < s2 is " << TF(s1 < s2) << endl; cout << "s1 == s2 is " << TF(s1 == s2) << endl; cout << "Use 'operator char* ( )' to get s1" << " as a C++ string: "; strcpy(cstr, s1); cout << cstr << endl;}

Page 114: 线性表 顺序表  稀疏矩阵 字符串

/*<Run of Program >STRING concatenated with CLASS = STRING

CLASSLength of CLASS = 5The first occurrence of 'S' in CLASS = 3The last occurrence of 'S' in CLASS is 4Insert 'OBJECT ' into s3 at position 7.STRING OBJECT CLASSThe string 'FILE1.S' converted to lower case is

file1.sTest relational operators with strings s1 = 'ABCDE' s2 = 'BCF's1 < s2 is TRUEs1 == s2 is FALSEUse 'operator char* ( )' to get s1 as a C++ string:

ABCDE*/