您的位置:

首页 >

365体育官网备用网址 >

365体育官网备用网址:如何在C++中建立一个顺序表 >

365体育官网备用网址:如何在C++中建立一个顺序表

2016-07-05 02:44:20

分类:365体育官网备用网址

准备数据复制代码 代码如下:#define MAXLEN 100 //定义顺序表的最大长度struct DATA{ char key[10]; //结点的关键字  char name[20]; int age;};struct SLType //定义顺序表结构 { DATA ListData[MAXLEN+1];//保存顺序表的结构数组 int ListLen;   //顺序表已存结点的数量 }; 定义了顺序表的最大长度MAXLEN、顺序表数据元素的类型DATA以及顺序表的数据结构SLType。在数据结构SLType中,Listen为顺序表已存结点的数量,也就是当前顺序表的长度,ListData是一个结构数组,用来存放各个数据结点。我们认为该顺序表是一个班级学生的记录。其中,key为学号,name为学生的名称,age为年龄。因为数组都是从下标0开始的,为了使用方便,我们从下标1开始记录数据结点,下标0的位置不可用。初始化顺序表在使用顺序表之前,首先创建一个空的顺序表,也就是初始化顺序表。这里,在程序中只需设置顺序表的结点数量ListLen为0即可。这样,后面需要添加的数据元素将从顺序表的第一个位置存储。示例代码:复制代码 代码如下:void SLInit(SLType * SL) //初始化顺序表{ SL->Listlen=0; } 计算线性表的长度计算线性表的长度也就是计算线性表中结点的个数,由于我们在SLType中定义了ListLen来表示结点的数量,所以我们只需要获得这个变量的值即可。复制代码 代码如下:int SLLenght(SLType *SL){ return(SL->ListLen); //返回顺序表的元素数量 } 插入结点插入节点就是在线性表L的第i个位置上插入一个新的结点,使其后的结点编号依次加1。这时,插入一个新节点之后,线性表L的长度将变为n+1。插入结点操作的难点在于随后的每个结点数据都要向后移动,计算机比较大,示例代码如下:复制代码 代码如下:int SLInsert(SLType *SL,int n,DATA data){ int i; if(SL->ListLen>=MAXLEN) //顺序表结点数量已超过最大数量 {  cout<<"顺序表已满,不能插入结点!"<<endl;  return 0;   //返回0表示插入不成功  }  if(n<1||n>SL->ListLen) //插入结点的序号不合法  {  cout<<"插入序号错误!"<<endl;  return 0; } for(i=SL->ListLen;i>=n;i--) //将顺序表中的数据向后移动 {  SL->ListData[i+1]=SL->ListData[i]; } SL->ListData[n]=data; SL->ListLen++; return 1; }在程序中首先判断顺序表结点数量时候已超过最大数量,以及插入点的序号是否正确。前面条件都瞒住以后,便将顺序表中的数据向后移动,同时插入结点,并更新结点数量ListLen。追加结点追加结点就是在顺序表的尾部插入结点,因此不必进行大量数据的移动,代码实现与插入结点相比就要简单的多。复制代码 代码如下:int SLAdd(SLType * SL,DATA data){ if(SL->ListLen>=MAXLEN) {  cout<<"顺序表已满,不能再添加结点了!"<<endl;  return 0; }  SL->ListData[++SL->ListLen]=data; return 1;}删除结点删除结点就是删除线性表L中的第i个结点,使得其后的所有节点编号依次减1.这是,删除一个结点之后,线性表L的长度将变为n-1。删除结点和插入结点类似,都需要进行大量数据的移动。复制代码 代码如下:int SLDelete(SLType *SL,int n) //删除顺序表中的数据元素{ int i; if(n<1||n>SL->ListLen) //删除结点的序号不合法  {  cout<<"删除序号错误!"<<endl;  return 0; } for(i=n;i<SL->ListLen;i++)//将顺序表中的数据向前移动  {  SL->ListData[i]=SL->ListData[i+1];  }  SL->ListLen--;   //顺序表元素数量减1  return 1;    //成功删除返回1 } 查找结点查找节点就是在线性表L中查找值为x的结点,并返回该节点在线性表L中的位置。如果在线性表中没有找到值为x的结点,则返回一个错误标志。根据x的类型不同,查找结点可以分为:按照序号查找结点对于一个顺序表,序号就是数据元素在数组中的位置,也就是数组的下标标号。按照序号查找结点是顺序表查找结点最常用的方法,这是因为顺序表的存储本身就是一个数组,示例代码如下:复制代码 代码如下:DATA * SLFindByNum(SLType *SL,int n)//根据呼号返回数据元素{ if(n<1||n>SL->ListLen)   //查询结点的序号不合法  {  cout<<"查询序号错误!"<<endl;  return 0; } return &(SL->ListData[n]); } 按照关键字查找结点关键字可以是数据元素中的任意一项。这里以key关键字为例进行介绍,例如,可以通过key查找学生的信息。示例代码如下:复制代码 代码如下:int SLFindByCont(SLType * SL,char *key)//按关键字查询结点 { int i; for(i=1;i<=SL->ListLen;i++) {  if(strcmp(SL->ListData[i].key,key)==0)//如果找到结点   {   return i;  } } return 0;      //在整个表中都没有找到,返回0 } 显示所有的结点示例代码如下:复制代码 代码如下:void SLALL(SLType *SL){ int i; for(i=1;i<SL->ListLen;i++) {  cout<<"key:"<<SL->ListData[i].key<<endl;  cout<<"name:"<<SL->ListData[i].name<<endl;  cout<<"age:"<<SL->ListData[i].age<<endl;  cout<<"============================="<<endl;  }} 顺序表操作完整示例:基本上就是把上面的函数放到一块,集中展示了一下功能,代码有些长,请耐心阅读^.^复制代码 代码如下:#include<iostream>#include<string>using namespace std;#define MAXLEN 100 //定义顺序表的最大长度/**************顺序表的定义部分*****************/ struct DATA{ string key; //结点的关键字  string  name; int age;};struct SLType //定义顺序表结构 { DATA ListData[MAXLEN+1];//保存顺序表的结构数组 int ListLen;   //顺序表已存结点的数量 }; /************顺序表的初始化函数*****************/ void SLInit(SLType * SL) //初始化顺序表{ SL->ListLen=0; } /***********计算线性表的长度*******************/int SLLenght(SLType *SL){ return(SL->ListLen); //返回顺序表的元素数量 } /*********插入结点*******************************/int SLInsert(SLType *SL,int n,DATA data){ int i; if(SL->ListLen>=MAXLEN) //顺序表结点数量已超过最大数量 {  cout<<"顺序表已满,不能插入结点!"<<endl;  return 0;   //返回0表示插入不成功  }  if(n<1||n>SL->ListLen) //插入结点的序号不合法  {  cout<<"插入序号错误!"<<endl;  return 0; } for(i=SL->ListLen;i>=n;i--) //将顺序表中的数据向后移动 {  SL->ListData[i+1]=SL->ListData[i]; } SL->ListData[n]=data; SL->ListLen++; return 1;     //成功插入,返回1 }/***********************追加结点*************************/ int SLAdd(SLType * SL,DATA data){ if(SL->ListLen>=MAXLEN) {  cout<<"顺序表已满,不能再添加结点了!"<<endl;  return 0; }  SL->ListData[++SL->ListLen]=data; return 1;}/***********************删除结点*************************/ int SLDelete(SLType *SL,int n) //删除顺序表中的数据元素{ int i; if(n<1||n>SL->ListLen) //删除结点的序号不合法  {  cout<<"删除序号错误!"<<endl;  return 0; } for(i=n;i<SL->ListLen;i++)//将顺序表中的数据向前移动  {  SL->ListData[i]=SL->ListData[i+1];  }  SL->ListLen--;   //顺序表元素数量减1  return 1;    //成功删除返回1 } /*******************按照序号查找结点********************/DATA * SLFindByNum(SLType *SL,int n)//根据序号返回数据元素{ if(n<1||n>SL->ListLen)   //查询结点的序号不合法  {  cout<<"查询序号错误!"<<endl;  return 0; } return &(SL->ListData[n]); } /*******************按照关键字查找结点********************/DATA *SLFindByCont(SLType * SL,string name)//按关键字查询结点 { int i; for(i=1;i<=SL->ListLen;i++) {  if(SL->ListData[i].name==name)//如果找到结点   {   return &(SL->ListData[i]);  } } return 0;      //在整个表中都没有找到,返回0 } /*******************显示所有的结点********************/void SLALL(SLType *SL){ int i; for(i=1;i<=SL->ListLen;i++) {  cout<<"key:"<<SL->ListData[i].key<<",name:"<<SL->ListData[i].name<<",age:"<<SL->ListData[i].age<<endl; }} int main(){ int i; SLType SL; //定义顺序表变量  DATA data; //定义结点保存数据类型变量  DATA *pdata;//定义指向结点的指针变量 string name; cout<<"顺序表操作演示:"<<endl; SLInit(&SL);//初始化顺序表 do { //循环添加结点数据   cout<<"请输入要添加的结点(学号 姓名 年龄):";  cin>>data.key>>data.name>>data.age;  if(data.age)  //若年龄不为0  {   if(!SLAdd(&SL,data))//若添加结点失败    {    break;   //退出循环    }  }else  {   break;  }  }while(1); cout<<"顺序表中的结点顺序为:" <<endl; SLALL(&SL);    //显示所有的结点 cout<<"请输入要取出的结点序号:"; cin>>i; pdata=SLFindByNum(&SL,i);//按序号查找结点 if(pdata) {  cout<<"第"<<i<<"个结点为:key:"<<pdata->key<<",name:"<<pdata->name<<",age:"<<pdata->age<<endl; }  cout<<"请输入要查找的姓名:"; cin>>name; pdata=SLFindByCont(&SL,name); if(pdata) {  cout<<"key:"<<pdata->key<<",name:"<<pdata->name<<",age:"<<pdata->age<<endl; }  cout<<"请输入您要删除的结点的序号:"; cin>>i; if(SLDelete(&SL,i)) {  cout<<"数据删除成功"<<endl;  SLALL(&SL);  } cout<<"请输入您要插入的结点的序号:"; cin>>i; cout<<"请输入第"<<i<<"号结点的key,name,以及age"<<endl; cin>>data.key>>data.name>>data.age; if(SLInsert(&SL,i,data)) {  cout<<"插入数据成功"<<endl;  SLALL(&SL);  }  return 0;}运行界面:

在论坛上看到一位前辈当年的面试题,原话是这样说的“有一次在面试时遇到这样一个问题:不允许调用库函数,也不允许使用任何全局或局部变量编写 int strlen(char *strDest);  ”,无意中看到,自己想了一会儿,没有思路,后来整理了各位牛人的回复,觉得采用递归方法解决这个问题,是一种挺好的办法!于是,稍微写了一下代码,算是开拓视野的一点点积累吧!复制代码 代码如下:#include "stdafx.h"#include <iostream>#include<assert.h>  //使用断言assert的头文件using namespace std;//普通的方法int MyStrlen(const char* strDest){ assert(NULL != strDest); //使用了断言,如果strDest为Null,则终止程序 int i(0); while ('\0' != *strDest)//判断字符串结束的标志,'\0'标识符 {  i ++;  strDest ++; } return i;}//采用递归方式,没有定义新的全局变量和局部变量int MyStrlen2(const char* strDest){ assert(NULL != strDest);//使用了断言,如果strDest为Null,则终止程序 if ('\0' != *strDest) {  return 1 + MyStrlen2(++strDest); } else {  return 0; }}//和上面的方法类似,只不过采用的问号表达式int MyStrlen3(const char* strDest){ assert(NULL != strDest);//使用了断言,如果strDest为Null,则终止程序 return ('\0' != *strDest) ? (1 + MyStrlen3((++strDest))) : 0;  //这时候i++和++i的区别价值体现出来了,strDest++不行,考虑一下为何?}int _tmain(int argc, _TCHAR* argv[]){ char a[] = {"Hello World!"}; cout << MyStrlen(a) << endl; cout << MyStrlen2(a) << endl; cout << MyStrlen3(a) << endl; return 0;}注意 :++strDest不能换成strDest++,  这时候i++和++i的区别价值体现出来了,strDest++不行,考虑一下为何?

最近在学习JBoss下配置Log4j,JBoss的各个版本的目录、JBoss和Log4j集成的文件名每次都有变化,在JBoss5.x下配置了log4j.xml文件,但是配置没有生效。如果你在项目中没有指定使用的log4j的配置文件,最好使用JBoss自带的配置文件,文件名为jboss-log4j.xml。该文件在Jboss容器的目录为:${JBOSS_HOME}\server\default\conf下。下面就是基于log4j默认配置的一些基本修改和注释:<span style="font-size:12px;"><?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false"> <appender name="FILE" class="org.jboss.logging.appender.DailyRollingFileAppender"> <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler" /> <param name="File" value="${jboss.server.log.dir}/server.log" /> <param name="Append" value="true" /> <!-- Rollover at midnight each day --> <param name="DatePattern" value="'.'yyyy-MM-dd" /> <!-- Rollover at the top of each hour <param name="DatePattern" value="'.'yyyy-MM-dd-HH"/> --> <layout class="org.apache.log4j.PatternLayout"> <!-- The default pattern: Date Priority [Category] Message\n --> <param name="ConversionPattern" value="%d %-5p [%c] %m%n" /> <!-- The full pattern: Date MS Priority [Category] (Thread:NDC) Message\n <param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x) %m%n"/> --> </layout> </appender> <appender name="ErrorFile" class="org.jboss.logging.appender.DailyRollingFileAppender"> <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler" /> <param name="File" value="${jboss.server.log.dir}/error.log" /> <param name="Threshold" value="ERROR" /> <param name="Append" value="true" /> <!-- Rollover at midnight each day --> <param name="DatePattern" value="'.'yyyy-MM-dd" /> <layout class="org.apache.log4j.PatternLayout"> <!-- The default pattern: Date Priority [Category] Message\n --> <param name="ConversionPattern" value="%d %-5p [%c] %m%n" /> <!-- The full pattern: Date MS Priority [Category] (Thread:NDC) Message\n <param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x) %m%n"/> --> </layout> </appender> <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler" /> <param name="Target" value="System.out" /> <param name="Threshold" value="INFO" /> <layout class="org.apache.log4j.PatternLayout"> <!-- The default pattern: Date Priority [Category] Message\n --> <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n" /> </layout> </appender> <!-- ================ --> <!-- Limit categories --> <!-- ================ --> <category name="org.hibernate"> <priority value="WARN" /> </category> <category name="org.hibernate.engine.loading.LoadContexts"> <priority value="ERROR" /> </category> <category name="org.jboss"> <priority value="INFO" /> </category> <!-- Limit the org.apache category to INFO as its DEBUG is verbose --> <category name="org.apache"> <priority value="WARN" /> </category> <!-- Limit the jacorb category to WARN as its INFO is verbose --> <category name="jacorb"> <priority value="WARN" /> </category> <!-- Limit the org.jgroups category to WARN as its INFO is verbose --> <category name="org.jgroups"> <priority value="WARN" /> </category> <!-- Limit the org.quartz category to INFO as its DEBUG is verbose --> <category name="org.quartz"> <priority value="INFO" /> </category> <!-- Limit the JSR77 categories --> <category name="org.jboss.management"> <priority value="INFO" /> </category> <!-- Limit the org.jboss.serial (jboss-serialization) to INFO as its DEBUG is verbose --> <category name="org.jboss.serial"> <priority value="INFO" /> </category> <category name="com.liang"> <priority value="DEBUG" /> </category> <!-- ======================= --> <!-- Setup the Root category --> <!-- ======================= --> <root> <appender-ref ref="CONSOLE" /> <appender-ref ref="FILE" /> <appender-ref ref="ErrorFile" /> </root> </log4j:configuration></span> 1. Log4j的几种输出方式org.apache.log4j.ConsoleAppender(控制台)org.apache.log4j.FileAppender(文件)org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定位置)2. 日志记录的优先级优先级从高到低:OFF > FATAL > ERROR > WARN > INFO > DEBUG > ALL。log4j建议使用FATAL、ERROR、WARN、INFO、DEBUG。你可以在<param name="Threshold" value="ERROR" />来配置level,Threshold是一个全局的过滤器,低于其设置的level将不会显示出来。3. 当重启Jboss服务之后是否保存之前的日志<param name="Append" value="true" />,设置为true后,当Jboos重启后当前的log不会消失,即在原有日志上增加新日志。4. 日志输出格式    %c     输出所属类的全名,可在修改为 %c{num} ,num表示输出的范围               如:"org.apache.elathen.ClassName",%c{2}将输出elathen.ClassName                    %d     输出日志时间其格式为 %d{yyyy-MM-dd HH:mm:ss,SSS},可指定格式 如 %d{HH:mm:ss}    %l      输出日志事件发生位置,包括类目名、发生线程,在代码中的行数    %n     换行符    %m    输出代码指定信息,如info("message"),输出message    %p     输出优先级,即 FATAL ,ERROR 等    %r     输出从启动到显示该log信息所耗费的毫秒数    %t     输出产生该日志事件的线程名5. 关于category的配置category指定了以什么开头的包下的类输出的日志的级别。例如:<category name="com.liang"> <priority value="DEBUG" /> <appender-ref ref='FILE'/></category>从上面可以看出,项目中以com.liang包开头的所有类中,凡是DEBUG级别的日志可以输出到FILE中。注意:定义了一个appender-ref=FILE的引用,但是你如果也在root下配置了appender-ref=FILE的引用,会导致输出到FILE的日志会重复。本人碰到过类似的问题。总结以上就是本文关于JBoss5.x下配置Log4j方法介绍的全部内容,希望对大家有所帮助。刚兴趣的朋友可以继续参阅本站:浅谈Spring的两种配置容器、为什么我们要做三份 Webpack 配置文件、Java之Spring注解配置bean实例代码解析等,

1. const变量声明中带有关键词const,意味着不能通过赋值,增量或减量来修改该变量的值,这是显而易见的一点。指针使用const则要稍微复杂点,因为不得不把让指针本身成为const和指针指向的值成为const区别开来、下面的声明表示pf指向的值必须是不变的constfloat *pf;而pf则是可变的,它可以指向另外一个const或非const值;相反,下面的声明说明pf是不能改变的,而pf所指向的值则是可以改变的:float* const pf;最后,当然可以有既不能改变指针的值也不能改变指针指向的值的值的声明方式:constfloat * const pf;需要注意的是,还有第三种放置const关键字的方法:float const * pf; //等价于constfloat * pf;总结就是:一个位于*左边任意位置的const使得数据成为常量,而一个位于*右边的const使得指针本身成为const还要注意的一点是关于const在全局数据中的使用:使用全局变量被认为是一个冒险的方法,它使得数据在程序的任何部分都可以被错误地修改,如果数据是const,那么这种担心就是多余的了不是嘛?因此对全局数据使用const是合理的。然而,在文件之间共享const数据要格外小心,有两个策略可以使用。一个是遵循外部变量的惯用规则,在一个文件进行定义声明,在其他文件进行引用声明(使用关键字extern)。/*file1.c------定义一些全局常量*/const double PI = 3.14159;/*file2.c-----是用在其他文件中定义的全局变量*/extern const dounle PI;另外一个方法是把全局变量放在一个include文件里,这时候需要格外注意的是必须使用静态外部存储类/*constant.h----定义一些全局常量*/static const double PI = 3.14159;/*file1.c-----使用其他文件定义的全局变量*/#include”constant.h”。/*file2.c-----使用其他文件定义的全局变量*/#include”constant.h”如果不使用关键字static,在文件file1.c和file2.c中包含constant.h将导致每个文件都有同一标识符的定义声明ANSI标准不支持这样做(有些编译器确实支持)。通过使用static, 实际上给了每个文件一个独立的数据拷贝,如果文件想使用该数据与另外一个文件通话,这样做就不行了,因为每个文件只能看见他自己的拷贝,然而由于数据是不 可变的,这就不是问题了。使用头文件的好处是不必惦记在一个文件中进行定义声明,在另一个文件中进行引用声明,缺点在于复制了数据,如果常量很大的话,这 就是个问题了。2. volatile限定词volatile告诉编译器,该变量除了可被程序改变意外还可以被其他代理改变。典型的它用于硬件地址和其他并行运行的程序共享的数据。例如,一个地址中可能保存着当前的时钟信息。不管程序做些什么,该地址会随时间改变。另一种情况是一个地址用来接收来自其他计算机的信息;语法同const:volatile int a;//a是一个易变的位置volatile int * pf;//pf指向一个易变的位置把volatile作为一个关键字的原因是它可以方便编译器优化。假如有如下代码:va= x;//一些不使用x的代码vb= x;一个聪明的编译器可能注意到你两次使用了x,但是没有改变它的值,它将把x临时存贮在一个寄存器中,接着,当vb主要x是的时候,它从寄存器而非初始的内存位置得到x的值来节省时间。这个过程被称为缓存。通常缓存是一个好的优化方式,但是如果两个语句中间的其他代理改变了x的值的话就不是这样了。如果没有规定volatile关键字,编译器将无从得知这种改变是否可能发生,因此,为了安全起见,编译器不使用缓存。那是在ANSI以前的情形,现在,如果在声明中没有使用volatile关键字,编译器就可以假定一个值在使用过程中没有修改,它就可以试着优化代码。总而言之,volatile使得每次读取数据都是直接在内存读取而不是缓存。你可能会觉得奇怪,const和volatile可以同时使用,但是确实可以。例如硬件时钟一般不能由程序改变,这使得他成为const,但他被程序以外的代理改变,这使得他成为volatile,所以你可以同时使用它们,顺序是不重要的:const volatile time;volatile表明某个变量的值可能在外部被改变,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。它可以适用于基础类 型如:int,char,long......也适用于C的结构和C++的类。当对结构或者类对象使用volatile修饰的时候,结构或者类的所有成员 都会被视为volatile.该关键字在多线程环境下经常使用,因为在编写多线程的程序时,同一个变量可能被多个线程修改,而程序通过该变量同步各个线程。简单示例:复制代码 代码如下:DWORD __stdcall threadFunc(LPVOID signal){int* intSignal=reinterdivt_cast(signal);*intSignal=2;while(*intSignal!=1)sleep(1000);return 0;}该线程启动时将intSignal 置为2,然后循环等待直到intSignal 为1 时退出。显然intSignal的值必须在外部被改变,否则该线程不会退出。但是实际运行的时候该线程却不会退出,即使在外部将它的值改为1,看一下对应的伪汇编代码就明白了:mov ax,signallabel:if(ax!=1)goto label对于C编译器来说,它并不知道这个值会被其他线程修改。自然就把它cache在寄存器里面。C 编译器是没有线程概念的,这时候就需要用到volatile。volatile 的本意是指:这个值可能会在当前线程外部被改变。也就是说,我们要在threadFunc中的intSignal前面加上volatile关键字,这时 候,编译器知道该变量的值会在外部改变,因此每次访问该变量时会重新读取,所作的循环变为如下面伪码所示:label:mov ax,signalif(ax!=1)goto label 注意:一个参数既可以是const同时是volatile,是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。3.restrict关键字restrict通过允许编译器优化某几种代码增强了计算支持。记住,它只能用于指针,并且表明指针是访问一个数据对象的唯一且初始的方式。为了清楚为何这样做,我们需要看一些例子:复制代码 代码如下:intar[10];int* restrict restar = (int*)malloc(10*sizeof(int));int* par = ar;这里,指针restar是访问malloc分配的内存的唯一而且初始的方式,因此声明为restrict。然而,par指针既不是初始的,也不是访问数组ar中数据的唯一方式,所以不用restrict限定词。现在考虑下面这个更加复杂的例子,其中n是一个int复制代码 代码如下:for(n= 0;n < 10;n++){par[n]+= 5;restar[n]+= 5;ar[n]*= 2;par[n]+= 3;restar[n]+= 3;}知道了restar是访问它所指向的数据的唯一初始方式,编译器就可以用具有同样效果的一条语句来替代包含restar的两个语句restar[n]+= 8;/*可以替换*/然而将两个计算par的语句精简为一个则会导致错误因为在par两次访问数据之间,ar改变了该数据的值。没有关键字restrict,编译器将不得不设想比较糟糕的那一种形式,而使用之后,编译器可以放心大胆的寻找计算的捷径。可以将关键字作为指针型函数参量的限定词使用,这意味着编译器可以假定在函数体内没有其他标志符修改指针指向的数据,因而可以试着优化代码,反之不然。来看一下C99标准下C库中的两个函数,他们从一个位置把字节复制到另一个位置void*memcpy(void* restrict s1,const void* restrict s2,size_t n);void*memmove(void* s1,const void * s2,size_t);memcpy要求两个指针的位置不能重叠,但memmove没有这个要求。把s1,s2声明为restrict意味着每个指针都是相应数据的唯一访问方式,因此他们不能访问同一数据块。这满足了不能有重叠的要求。关键字restrict有两个读者:编译器,它告诉编译器可以自由地做一些优化的假定。另一个读者是用户,他告诉用户仅使用满足restrict要求的参数。一般,编译器没法检查你是否遵循了这一限制,如果你蔑视它,也就是让自己冒险。

java 中基本算法之希尔排序的实例详解希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。基本思想:算法先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组中记录的下标相差d.对每组中全部元素进行直接插入排序, 然后再用一个较小的增量(d/2)对它进行分组,在每组中再进行直接插入排序。当增量减到1时,进行直接插入排序后,排序完成。实例代码:public class ShellSort { /** * 原理:算法先将要排序的一组数按某个增量d(n/2,n为要排序数的个数)分成若干组,每组中记录的 * 下标相差d.对每组中全部元素进行直接插入排序,然后再用一个较小的增量(d/2)对它进行分组, * 在每组中再进行直接插入排序。当增量减到1时,进行直接插入排序后,排序完成。 * * @author 阿信sxq-2015年7月16日 * * @param args */ public static void main(String[] args) { int a[] = { 49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35, 25, 53, 51 }; int d = a.length; int temp = 0; while (true) { d = d / 2; for (int x = 0; x < d; x++) { //对每一个组进行直接插入排序 for (int i = x + d; i < a.length; i += d) { int j = i - d; temp = a[i]; for (; j >= 0 && temp < a[j]; j -= d) { a[j + d] = a[j]; } a[j + d] = temp; } } if (d == 1) { break; } } System.out.println(Arrays.toString(a)); }}以上就是java 算法的希尔排序的讲解,如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

焦点访谈

最新最热的文章

更多 >

COPYRIGHT (©) 2017 Copyright ©2017 365体育在线备用网址 网站地图

联系我们

827570882

扫描二维码分享到微信