template <classT> //构造函数 SeqList<T> :: SeqList ( int sz ) { if ( sz > 0 ) { MaxSize = sz; last = -1; data = new T [MaxSize]; if ( data == NULL ) { cerr<<"存储分配失败!"<<endl; exit(1); } } } template <classT> //复制构造函数 SeqList<T> :: SeqList( SeqList<T>& L ){ maxSize=L.Size(); last=L.Length()-1; T value; data=new T[maxSize]; if ( data == NULL ) { cerr<<"存储分配失败!"<<endl;exit(1); } for(int i=1;i<=last+1;i++) { L.getData(i,value);data[i-1]=value; } }
template <classT> //重定义大小 voidSeqList<T> :: reSize(int newSize){ if(newSize<=0){cerr<<"无效的数组大小"<<endl;return;} if(newSize!=maxSize){ T *newarray=new T[newSize]; if ( newarray == NULL ) { cerr<<"存储分配失败!"<<endl;exit(1); } int n=last+1; T *srcptr=data; T *destptr=newarray; while(n- -)*destptr++=*srcptr++; delete []data; data=newarray; maxSize=newSize; } }
template <classT> intSeqList<T> :: search ( T & x ) const { //搜索函数:在顺序表中从头查找结点值等于 //给定值x的结点所在位置,如果没找到返回0 for(int i = 0; i <= last ; i++) if (data[i]==x) return i+1 ; return0; }
template <classT> //顺序表的表项的插入insert算法 boolSeqList<T> :: Insert (T& x, int i ) { if (last+1 >= MaxSize|| (i < 0 || i > last + 1) ) returnfalse;
voidUnion( SeqList<int> & A, SeqList<int> & B) { int n = A.Length ( ), x; int m = B.Length ( ); for ( int i = 1; i < =m; i++ ) { B.getData(i,x); //在B中取一元素 int k = A.Search (x); //在A中搜索它 if ( k == 0 ) //若未找到插入它 { A.Insert (n, x); n++; } } } voidmain(){ SeqList<int> s1,s2; s1.input(); s2.input(); Union(s1,s2); s1.output();
}
顺序表的应用:集合的“交”运算
1 2 3 4 5 6 7 8 9 10 11 12
voidIntersection( SeqList<int> & A, SeqList<int> & B ){ int n = A.Length ( ); int m = B.Length ( ); int i = 1, x; while ( i < =n ) { A.getData(i, x); //在A中取一元素 int k = B.search (x); //在B中搜索它 if ( k == 0 ) { A.Remove (i,x); n- - ; } //未找到在A中删除它 else i++; } }
public: SeqList( intsize = DefaultSize ){ assert ( size >= 0 ); if ( size > 0 ) { MaxSize = size; last = -1; data = new Type[MaxSize]; } }
~SeqList() { delete[] data; } intLength()const{ return last + 1; } intFind( Type & x )const; intIsIn( Type & x); intInsert( Type & x, int i ); intRemove( Type & x); intNext( Type & x ); intPrior( Type & x ); intIsEmpty(){ return last == -1; } intIsFull(){ return last == MaxSize - 1; } Type Get( int i ){ return i < 0 || i > last ? NULL:data[i]; } voidPrint(); private: Type *data; int MaxSize; int last; };
/*template < class Type > SeqList <Type>::SeqList( int size = DefaultSize ) { assert ( size >= 0 ); if ( size > 0 ) { MaxSize = size; last = -1; data = new Type[MaxSize]; } } */ template < classType > intSeqList <Type>::Find( Type & x ) const { int i = 0; while ( i <= last && data[i] != x ) i++; if ( i > last ) return-1; elsereturn i; }
template < classType > intSeqList <Type>::IsIn( Type & x ) { int i = 0, found = 0; while ( i <= last && !found) if ( data[i] != x ) i++; else found = 1; return found; }
template < classType > intSeqList <Type>::Insert( Type & x, int i ) { if ( i < 0 || i > last+1 || last == MaxSize - 1 ) return0; else { last++; for ( int j = last; j > i; j-- ) data[j] = data[j-1]; data[i] = x; return1; } }
template < classType > intSeqList <Type>::Remove( Type & x ) { int i = Find(x); if ( i >= 0 ) { last--; for ( int j = i; j <= last; j++ ) data[j] = data[j+1]; return1; } }
template < classType > intSeqList <Type>::Next( Type & x ) { int i = Find(x); if ( i >= 0 && i < last ) return i+1; elsereturn-1; }
template < classType > intSeqList <Type>::Prior( Type & x ) { int i = Find(x); if ( i > 0 && i <= last ) return i-1; elsereturn-1; }
template < classType > voidUnion( SeqList <Type> & LA, SeqList <Type> & LB ) { int n = LA.Length(); int m = LB.Length(); for ( int i=0; i <= m; i++ ) { Type x = LB.Get(i); int k = LA.Find(x); if ( k == -1 ) { LA.Insert( x, n ); n++;} } }
template < classType > voidIntersection ( SeqList <Type> & LA, SeqList <Type> & LB ) { int n = LA.Length(); int m = LB.Length(); int i = 0; while ( i < n ) { Type x = LA.Get(i); int k = LB.Find(x); if ( k == -1 ) { LA.Remove(x); n--; } else i++; } }
template < classType > voidSeqList <Type>::Print() { if ( last == -1 ) cout<<"It is empty" ; elsefor ( int i=0; i<=last; cout << " data[" << i++ << "] = " << data[i] ); cout << endl; }
intmain(){ int length; SeqList<int>* sq=new SeqList<int>;
public: List () { first = new LinkNode<T>; } List (const T& x) { first = new LinkNode<T> (x ); } List (List<T>& L); ~List () { makeEmpty(); } voidMakeEmpty( ); //将链表置为空表 intLength( )const; //计算链表的长度
LinkNode<T> *getHead()const{ return first; } LinkNode<T> *Search( T x ); //搜索含数据x的元素 LinkNode<T> * Locate( int i ); //搜索第 i 个元素的地址 boolGetData( int i, T& x ); //取出表中第 i 个元素的值 boolInsert(int i ,T& x); //将x插在表中第 i 个元素后 boolRemove(int i ,T& x); //删除第i个元素,x返回该元素的值
template <classT>//链表长度 intList<T> :: Length ( ) const { //求单链表的长度 LinkNode<T> *p = first->link; //检测指针 p 指示第一个结点 int count = 0; while ( p != NULL ) { //逐个结点检测 count++; p = p->link; } return count; //注意count的初始化和返回值之间的关系 }
template <classT> //搜索 LinkNode<T> *List <T> :: Search (T x ) { //在链表中从头搜索其数据值为x的结点 LinkNode<T> * p = first->link; //检测指针 p 指示第一个结点 while ( p != NULL ) if ( p->data == x ) break; else p = p->link; return p; // p 在搜索成功时返回找到的结点地址 // p 在搜索不成功时返回空值 }
template <classT> //定位 LinkNode<T> *List<T> :: Locate ( int i ) { //定位函数。返回表中第 i 个元素的地址 //若 i < 0或 i 超出,则返回NULL if ( i < 0 ) returnNULL; // i 值不合理 LinkNode<T> * p =first; int k = 0; while ( p != NULL && k < i ) {p = p->link ; k++;} //找第 i 个结点 return p; //返回第 i 个结点地址或NULL }
template <classT> //取值 bool * List<T> :: GetData ( int i, T& x ) { //取出链表中当前元素的值 if (i<=0) returnNULL; LinkNode<T> *p = Locate ( i ); // p 指向链表第 i 个结点 if ( p == NULL ) returnfalse; else { x=p->data; returntrue; } }
template <classT> //单链表的实现———插入 boolLinkList<T> :: Insert(int i, T& x) //在第i个位置后插入x { LinkNode<T> * p=Locate(i); if (p == NULL) returnfalse ; //没有找到 else { s = new LinkNode<T>(x); //申请一个结点s if(s==null){cerr<<"store is error"<<endl; exit(1);} s->link= p->link; p->link = s; //结点s插入结点p之后 returntrue; } }
template <classT> //删除 boolList<T> :: Remove ( int i ,T& x) { LinkNode<T> *p = Locate (i-1); if (p == NULL || p->link == NULL) returnfalse; LinkNode<T> *q= p->link; x = q->data; p->link = q->link; delete q; returntrue; }
CircLinkNode ( CircLinkNode<T> *next = NULL ) : link ( next ) { } CircLinkNode ( T d ,CircLinkNode<T> *next = NULL ) : data ( d ), link ( next ) { } };
CircLinkNode<T> * getHead( )const; voidsetHead(CircLinkNode<T> *p); CircLinkNode<T> * Search(T x); CircLinkNode<T> * Locate(int i); T *getData( int i ); voidsetData( int i, T& x); boolInsert(int i, T& x ); boolRemove(int i, T& x ); }; //循环链表与单链表的操作实现,最主要的不同就是扫描到链尾,遇到的不是NULL,而是表头first
template <classT> //循环链表的搜索算法 CircListNode<T> * CircList<T>::Search( T x ) { //在链表中从头搜索其数据值为 x 的结点 current = first->link; while ( current != first && current->data != x ) current = current->link; return current; }
template <classT> //循环链表——插入 boolCircList<T> ::Insert(int i, T x)//在i项后面插入一项 { if i<0returnfalse; CircLinkNode<T> * p ; int count; if (i==0) {p=first;count=0}else{ p=first->link; count=1;} //第一个位置特别处理。避免指针出界状态与初始状态重合 while (p != first && count < i ) { p = p->link; count++; } if (p == first&&i!=0) returnfalse; else { s = new CircLinkNode<T>; s->data = x; s->link = p-> link; p-> link = s; returntrue; } } //循环链表,循环指针结束条件不同于单链表,所以初始化不同。需要特别考虑第一个元素
用循环链表求解约瑟夫问题
约瑟夫问题的提法 n 个人围成一个圆圈,首先第 1 个人从 1 开始一个人一个人顺时针报数, 报到第 m 个人,令其出列。然后再从下一 个人开始,从 1 顺时针报数,报到第 m 个人,再令其出列,…,如此下去, 直到圆圈中只剩一个人为止。此人即为优胜者。
template <classT> classCircList{ private: CircLinkNode<T> *first, *last;//链表的表头指针、当前指针和表尾指针 public: CircList(){first=new CircLinkNode<T>(); first->link=first;}; //CircList ( const T& x ); // CircList ( CircList<T>& L); // ~CircList ( ); // void setHead(CircLinkNode<T> *p); // CircLinkNode<T> * Search(T x); // CircLinkNode<T> * Locate(int i); // T *getData ( int i ); // void setData( int i, T& x); boolinsert(int i, T& x ); // bool Remove (int i, T& x ); //bool IsEmpty ( ) { return first->link == first; } // int Length ( ) const; CircLinkNode<T> * getHead( )const{return first;}; //void input(int i); //输入i个元素
};
template <classT> boolCircList<T>::insert(int i, T& x)//在i项后面插入一项 { if(i<0)returnfalse; CircLinkNode<T> * p,s ; int count ; if(i==0) {p=first;count=0;} else {p=first->link;count=1;} //第一个位置特别处理。避免循环指针出界状态与初始状态重合 while (p != first && count < i ) { p = p->link; count++; } if (p == first&&i!=0) returnfalse; else { // s = new CircLinkNode<T>(); s->data = x; // s->link = p->link; p->link = s; p->link=new CircLinkNode<T>(x,p->link); cout<<"input:"<<x<<endl; returntrue; } }
template <classT> voidJosephus(CircList<T>& Js, intn, intm) { CircLinkNode<T> *p,*first, *pre = NULL; first= Js.getHead(); p=first->link; if(p==first) exit(1); //表空退出 int i, j; for ( i = 0; i < n-1; i++ ) { //执行n-1次 if(p==first)p=p->link; for ( j = 1; j < m; j++) //数m-1个人 { pre = p; p = p->link; if(p==first)j--; } cout << "出列的人是" << p->data << endl; pre->link = p->link; delete p; //删去 p = pre->link; } };
voidmain(){ CircList<int> clist; int i,n,m; cout << "输入游戏者人数和报数间隔 : "; cin >> n >> m; for (i = 1; i <= n; i++ ) clist.insert(i-1, i); //约瑟夫环 // inclist.input(n); //函数需考虑第一个元素插入的特殊性 Josephus(clist, n, m); //解决约瑟夫问题 }