昨晚数据结构最简单也是最基础的线性表,有两种实现方式:
1、是逻辑结构与物理结构一致的顺序表,具体来说,就是用数组来实现
2、是数据的逻辑次序与物理次序很有可能不一致的链式表,通过结点来存储后继点的指针地址
顺序表定义:
const int MAX=100; template<typename T> class seqlist{ private: T data[MAX]; int size; public: seqlist(){size=0;} seqlist(T a[],int n){ if(n>MAX)throw "n error"; for(int i=0;i<n;i++) data[i]=a[i]; size=n;} ~seqlist(){} int getsize(){return size;} T get(int i); int loc(T x); void insert(int i,T x); T dele(int i); void prt();}; template<typename T> T seqlist<T>::get(int i){ if(i>size||i<1)throw"i error"; return data[i-1];} template<typename T> int seqlist<T>::loc(T x){ for(int i=0;i<size;i++) if(data[i]==x) return i+1; return -1;} template<typename T> void seqlist<T>::insert(int i,T x){ if(size>=MAX)throw"overflow"; if(i>size+1||i<1)throw"i error"; for(int j=size;j>=i;j--) data[j]=data[j-1]; data[i-1]=x; size++;} template<typename T> T seqlist<T>::dele(int i){ if(size<1)throw"downflow"; if(i<1||i>size)throw"i error"; T x=data[i-1]; for(int j=i;j<size;j++) data[j-1]=data[j]; size--; return x; } template<typename T> void seqlist<T>::prt(){ if(size<1)cout<<"empty"<<endl; else { for(int i=0;i<size;i++) cout<<data[i]<<" "; cout<<endl;}}
//link list template<typename T> struct node{ T data; node<T>*next;}; template<typename T> class linklist{ private:node<T>*first;//单链表的头指针 int linksize; public: linklist(){fisrt=new node<T>; first->next=NULL;//无参构造构造空线性表 linksize=0;} linklist(T a[],int n){ first=new node<T>; first->next=NULL;//先构造空链表 linksize=n; node<T>*p=first; for(int i=0;i<n;i++) {node<T>*s=new node<T>; s->data=a[i]; s->next=p->next;//插入到头节点之后 p->next=s;}} ~linklist(){ node<T>*p=first; while(p){ node<T>*q=p; p=p->next; delete q;}} int size(); T get(int i); int loc(T x); void insert(int i,T x); T del(int i); void prt();}; template<typename T> int linklist<T>::size(){ return linksize;} template<typename T> T linklist<T>::get(int i){ node<T>*p=first; int j=0; while(p&&j<i){ p=p->next; j++;} if(!p) throw"i error"; else return p->data;} template<typename T> int linklist<T>::loc(T x){ node<T>*p=first; int j=0; while(p&&x!=p->data){ p=p->next; j++;} if(!p)throw"x no"; else return j;} template<typename T> void linklist<T>::insert(int i,T x){ node<T>*p=first; int j=0; while(p&&j<i-1){ p=p->next; j++;}//找到i-1 if(!p)throw"insert error"; else{ node<T>*s=new node<T>; s->data=x; s->next=p->next; p->next=s;} linksize++;} template<typename T> T linklist<T>::del(int i){ node<T>*p=first; int j=0; while(p&&j<i-1){ p=p->next; j++;} if(!p||!p->next)throw"del error"; else{ T t=p->next->data; p->next=p->next->next; return t;} linksize--;} template<typename T> void linklist<T>::prt(){ node<T>*p=first; if(!p)cout<<"empty"<<endl; p=p->next; while(p){ cout<<p->data<<" "; p=p->next;} cout<<endl;}
#include"2.h" int main(){ int a[]={10,12,15,25,8,16,20}; seqlist<int>li(a,7); linklist<int>l(a,7); cout<<"the inf li:"<<endl; li.prt(); cout<<"the inf of linklist:"<<endl; l.prt(); try{ cout<<"the size of seqlist:"<<endl; cout<<li.getsize()<<endl; cout<<"the size of linksize:"<<endl; cout<<l.size()<<endl; cout<<"find the ith:"<<endl; cout<<li.get(3)<<endl; cout<<"find the ith:"<<endl; cout<<l.get(3)<<endl; cout<<"the loc of 15"<<endl; cout<<li.loc(15)<<endl; cout<<"the loc of 15:"<<endl; cout<<l.loc(15)<<endl; li.insert(3,100); cout<<"the new after insert:"<<endl; li.prt(); l.insert(3,100); cout<<"the new after insert:"<<endl; l.prt(); li.dele(3); cout<<"the new after dele:"<<endl; li.prt(); l.del(3); cout<<"the new after dele:"<<endl; l.prt();} catch(string&s){ cout<<s<<endl; } system("pause"); return 0;}两者的比较:
一、时间性能比较:
是指基于某种存储结构的算法时间复杂度。类如取出线性表内任意某个元素,使用顺序表快一点时间性能O(1),而链式表只能从表头开始依次向后扫描直至特定位置O(n);但是在进行相应插入与删除操作时候,在给出该处指针以后,增删所需时间O(1),而顺序表需平均移动一半元素,时间性能O(n),这对于大规模线性表来说,是不可忍受的。
二、空间性能比较:
首先定义存储密度:存储密度=(数据域占用的存储量)/(整个节点占用的存储量)
顺序表存储密度为1,而链式表数据域和指针域各占一部分节点,从这一层来说,顺序表更好;但是顺序表需要预先静态分配一定长度的存储空间,如果事先不知道线性表规模,会面临预分配过剩导致的浪费或者预分配过少导致的碎片,而单链表无需预分配。根据需要动态产生即可。故当线性表规模小或者规模已知时候用顺序表,否则用单链表。