C语言间隔删除数组的探究

最近整理的一些数据操作函数

#include <stdlib.h>
#include <stdio.h>

#define SIZE2 1000
#define STEP 2
#define DELFLAG (SIZE2 + 1)
#define MaxCount 1000
#define null 0
#define   FST_ROUND_LEFT   (MaxCount - MaxCount/(STEP+1))
#define   ARRAYSIZE (MaxCount+FST_ROUND_LEFT)
// 在第一轮里未删除的数,应该保存未删除数据的下标
// 以后待删除的数已经都是下标了,应该保存其值,最后删除的数就是其原始数的下标了
typedef struct _node
{
int data;
int index;
struct _node *next;
}node,pNode;

const int size = 1000;

void test1(void);
void test2(void);
void test3(void);
void test4(void);
void test5(void);
void test6(void);
void test7(void);
void test8(void);
void test9(void);

void test9(void)
{
    printf("this is hello world\n");
}

int main(void)
{
    test1();
    test2();
    test3();
    test4();
    test5();
    test6();
    test7();
    test8();
    test9();
    return 0;
}

void test1(void)
{
    int arr[size];
    int currentSize = size; //指示当前数组还剩于的数组个数,如果为1删除完毕
    int count = 0; //计数用;
    int k = 0;
    //赋值1000个
    for(;k<size;k++)
    {
	arr[k] = k;
    }

    //i用%循环计数,终止条件是删除的只剩下一个数
    int i = 0;
    for(;(i<size)&&(currentSize!=1);i = (i+1)%size)
    {
	if(arr[i]!=-1)//-1表示已经删除的标志,未删除则计数,已删除则循环下一位
	{
	    //按照计数间隔计数,达到间隔时删除数据
	    if(count>=0 && count < 2 )
	    {
		count++;
	    }
	    else if(count ==2)//间隔为二
	    {
		arr[i] = -1; //元素做上标记表示已删除
		currentSize--;//有效元素减1
		count=0;//并将计数值归零;
	    }
	}
    }
    int j = 0;
    for(;j < size;j++)//显示最后结果
    {
	if(arr[j]!= -1)
	{
	    printf("test1结果是: %d \n",j);
	    break;
	}
    }
}

#if 0
#include <iostream> 

using namespace std;    

struct Node  {      
int value;      
bool isDeleted;  
};  
int main()  
{      
    Node a[1001];      
    int i,n = 1000;      
    for (i = 0; i < n; ++i)      
    {          
	a[i].value = i;          
	a[i].isDeleted = false;                
    }	      
	int cur = 0,count,num = n;      
	while (num != 1)      
	{          
	    count = 0;          
	    while (count != 2)          
	    {              
		cur = (cur+1)%n;              
		if (a[cur].isDeleted == false)              
		{                  
		    count++;              
		}          
	    }          
	    a[cur].isDeleted = true;         
	    // cout<<a[cur].value<<"  ";          
	    while (a[cur].isDeleted != false)          
	    {              
		cur = (cur+1)%n;          
	    }          
		--num;      
	}      
	cout<<endl;      
	cout << cur << endl;      
	system("pause");      
	return 0;  
	
}

#endif


void test2(void)
{
        int arr[SIZE2];
	int currentSize = SIZE2;//为1时表示删除完毕
	int count = 0;
	int i = 0;
	int lastindex = 0;
	int lastvalue = 0;
	int k = 0;
	for(;k<SIZE2;k++)
	{
	    arr[k] = k;
	}
	while(currentSize != 0)
	{
	    if(arr[i] != DELFLAG)
	    {
		if(count++ == STEP)
		{
		    lastindex = i;
		    lastvalue = arr[i];
		    arr[i] = DELFLAG;
		    currentSize--;
		    count = 0;
		}
	    }
	    i = (i+1)%SIZE2; 
	}
	printf("test2最后删除的数的原始坐标: %d \n",lastindex);
	//printf("最后删除的数是 : %d\n",lastvalue);
}


void test3(void)
{
    int arr[SIZE2];
    int i = 0;
    for(;i < SIZE2;i++)
    {
	arr[i] = i;
    }
    int j = 0;
    int count = 0;
    while(count < SIZE2 - 1)//999保留最后一个为删除的数
    {
	while(arr[j%1000] == DELFLAG)
	{
	    j = (++j)%SIZE2;
	}
	j = (++j)%SIZE2;//第一个未访问的数
	while(arr[j%1000]== DELFLAG)
	{
	    j = (++j)%1000;
	}
	j = (++j)%1000;   //第二个未访问的数

	while(arr[j%1000]== DELFLAG)
	{
	    j = (++j)%1000;
	}
	arr[j] = DELFLAG; // 删除第三个数
	++count;
    }
    while(arr[j]==DELFLAG) // 扫描最后一个未删除的数
    j = (++j)%1000;
    printf("test3最后的数的下标 : %d\n",j);
}


void test4(void)
{
    int arr[SIZE2];
    int i =0;
    for(;i <SIZE2;i++)
    {
	arr[i] = i;
    }
    int j = 0;
    int count = 0;
    int stepcounter = 0;
    int delindex = 0;
    while(count < SIZE2)  //删除总次数
    {
	//删除一个
	while(stepcounter<=STEP)//寻找第三个未访问的数
	{
	while(arr[j%SIZE2] == DELFLAG)//剔除已删除的
	j = (++j)%SIZE2;
	j = (++j)%SIZE2;//(++j)中的j为一个未访问的的数,而非保存后的j,故下面delindex = j - 1;
	stepcounter++;
	}
	//delindex = j - 1;//由于上面j加1后可能溢出从头开始了,因此先加SIZE
	delindex = (j + SIZE2 - 1)%SIZE2;//保存当前删除数的下标
	stepcounter = 0;
	arr[delindex] = DELFLAG; //删除第三个未访问的数
	++count;
    }
    printf("test4下标是:%d\n",delindex);
}


void test5(void)
{
    int arr[SIZE2];
    int currentSize = SIZE2;
    int count = 0;
    int lastdel = 0;
    int i = 0;
    int k = 0;
    for(;k<SIZE2;k++)
    {
	//arr[k] = SIZE2 - k;
	arr[k] = k;
    }
    
    while(currentSize != 0)
    {
	if(arr[i] >= 0)//当前数大于等于0,未删除,删除的话则看下一个
	{
	    //按照计数间隔来计数,达到计数间隔删除数据
	    if(count++ == STEP)
	    {
		lastdel = i;
		arr[i] = -1;//将此数的最高位置1,此时其为负数,表示删除
		//arr[i] = DELFLAG;
		currentSize--; //有效元素减1;
		count = 0;//计数值归零
	    }
	}
	i = (i + 1)%SIZE2;
    }
    printf("test5下标是:  %d\n",lastdel);
//    printf("最后的删除的数:  %d\n",i);
    //清除最高位的1,恢复原始数组
    for(k = 0;k < SIZE2;k++)
    {
	arr[k] &= ~DELFLAG; // 注意这种清除方式的移植性高到爆 
    }
}

void test6(void)
{
    int   list[2*MaxCount];                               //多分配一倍的空间,用来放循环数据  
    int   i,index=0,tail,delcount=0;  
    
   for(i=0;i<MaxCount;i++)   
   {
   list[i]=i;     //初始化,存放0~999  
   }	      
   tail=MaxCount; //list[tail]用来存放不删除的数据  
   while(delcount<MaxCount) //删除1000个就退出  
   {  
	 //第三个数据删除,此处有误,因为index循环时重新赋值了,导致((index %3)的错误 
	if((index %3)==2)
	{  
	    delcount++;  
	    //       	printf("%d\t",list[index]);  
	}  
	else       //前两个数据放到队列末尾,  
	{  
	    list[tail]=list[index];  
	    tail=(tail+1) % (2*MaxCount);  
         }  
	 index=(index+1) % (2*MaxCount);//步近 
   }
   printf("test6下标是:%d\n",index);
   return; 
   // 缺点,不能输出最后一个删除数的原始下标,只能输出其值,因为该数组可能是随机的,下标与值可能不一致
  // 此题的考点就在于删除过程中拷贝了数据后如何保存原始位置,否则的话我每次删除一个值后,将后面所有的数前移,然后再删,没有意义了
}

void test7(void)
{
int   list[2*MaxCount]; //多分配一倍的空间,用来放循环数据  
int   i,index=0,counter=0,tail,delcount=0; 
int    lastdel = 0;
 
 for(i=0;i<MaxCount;i++)   list[i]=i;     //初始化,存放0~999  
  
  tail=MaxCount; //list[tail]用来存放不删除的数据  
   
   while(delcount<MaxCount) //删除1000个就退出  
   {  
   counter++;
   if(counter==3) //第三个数据删除,单独计数,不用index  
   {  
   delcount++;
   counter = 0;
   lastdel = list[index]; 
   //printf("%d\t",list[index]);  
   }  
   else       //前两个数据放到队列末尾,  
   {  
   list[tail]=list[index];  
   tail=(tail+1)%(2*MaxCount);  
   }  
   index=(index+1)%(2*MaxCount);//步近  
   }  
    
    printf("test7结果哦是:%d\n",lastdel);
}
void test8(void)
{
    int   list[ARRAYSIZE];  
    //多分配一倍的空间,用来放循环数据,其实多分配\\FST_ROUND_LEFT即可了,即 list[FST_ROUND_LEFT+MaxCount],后面的循环值要改下 
    int   i,index=0,counter=0,tail,delcount=0; 
    int           lastdel = 0, firstround = 1;
    for(i=0;i<MaxCount;i++)  
    list[i]=MaxCount - 1 - i;     //初始化,存放999~0,此时下标和数是非对应的  
    tail=MaxCount; //list[tail]用来存放不删除的数据下标或已经保存的下标  
    while(delcount<MaxCount) //删除1000个就退出  
    {  
        counter++;
       if(counter==3) //第三个数据删除  
       {  
           delcount++;
           counter = 0;
           if(firstround)
           lastdel=index;
           else
           lastdel=list[index];
           //printf("%d\t",list[index]);  
       }  
       else       //前两个数据放到队列末尾,  
      {
           if(firstround)
           list[tail]=index;
           else
           list[tail]=list[index];
           if(firstround)
           if(tail - MaxCount == FST_ROUND_LEFT - 1)
            {
               firstround = 0;       // 清除第一轮标志,以后保存值(保存后的下标)
//               printf("%d\n",FST_ROUND_LEFT);
           }
	   tail=(tail+1)%(ARRAYSIZE);  
	}  
    index=(index+1)%(ARRAYSIZE);//步近  
    }  
    printf("test8结果的是:%d\n",lastdel);
}


#if 0

void test9(void)
{
    int arr[SIZE2];
    int i = 0;
    for (;i<SIZE2;++i)
    {
	arr[i]=SIZE2-i; // 实际情况可能是随机
    }
    pNode head=(pNode)malloc(sizeof(node));
    head->data=arr[0];
    head->index=0;
    head->next=null;
    pNode p=head;
    for(i=1;i<1000;i++)
    {
	pNode tmp=(pNode)malloc(sizeof(node));
	tmp->data=arr[i];
	 tmp->index=i;
	tmp->next=null;
	head->next=tmp;
	head=head->next;
    }
    head->next=p;
    while(p!=p->next) // p指向自己时,循环链表只剩一个元素了
    {
	p->next->next=p->next->next->next;
	p=p->next->next;
    }
    // 存在内存泄漏
     printf("test9结果是: %d\n",p->data);
    //cout<<p->index<< ' '<< p->data<<endl;
}

#endif


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

telllong

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值