C++程序设计基础之(第五章)集合与结构

  • 在程序设计中,被处理数据对象的数据元素之间通常有不同的逻辑关系。
  • 集合是具有某种相同属性数据元素的整体。
  • 由不同类型的数据元素组成的数据类型称为结构。

5.1 位运算

在这里插入图片描述
在这里插入图片描述

1. 按位与运算

左右操作数对应的每一位分别做逻辑运算
在这里插入图片描述 若有语句

 cout<<"10&29="<<(10&29)<<endl;

则显示结果为
在这里插入图片描述

2. 按位或运算

左右操作数对应的每一位分别做逻辑运算
在这里插入图片描述
若有语句

cout<<"10|29="<<(10|29)<<endl;

则显示结果为
在这里插入图片描述

3. 按位异或运算

当左右操作数对应位不相同,即当且仅当其中一个为1时,位操作的结果才为1。
在这里插入图片描述
若有语句

 cout<<"10|29="<<(10|29)<<endl;

则显示结果为
在这里插入图片描述

4. 左移

按右操作数指定位数,将左操作数按位向左移动,腾空数位补0
对于一个整数,每左移一位就相当于乘以2(结果不溢出时)
在这里插入图片描述
若有语句

 cout<<"10<<2="<<(10<<2)<<endl;

则显示结果为
在这里插入图片描述

5. 右移

按右操作数指定位数,将左操作数按位向右移动
对于一个整数,每右移一位就相当于整除以2
在这里插入图片描述
若有语句

 cout<<"12>>2="<<(12>>2)<<endl;

则显示结果为
在这里插入图片描述
做算术右移时,不会移动符号位
若有语句

cout<<-12>>2="<<(-12>>2)<<endl;

则显示结果为
在这里插入图片描述

6. 按位取反

单目运算。对操作数按位做逻辑非.
在这里插入图片描述
负数在计算机中用补码表示。11110101是-11的补码。
若有语句

 cout<<"~10="<<(~10)<<endl;

则显示结果为
在这里插入图片描述

7. 位运算的复合赋值

位运算的5个复合赋值与其他复合赋值的操作形式一致。
在这里插入图片描述

8.掩码

  • 当一个整数的二进制串中只有一个数位为1时,称为掩码
  • 程序中通常借助掩码对数据按位进行测试

例:按二进制位串形式输出正整数的值。


```cpp
#include<iostream>
using namespace std;
void bitDisplay(unsigned value);
void main()
{ unsigned x;
  cout<<"Enter an unsigned integer: ";
  cin>>x;
  bitDisplay(x);	//调用函数,以二进制形式输出正整数
}
void bitDisplay(unsigned value)
{ unsigned c;
  unsigned bitMask=1<<31;		//掩码,最高位置1
  cout<<value<<'=';
  for(c=1;c<=32;c++)
  { cout<<(value&bitMask?'1':'0');	//输出value的最高位
     value<<=1;			//value左移1位
     if(c%8==0)   cout<<' ';
  }
  cout<<endl;
}

结果为:
在这里插入图片描述

5.2 集合

  • 集合是不能精确定义的基本数学概念。一般认为,当一些事物是可以按照某种性质(属性)分辨,这种事物构成的整体就称为集合。
  • 根据集合的属性,可以断定某个特定的事物是否属于这个集合。如果属于,就称它为这个集合的元素。

集合的基本运算

在这里插入图片描述

集合运算的实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
例:集合运算的实现

//用无符号整数 表示{1…32}的 整数集合
//setH.h
#include<iostream>
using namespace std;
unsigned putX( unsigned &S, unsigned x );     //元素x并入集合S
void setPut( unsigned &S ); 	//输入集合S的元素
void setDisplay( unsigned S ); 	//输出集合S中的全部元素
unsigned Com( unsigned A, unsigned B );       //求并集A∪ B
unsigned setInt( unsigned A, unsigned B );     //求交集A∩B
unsigned setDiff( unsigned A, unsigned B);      //求差集A-B
bool Inc(unsigned A, unsigned B);		      //判蕴含
bool In(unsigned S, unsigned x); 		//判属于x∈S
bool Null( unsigned S ); 			//判空集
//steOperate.cpp
#include"setH.h“

void setPut(unsigned & S) 	//输入集合元素
{ unsigned x;
  cin>>x;
  while( x )  {  putX( S, x );    cin>>x;  }
}

void setDisplay(unsigned S) 	//输出集合S中的全部元素
{ unsigned c;
  unsigned bitMask=1;
  if( Null( S ) )
    { cout<<"{    }\n“;      return ;    }
  cout<<"{ ";
  for( c=1; c<=32; c++ )
    { if( S&bitMask )     cout<<c<<",;    bitMask<<=1;  }
  cout<<"\b\b }\n";
 }
 unsigned putX(unsigned &S, unsigned x)   //元素x并入集合S
{  unsigned bitMask=1;
    bitMask <<= x-1;
   S |= bitMask;
   return  S;
}

unsigned Com( unsigned A,unsigned B )     //求并集A∪B
{  return  A|B;
}

unsigned setInt( unsigned A, unsigned B )	  //求交集A∩B
{  return  A&B;
}

unsigned setDiff( unsigned A,unsigned B)    //求差集A-B
{ return  A&( ~ ( A&B ) );
}
bool Inc(unsigned A,unsigned B)   //判蕴含 
{  if(  ( A | B ) == B )     return  true;
    return  false;
}

bool In(unsigned S,unsigned x)	//判属于x∈S
{  unsigned bitMask=1;
   bitMask <<= x-1;
   if( S & bitMask )
       return  true;
   return  false;
}

bool Null(unsigned S) 	//判空集
{  if( S )
      return  true;
   return  false;
}
//test.cpp
#include "setH.h"
int main()
{ unsigned A=0,  B=0;
  unsigned x;
  cout<<"Input the elements of set A, 1-32, until input 0 :\n";
  setPut( A );
  cout<<"Input the elements of set B, 1-32, until input 0 :\n";
  setPut( B );
  cout<<"A = "; 
  setDisplay( A );
  cout<<"B = ";
  setDisplay( B );
  cout<<"Input x: ";
  cin>>x;
  cout<<"Put "<<x<<" in A = ";
  setDisplay( putX( A,x ) );
  cout<<"A+B = ";
  setDisplay( Com( A, B ) );
  cout<<"A*B = ";
  setDisplay( setInt( A, B ) );
  cout<<"A-B = ";
  setDisplay( setDiff( A, B ) );
  if( Inc( A, B ) )
	   cout <<"A <= B\n";
  else 
    cout <<"not A <= B\n";
  cout <<"Input x: ";
  cin >> x;
  if( In( A, x ) )
	   cout <<x << " in A\n";
  else
    cout << x << " not in A\n";
}

给出结果:
在这里插入图片描述
例:用数组和位运算实现集合的基本运算。用长度为N,元素为无符号整数的数组表示全集{1,2,… ,32*N }的整数集合。

//setH.h
#include<iostream>
using namespace std;
 const unsigned N=4;			//数组长度
typedef unsigned setType[N];		//用数组存放长度的集合
void setPut( setType S ); 			//输入集合S的元素
void setDisplay( const setType S ); 	//输出集合S中的全部元素
void putX( setType S, unsigned x ); 		//元素x并入集合S
void Com( setType C, const setType A, const setType B ); 	//求并集C=A∪B
void setInt(setType C,const setType A,const setType B ); 	//求交集C=A∩B
void setDiff(setType C,const setType A,const setType B); 	//求差集C=A-B
bool Inc( const setType A, const setType B ); 		//判蕴含
bool In( const setType S, unsigned x ); 			//判属于x∈S
bool Null( const setType S ); 			//判空集,空集返回true
//steOperate.cpp
#include"setH.h"
 void setPut( setType S)		 //输入集合元素
{ unsigned x ;
  cin >> x ;
  while( x )
  { putX( S, x ) ;	    cin >> x ;  }
}
void setDisplay( const setType S )		 //输出集合S中的全部元素
{ unsigned c , i ;   unsigned bitMask ;
  if( Null( S ) )    { cout<<"{    }\n“;      return ;    }
  cout << "{ " ;
  for( i=0; i<N; i++ )		//处理每个数组元素
   { bitMask = 1 ;			//掩码,32位
     for( c=1; c<=32; c++ )		//按位处理
       {  if( S[i] & bitMask )    cout << i*32+c <<,;   //输出元素
          bitMask <<= 1 ;
       }
   }
  cout << "\b\b }\n" ;		//刷除最后的逗号
}
//元素x并入集合S
void putX( setType S, unsigned x ) 	
{ unsigned bitMask = 1 ;
  bitMask <<= ( (x-1)%32 ) ;
  S[(x-1)/32] |= bitMask ;
}
 //求并集C=A∪B
void Com( setType C, const setType A, const setType B )	
{ for( int i=0; i<N; i++ )
       C[i] = A[i] | B[i] ;
}
 //求交集C=A∩B
 void setInt( setType C, const setType A, const setType B )	
{ for( int i=0;  i<N;  i++ )
       C[i] = A[i] & B[i] ;
}
//求差集C=A-B
 void setDiff( setType C, const setType A, const setType B ) 	
{ for( int i=0; i<N; i++ )
       C[i] = A[i] & ( ~( A[i] & B[i] ) ) ;
}
bool Inc( const setType A, const setType B ) 	//判蕴含
{  bool t = true ;
   for( int i=0; i<N; i++)
     {  if( ( A[i] | B[i] ) != B[i] )      t = false ;   }
  return t ;
}
 bool In( const setType S, unsigned x )		 //判属于x∈S
{  unsigned bitMask = 1 ;
   bitMask <<= ( (x-1)%32 ) ;
   if ( S[(x-1)/32] & bitMask )     return true;
   return false;
}
 bool Null( const setType S )		 //判空集
{  bool t = true ;
   for( int i=0; i<N; i++)
     {  if( S[i] )        t = false ;    }
  return t ;
}
//test.cpp
#include"setH.h"
int main()
{ setType A = { 0 } , B = { 0 } , C = { 0 } ;   unsigned x;
  cout << "Input the elements of set A, 1-"<<32*N<<" , until input 0 :\n" ;
  setPut( A );
  cout << "Input the elements of set B, 1-"<<32*N<<" , until input 0 :\n" ;
  setPut( B );
  cout << "A = " ;   setDisplay( A ) ;
  cout << "B = " ;  setDisplay( B );
  cout << "Input x: " ;  cin >> x ;   putX( A, x);
  cout << "Put " << x << " in A = " ;   setDisplay( A );
  cout << "C = A+B = " ;   Com( C, A, B );   setDisplay( C );
  cout << "C = A*B = " ;   setInt( C, A, B );  setDisplay( C );
  cout << "C = A-B = " ;   setDiff( C, A, B );  setDisplay( C );
  if( Inc( A, B ) )	 cout << "A <= B\n" ;
  else     cout << "not A <= B\n" ;
  cout << "Input x: " ;  cin >> x ;
  if( In( A, x ) )	 cout << x << " in A\n" ;
  else    cout << x << " not in A\n" ;
}

5.3 结构

在这里插入图片描述

5.3.1 定义结构

结构类型定义形式为:

struct 标识符 {
类型 成员1 ;
类型 成员2 ;

类型 成员n ; } ;
例:

struct  employee  
{  char  name [ 10 ] ;
    long  code ;
    double  salary ;
    char address [ 50 ] ;
    char  phone [ 20 ] ;
} ;
  • 可以用不同方法定义一个结构变量

(1) 声明类型之后声明变量
例:

struct  employee  
{  char  name [ 10 ] ;
    long  code ;
    double  salary ;
    char address [ 50 ] ;
    char  phone [ 20 ] ;
} ;
employee  worker1, worker2, *Emp ;

(2) 声明类型的同时声明变量
例:

struct  employee  
{  char  name [ 10 ] ;
    long  code ;
    double  salary ;
    char address [ 50 ] ;
    char  phone [ 20 ] ;
}worker1, worker2, *Emp ;
 

(3) 直接声明结构类型变量
例:

struct     //注意此时没有了结构类型标识符
{  char  name [ 10 ] ;
    long  code ;
    double  salary ;
    char address [ 50 ] ;
    char  phone [ 20 ] ;
} worker1, worker2, *Emp ;
  • 说明

(1) 结构变量占有一片连续内存空间,具有结构类型的特征
例:

struct  employee  
{  char  name [ 10 ] ;
    long  code ;
    double  salary ;
    char address [ 50 ] ;
    char  phone [ 20 ] ;
} ;
employee  worker1, worker2,  *Emp = &worker1 ;

在这里插入图片描述
(2) 一个结构类型的成员可以是另一个已定义的结构类型
例如: 为职工结构添加出生日期信息类型和变量声明为:

struct  date
{  int  month ;
    int  day ;
    int  year ;
} ;
struct employee
{  char  name [ 10 ] ;
    date  birthday ;
    long  code ;
    double  salary ;
    char address [ 50 ] ;
    char  phone [ 11 ] ;
}  worker1, worker2 ;

不能出现递归操作。

struct  person
{  char  name [ 10 ] ;
    long  code ;
    double  salary ;
    char address [ 50 ] ;
    char  phone [ 11 ] ; 
    person son;//这样是错误的。
    
}  worker1, worker2 ;

(3) 声明结构类型变量可以同时初始化

struct employee
{  char  name [ 10 ] ;
    long  code ;
    double  salary ;
    char address [ 50 ] ;
    char  phone [ 11 ] ;
}  worker = {"Wang Li " , 991083456, 1200.5, "guang zhou " , " 87111111 " } ;

5.3.2 访问结构

(1)访问结构变量的成员 结构变量 . 成员

# include <iostream>
using namespace std ;
struct weather		// 声明结构类型
{  double  temp; 
   double  wind;  
} ;
int main( )
{ 
    weather  today ;	// 声明结构类型变量
    today.temp = 10.5 ;	// 对结构变量成员赋值
    today.wind = 3.1 ;
    cout << “Temp =<< today.temp << endl ;	 // 按成员输出
    cout << “Wind =<< today.wind << endl ;
}

(2)用指针访问结构变量的成员

  • 结构指针 -> 成员
  • (*结构指针 ) . 成员
# include <iostream>
using namespace std ;
# include <cstring>
struct  person
{ char name[20] ;
  unsigned long id;
  double salary; 
 };
int main( )
{  person  pr1 ;
   person *pp ;		// 定义结构指针
   pp = & pr1 ;		// 取结构变量地址
   strcpy ( pp -> name ,  “David Marat” ) ;		// 对结构成员赋值
   pp -> id = 987654321 ;//  (*pp). id 
   pp -> salary = 335.0 ;(*pp). salary
   cout << pp -> name << ‘\t’ << pp -> id << ‘\t’ << pp -> salary << endl ;
}

(3)类型相同的结构变量可以整体赋值

# include <iostream>
using namespace std ;
struct  weather		
{  double  temp;
   double  wind; 
 } yesterday ;
int main ( )
{  weather  today ;	
   yesterday . temp = 10.5 ;	
   yesterday . wind = 3.1 ;
   today = yesterday ;	// 结构变量整体赋值
   cout << “Temp =<< today . temp << endl ;
   cout << “Wind =<< today . wind << endl ;
}

“类型相同的变量” 是指用同一类型标识符说明的变量
例如:

struct  weather1		
{  double  temp; 
   double  wind; 
 } yesterday ;
struct  weather2		
{  double  temp;
   double  wind; 
 } today ;

yesterday 和 today尽管成员相同,但不是同类型变量不可以整体赋值。

5.3.3 结构参数

函数的结构类型参数可以传值、指针及引用参数
例:

  • 传值得方式。
# include <iostream>
using namespace std ;
struct  weather
{  double  temp;  
   double  wind;
} ;
void funstu(weather w)
{  
    w.temp=15;
    w.wind=2.3;
    cout << " fun:\nTemp = " << w.temp << endl ;
    cout << "Wind = " << w.wind << endl ;
}
int main()
{  
    weather  day ;
    day.temp = 10.5 ;
    day.wind = 3.1 ;
    cout << " 1:\nTemp = " << day.temp << endl ;
    cout << "Wind = " << day.wind << endl ;
    funstu(day);
    cout << " 2:\nTemp = " << day.temp << endl ;
    cout << "Wind = " << day.wind << endl ;
}
  • 传引用参数
# include <iostream>
using namespace std ;
struct  weather
{  double  temp; 
   double  wind;  
 } ;
void funstu(weather  &w)
{ 
    w.temp=15;
    w.wind=2.3;
    cout << " fun:\nTemp = " << w.temp << endl ;
    cout << "Wind = " << w.wind << endl ;
}
int main()
{  weather  day ;
    day . temp = 10.5 ;
    day . wind = 3.1 ;
    cout << " 1:\nTemp = " << day.temp << endl ;
    cout << "Wind = " << day.wind << endl ;
    funstu(day);
    cout << " 2:\nTemp = " << day.temp << endl ;
    cout << "Wind = " << day.wind << endl ;
}
  • 传地址的方式
# include <iostream>
using namespace std ;
struct  weather
{  double  temp;   
   double  wind;
 } ;
void funstu(weather  *w)
{ 
    w->temp=15;
    w->wind=2.3;
    cout << " fun:\nTemp = " << w->temp << endl ;
    cout << "Wind = " << w->wind << endl ;
}
int main()
{  
    weather  day ;
    day . temp = 10.5 ;
    day . wind = 3.1 ;
    cout << " 1:\nTemp = " << day.temp << endl ;
    cout << "Wind = " << day.wind << endl ;
    funstu(&day);
    cout << " 2:\nTemp = " << day.temp << endl ;
    cout << "Wind = " << day.wind << endl ;
}

结果为:
在这里插入图片描述

5.4 结构数组

数组的元素类型为结构类型时,称为结构数组。
例如

  struct S_type
  { 
     int a; 
     double x; 
  };
S_type S_ary[10];

S_ary是一个有10个元素的数组,元素类型是S_type。
数组的每一个元素包含两个数据成员。

    S_ary[0].a      S_ary[0].x
	S_ary[1].a      S_ary[1].x
	……
	S_ary[9].a      S_ary[9].x

例:对结构数组以某一成员作关键字排序

# include <iostream>
using namespace std ;
struct  person	// 结构定义
{  char  name[10] ; 
   unsigned  int  id; 
   double  salary ; 
 } ;
person  allone[6] ;	// 结构数组声明
int main()
{  int  i ; 
   person  temp ;		// 结构变量声明
   for ( i = 0 ;  i < 6 ;  i ++ )	// 输入数据
     {
        cout << i << ": name: " ; cgets ( allone[i].name ) ;//cgets接收空格输入
        cout << "id: " ;          cin >> allone[i].id ;
        cout << "salary: " ;      cin >> allone[i].salary ;
        cout << endl ;
     } ;
cout << "Sort:\n" ;
  for  ( i=1 ;  i < 6 ;  i ++ )		// 以成员salary作关键字排序
  {  for ( int  j = 0 ;  j <= 5-i ;  j ++ )
     {
      if  ( allone[j].salary > allone[j+1].salary  )     // 结构变量的整体交换 
       { 
        temp = allone[j] ;  
        allone[j] = allone[j+1] ;  
        allone[j+1] = temp ;
        }
     }
  }
  for ( i = 0 ;  i < 6 ;  i ++ )		// 输出排序后数据
      cout << allone[i].name << '\t' << allone[i].id << '\t' << allone[i].salary << endl ;
}

实际上,这样做会产生问题。
问题: 结构变量的整体交换降低了排序效率
解决: 使用索引机制, 建立结构指针数组
方法 :

    1. 建立索引数组
    1. 以关键字作依据进行数据比较,移动索引
    1. 通过索引访问数据

使用索引排序

  1. 建立索引数组
  2. 排序(冒泡法)
    在这里插入图片描述
    pa [ 0 ]->salary < pa [ 1 ] -> salary
    即 allone[0] . salary < allone[1] . salary
    不交换
    pa [ 1 ]->salary > pa [ 2 ] ->salary
    即 allone[1] . salary > allone[2] . salary
    pa [ 1 ] 与 pa [ 2 ]交换
    一次类推。
    最后输出排序结果
    在这里插入图片描述
	:
  person * pa[6] = { &allone[0] , &allone[1] , &allone[2] ,
		     &allone[3] , &allone[4] , &allone[5] };
  person * temp;for  ( i = 1 ;  i < 6 ;  i + + )
  {  for ( int  j = 0 ;  j <= 5 - i ;  j + + )
     {  if  ( pa [ j ] -> salary > pa [ j+1 ] -> salary )
       {  temp = pa [ j ] ; 	 pa [ j ] = pa [ j+1 ] ;	 pa [ j+1 ] = temp ;
       }
     }
  }

5.5 链表

在这里插入图片描述

1.动态链表存储

在这里插入图片描述
结点数据类型

struct node
{ 
   char name[20] ;  
   double salary ;  
   node * next ;  
} ; 

单向链表结点数据类型

struct node
{ 
   dataType data ;  
   node * next ;  
} ; 

2.建立和遍历链表

建立链表的过程:

生成头结点;
while(未结束)
{ 
  生成新结点;
  把新结点插入链表;
}
struct node
{ 
	int data ;
    node * next ; 
} ;  
node * head ;//头指针  
node * CreateList()
{ 
  node * s, * p ; //声明局部量 
  s = new node ;//建立第一个结点
  cin >> s->data ;
  head = NULL ;//链表头指针初始化
  while ( s->data != 0 )//插入新结点
  { 
    if ( head == NULL ) head = s ;
      else  p->next = s ;
    p = s ;
    s = new node ;
    cin >> s->data ;
  }
  p -> next = NULL ;
  delete  s ;//释放值为0的结点
  return ( head ) ;
}

3.插入结点

  1. 在表头插入结点
 s -> next = head ;
 head  = s ;
  1. p之后插入s
 s -> next = p -> next ;
 p -> next  = s ;
  1. p之前插入s

方法一 知道前驱结点

s -> next = p ;
q -> next  = s ;

方法二 尾插交换数据

s -> next = p -> next ;
p -> next  = s ;
t = p -> data ;
p -> data  = s-> data;
s-> data = t ;

例:用插入法生成一个有序链表
算法思路:

if (表空) 生成链表的第一个结点;
else if ( num < head->data ) 
	把 num 插入头结点之前; 	//此时num是最小值
       else 
              {  if (找到) 找第一个大于num的结点*p;
	    把num插入*p之前;
	}
        else 把num插入表尾;	//此时num是最大值
#include<iostream>
using namespace std ;
struct list
{ int data ; 
  list * next ; 
} ;  
list * head ;  
list * insert(int num )
{ list * s, *p, *q ;
  s = new list ;
  s->data = num ;  s->next = NULL ;
  if ( head == NULL )	
    { head = s ;   return( head ) ; }
  if ( head->data > s->data ) 
   { s->next = head ;   head = s ;
      return ( head ) ;
   }
  for ( q = head, p = head->next ;  p ; q = p, p = p->next )
   if ( p->data > s->data )
    { s->next = p ;      q->next = s ;
      return ( head ) ;
    }
  q->next = s ;
  return ( head ) ;
}
void showlist( const list * head )
{ cout << "now the items of list are: \n" ;
  while( head )
  { cout << head->data << '\t';    head = head->next ;  }
  cout << endl ;
}
 int main()
{ int k ;
  head = NULL ;
  cin >> k ;
  while( k != 0 )
    { head = insert(k) ;    cin >> k ; }
  showlist( head ) ;
} 

4.删除结点

  1. 删除头结点
p = head ;
head  = head->next ;
delete p ;
  1. 删除结点 *p
 q->next  = p->next ;
delete p ;

这里给出一个著名问题:约瑟夫(Jonsephus)问题

n个人围成一个环,从第i个开始,由1至interval不断报数,凡报到interval的出列,直到环空为止。

例:
n=8,i=1,interval=3,则输出序列为:
3 6 1 5 2 8 4 7
对数据操作

找开始报数位置 ;
	while ( 表结点数 >1 )
	{ for ( 1 To interval )
	      { 结点计数;
	         输出,删除第 interval 个结点 ;
	      }
	 } 	
	输出,删除最后一个结点 ; 
// 例  约瑟夫问题 
#include <iostream>
#include <iomanip>
 using namespace std ;
struct Jonse { int code ;  Jonse *next ; } ;//声明结构类型
Jonse * Create( int ) ;
void ShowList( Jonse * ) ;
void Out( Jonse *, int, int ) ;
int main()
{ Jonse * head ;  
  int num , val , beg ;
  cout << "\nplease input the number of total:\n" ;
  cin >> num ;  //输入人数
  head = Create(num) ;  
  ShowList(head) ; 
  cout << "\nplease input the code of begin:\n" ;  
  cin >> beg ; //输入开始报数的位置
  cout << "\nplease input interval of counting:\n" ;  
  cin >>  val ;  //输入报数间隔
  cout << "the new list is:\n" ;  
  Out( head, beg, val ) ;  以约瑟夫方式输出链表
}
Jonse * Create ( int n )//创建n个结点的单向链表
{
 Jonse *h, *p ;  
 h = new Jonse ;建立第一个结点
 p = h ;  
 for ( int i = 1 ;  i<=n ;  i++ )//建立后续结点
  { p->code = i ;  //向结点赋序号
    if (i<n){ p->next = new Jonse ;   p = p->next ;  }//在表尾建立新结点
  }
 p->next = h ; //构成链环
 return h ;  
}
void ShowList(Jonse *h) 
{ Jonse *p ;   p = h ;  
  do { cout << p->code << '\t' ;   p = p->next ; 
       } while ( p!=h ) ;  
}
void Out(Jonse *h, int i, int d)
{ Jonse *p,*q ; //建立双跟踪指针
  int k ;   p = h ; //从表头开始操作
  for( q = h ;  q->next != h ;  q = q->next ) ; //寻找p的前驱q
  for( k = 1; k<i; k++) { q = p ;   p = p->next ;  }//寻找开始位置
  while( p != p->next )//处理链环直至剩下一个结点 
  { for ( k = 1 ; k<d ; k++ ) { q = p ;   p = p->next ;  }//报数
    cout << p->code << '\t' ; //输出报到结点 
    q->next = p->next ;//删除结点 
    delete p ;
    p = q->next ;//移动指针 
  }
 cout << p->code << endl ;//输出、删除最后一个结点
 delete p ;
}

小结

在这里插入图片描述

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值