1 / 114

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

第二章 数组. 线性表 顺序表 稀疏矩阵 字符串. 一、线性表. 线性表 相同数据类型的元素的有限序列 叫线性表。 ( 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 。.

von
Télécharger la présentation

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

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第二章 数组 • 线性表 • 顺序表 • 稀疏矩阵 • 字符串

  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

  3. 线性表是最简单的也是最基本的数据结构。 • 线性表可以用来构造字符串,集合,栈,队列,用来排序。 • 线性表可以顺序表示用一组地址连续的存储单元一次存储数据元素。 • 线性表也可以用线性链表表示。

  4. 二、顺序表——线性表的顺序表示 可以用通用数组定义通用线性表。 通用数组是可变长度的数组,也叫安全数组。

  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>&); //输出操作重载 };

  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; //查找一个元素 TGetData(int pos) const; //取线性表中元素

  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); //清空 };

  8. // constructor. set size to 0 template<class T> SeqList<T>::SeqList(void): listitem(size),size(0) { }

  9. // return number of elements in list template<class T> int SeqList<T>::ListSize(void) const { return size; }

  10. // tests for an empty list template<class T> int SeqList<T>::ListEmpty(void) const { return size == 0; }

  11. // clears list by setting size to 0 template<class T> void SeqList<T>::ClearList(void) { size = 0; }

  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

  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 }

  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 }

  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;

  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 }

  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 {

  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 } }

  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> TSeqList<T>::DeleteFront(void) { TfrontItem; // list is empty if size == 0 if (size == 0) { cerr << "Attempt to delete the front / of an empty list!" << endl; exit(1); }

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

  21. // return value at position pos in list. // if pos is not valid list position, // teminate program with an error message. template<class T> TSeqList<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]; }

  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;

  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; }

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

  25. 顺序线性表复杂度分析 • 从已建立的顺序表中“取表长” ,“取第i个元素”的复杂性是O(1), 2. 在表长n的顺序表第i位前插入一个元素,要把表尾n-i+1个元素后移一格。 假设每一位都插入一个数,从第1位到末尾第n+1位,总移动次数是: Σi=1i=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).

  26. 三、稀疏矩阵 一个阶数很高的矩阵中如果有许多相等的元素,或零元素,成为特殊矩阵。 对特殊矩阵可以进行压缩存储

  27. 特殊矩阵 对称矩阵 上(下)三角矩阵 对角矩阵 稀疏矩阵

  28. 对称矩阵 矩阵 A=(aij)n,n aij= aji , 0≤i,j≤n 每一对元素分配一个存储空间,可以 将n2个元素存储到n(n+1)/2个空间中

  29. 下三角矩阵 1+2+3+ ……+n=n(n+1)/2 T s[n(n+1)/2]; a11 a21a22 a31a32 a33 …… an1an2 an3 ……ann s[0]=a11;s[1]=a21; s[k]=aij 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

  30. 对角矩阵 a11 a12 a21 a22 a23 · · · · · · · · an-1n ann-1 ann s[k]=aij; k=3(i-1)+j; j=k%3; i=(k-j)/3

  31. 稀疏矩阵 Sparse Matrix 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 m*n阶矩阵 A=(aij)mn中有t个非零元素, 如果 δ=t/(m*n)≤5%, 称A为稀疏矩阵

  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

  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

  34. 稀疏矩阵元素的类TRiple template<class T> class Triple { public: int row, col; T elem; SetVal(int r,int c,T d) {elem=d;row=r;col=c;} };

  35. 稀疏矩阵类的定义 #define MAXSIZE 500 template<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; };

  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( ); };

  37. 矩阵的转置 T=M’ for(col=1;col<=nu;col++) for(row=1;row<=mu;row++) T[col][row]=M[row][col] 时间复杂度O(mu*nu)

  38. M’ rowcol elem 21 12 3 1 9 1 3 –3 6 3 14 3 4 24 2 5 18 1 6 15 46 -7 M rowcol elem 12 12 1 3 9 3 1 –3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7

  39. M rowcol elem 12 12 1 3 9 3 1 –3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7 M’ rowcol elem 13 -3 16 15 21 12 2 5 18 31 9 34 24 4 6 -7 6 3 14

  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;}

  41. 稀疏矩阵的转置的时间复杂度 O(nu*tu) 若tu~nu*mu O(nu*tu)=O(mu*nu*nu) 不是一个好算法! 应当改进!

  42. 快速转置 依次逐个对号入座 M rowcol elem 12 12 1 3 9 3 1 –3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7 M’ rowcol elem 2 1 12 3 1 9 先求出M中每一列(即M’中每一行)元素的个数num[col],确定M’每行起始位置cpot[col]。

  43. 快速转置 M rowcol elem 12 12 1 3 9 3 1 –3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7

  44. 时间复杂性O(nu+tu) 快速转置算法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; }

  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++;}

  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; }

  47. 矩阵的乘法 Amp*Bpn 时间复杂度mpn (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*b21a12*b22 a12*b23a12*b24 a13*b31a13*b32 a13*b33a13*b34 a14*b41a14*b42 a14*b43a14*b44

  48. 稀疏矩阵的乘法 B rowcol elem rpos[row] 11 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 A rowcol elem 12 12 1 3 9 3 1 –3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7

  49. template <classT>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];

  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++;}

More Related