1,查找代码.c
2,枚举窗口
3,枚举进程
///////////////////////////内存                 枚举,搜索
///////////////////////////注册表
///////////////////////////服务
///////////////////////////图像
//////////////////////////////////格式集


//////////////////////////////////驱动--------HOOK?
/////////////////////////////////代码,比较,

//1,查找代码.c
/* READ.C: This program opens a file named
 * READ.C and tries to read 60,000 bytes from
 * that file using _read. It then displays the
 * actual number of bytes read from READ.C.
 */

#include <fcntl.h>      /* Needed only for _O_RDWR definition */
#include <io.h>
#include <stdlib.h>
#include <stdio.h>

char buffer[60000];

void main( void )
{
   int fh;
   unsigned int nbytes = 60000, bytesread;

   /* Open file for input: */
   if( (fh = _open( "read.c", _O_RDONLY )) == -1 )
   {
      perror( "open failed on input file" );
      exit( 1 );
   }

   /* Read in input: */
   if( ( bytesread = _read( fh, buffer, nbytes ) ) <= 0 )
      perror( "Problem reading file" );
   else
      printf( "Read %u bytes from file\n", bytesread );

   _close( fh );
}



//2,枚举窗口
 #include <Stdio.h>
#include <Windows.h>

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam);
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam );

int main( int argc, char* argv[] )
{
 HWND m_htest = FindWindow("TXGuiFoundation",NULL);//(1,lpclassname 2,lpwindowsname)
 //   EnumWindows( EnumWindowsProc, NULL );
 if(m_htest==NULL)
 {
  printf("No find something!!\n");
 }
 
 EnumChildWindows(m_htest,EnumChildProc,NULL);
 return 0;
}

HWND m_hwndFind[1000] = {0};
int  m_num = 0;


BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM lParam )
{
 //      if(::GetWindowLong(hWnd,GWL_STYLE) & WS_VISIBLE)
 //   {
 
 char sBuf[256];
 ::GetClassName(hWnd,NULL,254);
// ::GetWindowText(aHwnd,WndCaption,254);
 ::GetWindowText( hWnd, sBuf, 256 );
 printf( "%s\n", sBuf );
 m_hwndFind[m_num] = hWnd;
 m_num++;
 //  }
 return 1;
 
}

 

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
 if(::GetWindowLong(hWnd,GWL_STYLE) & WS_VISIBLE)
 {
  char sBuf[256];
  //获取窗口标题
  ::GetWindowText( hWnd, sBuf, 256 );
  if ( strcmp( sBuf, "我的电脑" ) == 0 )
  {
   //在发现我的电脑时设置其标题为www.a3gs.com
   ::SetWindowText( hWnd, "www.a3gs.com" );
  }
  printf( "%s\n", sBuf );
  m_hwndFind[m_num] = hWnd;
  m_num++;
 }
 return 1;
}

//3,枚举进程

#include <windows.h>
#include <tlhelp32.h>
#include <iostream


#pragma commentlinker"/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
int main( )
{
    
// 现在我们将利用函数CreateToolhelp32Snapshot()获得当前运行进程的快照
    //这个函数返回包含正在运行进程的快照句柄。
    //他的原形是:
    // HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);
    // 我们将dwFlags设为TH32CS_SNAPPROCESS,th32ProcessID置为0。
    
    
HANDLE hSnapShot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    
    
//现在我们获得了所有进程的信息。
    //将从hSnapShot中抽取数据到一个PROCESSENTRY32结构中
    //这个结构代表了一个进程,是ToolHelp32 API的一部分。
    //抽取数据靠Process32First()和Process32Next()这两个函数。
    
    //这里我们仅用Process32Next(),他的原形是:
    //BOOL WINAPI Process32Next(HANDLE hSnapshot,LPPROCESSENTRY32 lppe);
    //我们程序的代码中加入:
    
    
PROCESSENTRY32processInfo=new PROCESSENTRY32;
    
    
// 必须设置PROCESSENTRY32的dwSize成员的值 ;
    
    
processInfo->dwSize=sizeof(PROCESSENTRY32);
    
int index=0;
    
    
//这里我们将快照句柄和PROCESSENTRY32结构传给Process32Next()。
    //执行之后,PROCESSENTRY32 结构将获得进程的信息。我们循环遍历,直到函数返回FALSE。
    
    
printf("****************开始列举进程****************\n");
    
while(Process32Next(hSnapShot,processInfo)!=FALSE)
    {
        
index++;
        
printf("****************** %d ******************\n",index);
        
printf("PID       Name      Current Threads\n");
        
printf("%-15d%-25s%-4d\n",processInfo->th32ProcessID,processInfo->szExeFile,processInfo->cntThreads);
        
        
if(strcmp(processInfo->szExeFile,"XsMenu.exe")==||strcmp(processInfo->szExeFile,"xsmenu.exe")==0)
        {

            
HANDLE hProcess2=OpenProcess(PROCESS_ALL_ACCESS,TRUE,processInfo->th32ProcessID);
            
HEAPENTRY32heapInfo=new HEAPENTRY32;    
               
heapInfo->dwSize=sizeof(HEAPENTRY32);

            
printf("******开始列举Heap****\n");

            
int indexNum=0;
            
while(Heap32Next(heapInfo)!=FALSE)//
            
{
                
indexNum=0;
                
printf("****************** %d ******************\n",index);
                
printf("PID       Name      Current Threads\n");
                
printf("%x-15x%-25s%-4d\n",heapInfo->dwAddress,heapInfo->dwSize,heapInfo->th32ProcessID);
                
            }

    
// 现在我们用函数 TerminateProcess()终止进程:
    // 这里我们用PROCESS_ALL_ACCESS
    
int processID;
    
HANDLE hProcess;
    
hProcess=OpenProcess(PROCESS_ALL_ACCESS,TRUE,processInfo->th32ProcessID);
    
if(hProcess==NULL)
    {
        
printf("Unable to get handle of process: ");
        
printf("Error is: %d",GetLastError());
    }
    
TerminateProcess(hProcess,0);
    
printf("结束成功!!");
//    printf("Enter Process ID to terminate that process:");
//    scanf("%d",&processID);
            /*
            pritnf("******开始列举Module****\n");
            while()//
            {
            }
            
            pritnf("******开始列举Thread****\n");
            while()//
            {
            }
            
            */
            
            
            
        //    TerminateProcess(hProcess2,0);
        
}
        
    }
    
    
CloseHandle(hSnapShot);
    
printf("****************进程列举结束****************\n");
    
    

    


    
    
delete processInfo;








//////////////////
    
char chPath[301];
    
char path[200]= "\\XsMenu.exe";
    
    
    ::
GetCurrentDirectory(300,(LPTSTR)chPath);//得到当前目录
    
strcat(chPath,path);
    
STARTUPINFO si;
    
PROCESS_INFORMATION pi;
    
ZeroMemory( &pisizeof(pi) );
    
ZeroMemory( &sisizeof(si) );
    
si.cb sizeof(si);
    
if(CreateProcess(chPath""NULLNULLFALSE0NULLNULL, &si, &pi))
    {
    }
    
else 
    
{
    }
///////////////////    



    
return 0;

posted @ 2010-08-24 06:57 傅先生 阅读(206) | 评论 (0)编辑 收藏



char 转 int
  ////////
   char m_add_right_Data[6];
  test.Format("正向地址 :");
  for(int t=FIXADD1,int atemp=0;t<FIXADD1+5;t++,atemp++)
  {
   m_add_right_Data[atemp]=bufCopyData[t];  //char 数据问题
   temp.Format("%x ",m_add_right_Data[atemp]);
   test+=temp;
  }
  AfxMessageBox(m_add_right_Data);
     
       int _itemp=atoi(m_add_right_Data);  

 

      DWORD iNum22 = 0;
  //char szNum[32] = {1234};
  iNum22 = atoi(m_add_right_Data);
  mess_context.Format("%s",m_add_right_Data);
  
  //                 nt resultnum=-1;  
  char *pStr2=(char *)mess_context.GetBuffer(0);  
  sscanf(pStr2,"%x",&iNum);
  
  temp.Format("内容地址iNum为 %x",(DWORD*)iNum);  //正解的

  AfxMessageBox(temp);
//_i = atoi(m_add_right_Data);


  test.Format("作为测试: %d",_itemp);
        AfxMessageBox(test);


  mess_context.Format("%s",m_add_right_Data);
  


  //                 nt resultnum=-1;  
  char *pStr=(char *)mess_context.GetBuffer(0);  
  sscanf(pStr,"%x",&iNum);
  temp.Format("内容地址iNum为 %x",(DWORD*)iNum);  //正解的 2
  AfxMessageBox(temp);

 

posted @ 2010-08-20 20:24 傅先生 阅读(189) | 评论 (0)编辑 收藏

  



wchar_t pwchello[500];
  ReadProcessMemory(hProcess,(LPVOID)iNum,&pwchello,800,NULL);
  mess_context.Format("内容为:");
  
  
  //   AfxMessageBox(pwchello);
  CString atemp[50];
  wchar_t *chTest=new wchar_t[pCopyDataStruct->cbData-10];
  
  //  MessageBox(NULL,"","");
  for(int i=0;i<pCopyDataStruct->cbData-10;i++)
  {
   chTest[i]=pwchello[i];
   temp.Format("%X",pwchello[i]);
   mess_context+=temp;
   //              atemp[i]=m_MessageContex[i];
  }  
  MessageBoxW(NULL,chTest,chTest,MB_OK|MB_ICONINFORMATION);




//////////////////
 // wchar_t str[]=L"中国";
 /*
 TCHAR szTest[256] = _T("This is a Test String!");
 CString str(szTest);
 AfxMessageBox(str);
 wchar_t szTest1[256] = _T("Also a test string!");
 str = szTest1;
 AfxMessageBox(str);
 str.Format(_T("%s"), _T("Again!!!It's a test string!"));
 wchar_t *szTest2;
 szTest2 = str.GetBuffer(str.GetLength());
 TRACE1("%s", szTest2);  */
 /*
 setlocale(LC_ALL,"chs");
 wchar_t test[] = L"测试Test";
 wprintf(L"%s",test);
 
   CString temp;
  
  //temp.Format(L"%s",test);
  //AfxMessageBox(str);
  
 MessageBoxW(NULL,test,test,MB_OK|MB_ICONINFORMATION);*/

posted @ 2010-08-20 09:49 傅先生 阅读(221) | 评论 (0)编辑 收藏

``
 
 char s_Buf[256];
 HWND hWnd = ::GetForegroundWindow();//GetActiveWindow(); //'得到活动窗口的句柄 
 ::GetWindowText(hWnd,s_Buf,255);
 AfxMessageBox(s_Buf);

posted @ 2010-08-20 09:42 傅先生 阅读(119) | 评论 (0)编辑 收藏

`

posted @ 2010-08-20 09:41 傅先生 阅读(209) | 评论 (0)编辑 收藏





unresolved external symbol "public: __thiscall cat //错误

:#include <iostream>

using namespace std;

class cat
{ public:
cat(int age){itsage=age;}

~cat();
int getage()const {return itsage;}
private:
int itsage;
};


cat *makecat(int age);

int main()
{

int age=7;
cat * boots=makecat(age);

cout<<"boot is"<<boots->getage()<<"old"<<endl;

delete boots;
return 0;

}

cat *makecat(int age)
{ return new cat(age);

}

新手上路,大家帮我看看是哪里的问题。下面是显示的错误
error LNK2001: unresolved external symbol "public: __thiscall cat::~cat(void)" (??1cat@@QAE@XZ)
Debug/4.exe : fatal error LNK1120: 1 unresolved externals这里专家的回答会让您满意

~cat();
变成
~cat(){}

posted @ 2010-08-16 22:19 傅先生 阅读(198) | 评论 (0)编辑 收藏

VC用ADO访问数据库全攻略 收藏
(由于vchelp网站被封,故将此文章转移至此,愿它能为光大VC编程者一个抛砖引玉的作用)

一、ADO概述
ADO是Microsoft为最新和最强大的数据访问范例 OLE DB 而设计的,是一个便于使用的应用程序层接口。ADO 使您能够编写应用程序以通过 OLE. DB 提供者访问和操作数据库服务器中的数据。ADO 最主要的优点是易于使用、速度快、内存支出少和磁盘遗迹小。ADO 在关键的应用方案中使用最少的网络流量,并且在前端和数据源之间使用最少的层数,所有这些都是为了提供轻量、高性能的接口。之所以称为 ADO,是用了一个比较熟悉的暗喻,OLE 自动化接口。

OLE DB是一组”组件对象模型”(COM) 接口,是新的数据库低层接口,它封装了ODBC的功能,并以统一的方式访问存储在不同信息源中的数据。OLE DB是Microsoft UDA(Universal Data Access)策略的技术基础。OLE DB 为任何数据源提供了高性能的访问,这些数据源包括关系和非关系数据库、电子邮件和文件系统、文本和图形、自定义业务对象等等。也就是说,OLE DB 并不局限于 ISAM、Jet 甚至关系数据源,它能够处理任何类型的数据,而不考虑它们的格式和存储方法。在实际应用中,这种多样性意味着可以访问驻留在 Excel 电子数据表、文本文件、电子邮件/目录服务甚至邮件服务器,诸如 Microsoft Exchange 中的数据。但是,OLE DB 应用程序编程接口的目的是为各种应用程序提供最佳的功能,它并不符合简单化的要求。您需要的API 应该是一座连接应用程序和OLE DB 的桥梁,这就是 ActiveX Data Objects (ADO)。

二、在VC中使用ADO(开发步骤好下:)

1、引入ADO库文件

使用ADO前必须在工程的stdafx.h头文件里用直接引入符号#import引入ADO库文件,以使编译器能正确编译。代码如下所示:

用#import引入ADO库文件

#import "c:\program files\common files\system\ado\msado15.dll"no_namespaces rename("EOF" adoEOF")

这行语句声明在工程中使用ADO,但不使用ADO的名字空间,并且为了避免常数冲突,将常数EOF改名为adoEOF。现在不需添加另外的头文件,就可以使用ADO接口了。

2、初始化OLE/COM库环境
必须注意的是,ADO库是一组COM动态库,这意味应用程序在调用ADO前,必须初始化OLE/COM库环境。在MFC应用程序里,一个比较好的方法是在应用程序主类的InitInstance成员函数里初始化OLE/COM库环境。

BOOL CMyAdoTestApp::InitInstance()
{
if(!AfxOleInit())//这就是初始化COM库
{
AfxMessageBox(“OLE初始化出错!”);
return FALSE;
}

……

}

3、ADO接口简介

ADO库包含三个基本接口:_ConnectionPtr接口、_CommandPtr接口和_RecordsetPtr接口。
_ConnectionPtr接口返回一个记录集或一个空指针。通常使用它来创建一个数据连接或执行一条不返回任何结果的SQL语句,如一个存储过程。使用_ConnectionPtr接口返回一个记录集不是一个好的使用方法。对于要返回记录的操作通常用_RecordserPtr来实现。而用_ConnectionPtr操作时要想得到记录条数得遍历所有记录,而用_RecordserPtr时不需要。

_CommandPtr接口返回一个记录集。它提供了一种简单的方法来执行返回记录集的存储过程和SQL语句。在使用_CommandPtr接口时,你可以利用全局_ConnectionPtr接口,也可以在_CommandPtr接口里直接使用连接串。如果你只执行一次或几次数据访问操作,后者是比较好的选择。但如果你要频繁访问数据库,并要返回很多记录集,那么,你应该使用全局_ConnectionPtr接口创建一个数据连接,然后使用_CommandPtr接口执行存储过程和SQL语句。

_RecordsetPtr是一个记录集对象。与以上两种对象相比,它对记录集提供了更多的控制功能,如记录锁定,游标控制等。同_CommandPtr接口一样,它不一定要使用一个已经创建的数据连接,可以用一个连接串代替连接指针赋给_RecordsetPtr的connection成员变量,让它自己创建数据连接。如果你要使用多个记录集,最好的方法是同Command对象一样使用已经创建了数据连接的全局_ConnectionPtr接口
,然后使用_RecordsetPtr执行存储过程和SQL语句。 

4、使用_ConnectionPtr接口
_ConnectionPtr主要是一个连接接口,取得与数据库的连接。它的连接字符串可以是自己直接写,也可以指向一个ODBC DSN。。 
  _ConnectionPtr pConn;
if (FAILED(pConn.CreateInstance("ADODB.Connection")))
{
AfxMessageBox("Create Instance failed!");
return;
}


CString strSRC;
strSRC="Driver=SQL Server;Server=";
strSRC+="suppersoft";
strSRC+=";Database=";
strSRC+="mydb";
strSRC+=";UID=SA;PWD=";

CString strSQL = "Insert into student(no,name,sex,address) values(3,'aaa','male','beijing')";

_variant_t varSRC(strSRC);
_variant_t varSQL(strSQL);
_bstr_t bstrSRC(strSRC);

if (FAILED(pConn->Open(bstrSRC,"","",-1)))
{
AfxMessageBox("Can not open Database!");
pConn.Release();
return;
}

COleVariant vtOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR);

pConn->Execute(_bstr_t(strSQL),&vtOptional,-1);

pConn.Release();

AfxMessageBox("ok!");

5、使用_RecordsetPtr接口(以连接SQL Server为例)
_RecordsetPtr pPtr;
if (FAILED(pPtr.CreateInstance("ADODB.Recordset")))
{
AfxMessageBox("Create Instance failed!");
return FALSE;
}

CString strSRC;
strSRC="Driver=SQL Server;Server=";
strSRC+="210.46.141.145";
strSRC+=";Database=";
strSRC+="mydb";
strSRC+=";UID=sa;PWD=";
strSRC+="sa";

CString strSQL = "select id,name,gender,address from personal";

_variant_t varSRC(strSRC);
_variant_t varSQL(strSQL);

if(FAILED(pPtr->Open(varSQL,varSRC,adOpenStatic,adLockOptimistic,adCmdText)))
{
AfxMessageBox("Open table failed!");
pPtr.Release();
return FALSE;
}

while(!pPtr->GetadoEOF())
{
_variant_t varNo;
_variant_t varName;
_variant_t varSex;
_variant_t varAddress;

varNo = pPtr->GetCollect ("id");
varName = pPtr->GetCollect ("name");
varSex = pPtr->GetCollect ("gender");
varAddress = pPtr->GetCollect ("address");

CString strNo =(char *)_bstr_t(varNo);
CString strName =(char *)_bstr_t(varName);
CString strSex =(char *)_bstr_t(varSex);
CString strAddress =(char *)_bstr_t(varAddress);

strNo.TrimRight();
strName.TrimRight();
strSex.TrimRight();
strAddress.TrimRight();

int nCount = m_list.GetItemCount();
int nItem = m_list.InsertItem (nCount,_T(""));
m_list.SetItemText (nItem,0,strNo);
m_list.SetItemText (nItem,1,strName);
m_list.SetItemText (nItem,2,strSex);
m_list.SetItemText (nItem,3,strAddress);

pPtr->MoveNext();
}

pPtr->Close();
pPtr.Release();

6、使用_CommandPtr接口
_CommandPtr接口返回一个Recordset对象,并且提供了更多的记录集控制功能,以下代码示例了使用_CommandPtr接口的方法:

代码11:使用_CommandPtr接口获取数据
_CommandPtr pCommand;
_RecordsetPtr pRs;
pCommand.CreateInstance(__uuidof(Command));
pCommand->ActiveConnection=pConn;
pCommand->CommandText="select * from student";
pCommand->CommandType=adCmdText;
pCommand->Parameters->Refresh();
pRs=pCommand->Execute(NULL,NULL,adCmdUnknown);
_variant_t varValue = pRs->GetCollect("name");
Cstring strValue=(char*)_bstr_t(varValue);

6、关于数据类型转换由于COM对象是跨平台的,它使用了一种通用的方法来处理各种类型的数据,
因此Cstring 类和COM对象是不兼容的,我们需要一组API来转换COM对象和C++类型的数据。_vatiant_t和_bstr_t就是这样两种对象。它们提供了通用的方法转换COM对象和C++类型的数据。


发表于 @ 2008年08月28日 08:47:00 | 评论( 3 ) | 编辑| 举报|


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xsc2001/archive/2008/08/28/2841301.aspx

posted @ 2010-08-14 18:49 傅先生 阅读(410) | 评论 (0)编辑 收藏

各种排序算法小结 排序算法是一种基本并且常用的算法。由于实际工作中处理的数量巨大,所以排序算法
对算法本身的速度要求很高。
而一般我们所谓的算法的性能主要是指算法的复杂度,一般用O方法来表示。在后面我将
给出详细的说明。

对于排序的算法我想先做一点简单的介绍,也是给这篇文章理一个提纲。
我将按照算法的复杂度,从简单到难来分析算法。
第一部分是简单排序算法,后面你将看到他们的共同点是算法复杂度为O(N*N)(因为没有
使用word,所以无法打出上标和下标)。
第二部分是高级排序算法,复杂度为O(Log2(N))。这里我们只介绍一种算法。另外还有几种
算法因为涉及树与堆的概念,所以这里不于讨论。
第三部分类似动脑筋。这里的两种算法并不是最好的(甚至有最慢的),但是算法本身比较
奇特,值得参考(编程的角度)。同时也可以让我们从另外的角度来认识这个问题。
第四部分是我送给大家的一个餐后的甜点——一个基于模板的通用快速排序。由于是模板函数
可以对任何数据类型排序(抱歉,里面使用了一些论坛专家的呢称)。

现在,让我们开始吧:

一、简单排序算法
由于程序比较简单,所以没有加什么注释。所有的程序都给出了完整的运行代码,并在我的VC环境
下运行通过。因为没有涉及MFC和WINDOWS的内容,所以在BORLAND C++的平台上应该也不会有什么
问题的。在代码的后面给出了运行过程示意,希望对理解有帮助。

1.冒泡法:
这是最原始,也是众所周知的最慢的算法了。他的名字的由来因为它的工作看来象是冒泡:
#include <iostream.h>

void BubbleSort(int* pData,int Count)
{
int iTemp;
for(int i=1;i<Count;i++)
{
for(int j=Count-1;j>=i;j--)
{
if(pData[j]<pData[j-1])
{
iTemp = pData[j-1];
pData[j-1] = pData[j];
pData[j] = iTemp;
}
}
}
}

void main()
{
int data[] = {10,9,8,7,6,5,4};
BubbleSort(data,7);
for (int i=0;i<7;i++)
cout<<data[i]<<" ";
cout<<"\n";
}

倒序(最糟情况)
第一轮:10,9,8,7->10,9,7,8->10,7,9,8->7,10,9,8(交换3次)
第二轮:7,10,9,8->7,10,8,9->7,8,10,9(交换2次)
第一轮:7,8,10,9->7,8,9,10(交换1次)
循环次数:6次
交换次数:6次

其他:
第一轮:8,10,7,9->8,10,7,9->8,7,10,9->7,8,10,9(交换2次)
第二轮:7,8,10,9->7,8,10,9->7,8,10,9(交换0次)
第一轮:7,8,10,9->7,8,9,10(交换1次)
循环次数:6次
交换次数:3次

上面我们给出了程序段,现在我们分析它:这里,影响我们算法性能的主要部分是循环和交换,
显然,次数越多,性能就越差。从上面的程序我们可以看出循环的次数是固定的,为1+2+...+n-1。
写成公式就是1/2*(n-1)*n。
现在注意,我们给出O方法的定义:

若存在一常量K和起点n0,使当n>=n0时,有f(n)<=K*g(n),则f(n) = O(g(n))。(呵呵,不要说没
学好数学呀,对于编程数学是非常重要的!!!)

现在我们来看1/2*(n-1)*n,当K=1/2,n0=1,g(n)=n*n时,1/2*(n-1)*n<=1/2*n*n=K*g(n)。所以f(n)
=O(g(n))=O(n*n)。所以我们程序循环的复杂度为O(n*n)。
再看交换。从程序后面所跟的表可以看到,两种情况的循环相同,交换不同。其实交换本身同数据源的
有序程度有极大的关系,当数据处于倒序的情况时,交换次数同循环一样(每次循环判断都会交换),
复杂度为O(n*n)。当数据为正序,将不会有交换。复杂度为O(0)。乱序时处于中间状态。正是由于这样的
原因,我们通常都是通过循环次数来对比算法。


2.交换法:
交换法的程序最清晰简单,每次用当前的元素一一的同其后的元素比较并交换。
#include <iostream.h>
void ExchangeSort(int* pData,int Count)
{
int iTemp;
for(int i=0;i<Count-1;i++)
{
for(int j=i+1;j<Count;j++)
{
if(pData[j]<pData[i])
{
iTemp = pData[i];
pData[i] = pData[j];
pData[j] = iTemp;
}
}
}
}

void main()
{
int data[] = {10,9,8,7,6,5,4};
ExchangeSort(data,7);
for (int i=0;i<7;i++)
cout<<data[i]<<" ";
cout<<"\n";
}
倒序(最糟情况)
第一轮:10,9,8,7->9,10,8,7->8,10,9,7->7,10,9,8(交换3次)
第二轮:7,10,9,8->7,9,10,8->7,8,10,9(交换2次)
第一轮:7,8,10,9->7,8,9,10(交换1次)
循环次数:6次
交换次数:6次

其他:
第一轮:8,10,7,9->8,10,7,9->7,10,8,9->7,10,8,9(交换1次)
第二轮:7,10,8,9->7,8,10,9->7,8,10,9(交换1次)
第一轮:7,8,10,9->7,8,9,10(交换1次)
循环次数:6次
交换次数:3次

从运行的表格来看,交换几乎和冒泡一样糟。事实确实如此。循环次数和冒泡一样
也是1/2*(n-1)*n,所以算法的复杂度仍然是O(n*n)。由于我们无法给出所有的情况,所以
只能直接告诉大家他们在交换上面也是一样的糟糕(在某些情况下稍好,在某些情况下稍差)。

3.选择法:
现在我们终于可以看到一点希望:选择法,这种方法提高了一点性能(某些情况下)
这种方法类似我们人为的排序习惯:从数据中选择最小的同第一个值交换,在从省下的部分中
选择最小的与第二个交换,这样往复下去。
#include <iostream.h>
void SelectSort(int* pData,int Count)
{
int iTemp;
int iPos;
for(int i=0;i<Count-1;i++)
{
iTemp = pData[i];
iPos = i;
for(int j=i+1;j<Count;j++)
{
if(pData[j]<iTemp)
{
iTemp = pData[j];
iPos = j;
}
}
pData[iPos] = pData[i];
pData[i] = iTemp;
}
}

void main()
{
int data[] = {10,9,8,7,6,5,4};
SelectSort(data,7);
for (int i=0;i<7;i++)
cout<<data[i]<<" ";
cout<<"\n";
}
倒序(最糟情况)
第一轮:10,9,8,7->(iTemp=9)10,9,8,7->(iTemp=8)10,9,8,7->(iTemp=7)7,9,8,10(交换1次)
第二轮:7,9,8,10->7,9,8,10(iTemp=8)->(iTemp=8)7,8,9,10(交换1次)
第一轮:7,8,9,10->(iTemp=9)7,8,9,10(交换0次)
循环次数:6次
交换次数:2次

其他:
第一轮:8,10,7,9->(iTemp=8)8,10,7,9->(iTemp=7)8,10,7,9->(iTemp=7)7,10,8,9(交换1次)
第二轮:7,10,8,9->(iTemp=8)7,10,8,9->(iTemp=8)7,8,10,9(交换1次)
第一轮:7,8,10,9->(iTemp=9)7,8,9,10(交换1次)
循环次数:6次
交换次数:3次
遗憾的是算法需要的循环次数依然是1/2*(n-1)*n。所以算法复杂度为O(n*n)。
我们来看他的交换。由于每次外层循环只产生一次交换(只有一个最小值)。所以f(n)<=n
所以我们有f(n)=O(n)。所以,在数据较乱的时候,可以减少一定的交换次数。


4.插入法:
插入法较为复杂,它的基本工作原理是抽出牌,在前面的牌中寻找相应的位置插入,然后继续下一张
#include <iostream.h>
void InsertSort(int* pData,int Count)
{
int iTemp;
int iPos;
for(int i=1;i<Count;i++)
{
iTemp = pData[i];
iPos = i-1;
while((iPos>=0) && (iTemp<pData[iPos]))
{
pData[iPos+1] = pData[iPos];
iPos--;
}
pData[iPos+1] = iTemp;
}
}

void main()
{
int data[] = {10,9,8,7,6,5,4};
InsertSort(data,7);
for (int i=0;i<7;i++)
cout<<data[i]<<" ";
cout<<"\n";
}

倒序(最糟情况)
第一轮:10,9,8,7->9,10,8,7(交换1次)(循环1次)
第二轮:9,10,8,7->8,9,10,7(交换1次)(循环2次)
第一轮:8,9,10,7->7,8,9,10(交换1次)(循环3次)
循环次数:6次
交换次数:3次

其他:
第一轮:8,10,7,9->8,10,7,9(交换0次)(循环1次)
第二轮:8,10,7,9->7,8,10,9(交换1次)(循环2次)
第一轮:7,8,10,9->7,8,9,10(交换1次)(循环1次)
循环次数:4次
交换次数:2次
<
本文来自: 站长(http://www.qqcf.com) 详细出处参考:http://study.qqcf.com/web/202/22561.htm

posted @ 2010-08-14 17:16 傅先生 阅读(190) | 评论 (0)编辑 收藏

摘 要:本文对排序中最常见的起泡法进行分析,发现在实现单向起泡的同时可以实现双向起泡,从而实现了冒泡算法的改进,提高了运算速度。

  关键字:程序设计、起泡、双向起泡、VC++

  排序是在程序设计中常碰到的问题,排序算法也有很多种。起泡法是众所周知的排序算法,其原理是每次将相邻两个数进行比较,较大的下沉。其的主程序段如下(用VC++实现):

Void Bubble Sort (int* pData,int Count)
{
 Int iTemp;
 for(int i=1;i<Count;i++)
 {
  For (int j=Count-1;j>=i;j--)
  {
   if(pData[j]<pData[j-1])
   {
    iTemp = pData[j-1];
    pData[j-1] = pData[j];
    pData[j] = iTemp;
   }
  }
 }
}

  我们分析上述程序段可以发现起泡法是从一端开始比较的,第一次循环就是把最小数上升到第一位置,第二次循环就是把第二最小数上升到第二位置。如此循环实现数据的排序。那么我们是否可以找到最小数的同时找到最大数呢?当然可以。方法是在一端起泡时同时在另一端也进行起泡。即反向起泡。下面的程序段实现的是双向起泡:

void Bubble2Sort(int* pData,int Count)
{
 int iTemp;
 int left = 1;
 int right =Count -1;
 int t;
 do
 {
  //正向的部分
  for(int i=right;i>=left;i--)
  {
   if(pData[i]<pData[i-1])
   {
    iTemp = pData[i];
    pData[i] = pData[i-1];
    pData[i-1] = iTemp;
    t = i;
   }
  }
  left = t+1;
  //反向的部分
  for(i=left;i<right+1;i++)
  {
   if(pData[i]<pData[i-1])
   {
    iTemp = pData[i];
    pData[i] = pData[i-1];
    pData[i-1] = iTemp;
    t = i;
   }
  }
  right = t-1;
 }while(left<=right);
}

  分析上面的程序段我们可以发现正向起泡时第一次循环找出了最小数,反向起泡第一次循环找到最大数。很显然在一次循环中即可以找到一个最小的数还可以找到一个最大的数,所以用双向冒泡排序的交换的次数减少了,从而达到了优化起泡法的作用。
文章出处:飞诺网(www.firnow.com):http://dev.firnow.com/course/3_program/vc/vc_js/20100805/526159.html

posted @ 2010-08-14 17:01 傅先生 阅读(352) | 评论 (0)编辑 收藏


/////////////////客端源码/////////////////

#include "iostream"
#include "winsock2.h"
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define Const_BufLength 1024
#define Const_Port 12345

BOOL InitSocket(void);
WSADATA wsaData;
SOCKET m_socket;
sockaddr_in SerAdd,CliAdd;
int main()
{
 
 if(!InitSocket())
 {
  cout<<"套接字初始化出错,即将退出"<<endl;
  WSACleanup();
  system("pause");
  return -1;
 }
 int iLength=sizeof(SerAdd);
 int retval;
 char strSendMsg[Const_BufLength];
 char strRecvMsg[Const_BufLength];


 while(1)
 {
  memset(strSendMsg,0,sizeof(strSendMsg));
  cout<<"请输入要发送的:"<<endl;
  cin>>strSendMsg;
  if(strcmp(strSendMsg,"exit")==0)
  {
   strcpy(strSendMsg,"我是客户端,我要下线了");
   retval=sendto(m_socket,strSendMsg,sizeof(strSendMsg),0,(SOCKADDR*)&SerAdd,sizeof(CliAdd));
   closesocket(m_socket);
   WSACleanup();
   return 0;
  }
  retval=sendto(m_socket,strSendMsg,sizeof(strSendMsg),0,(SOCKADDR*)&SerAdd,sizeof(CliAdd));
  if(retval==SOCKET_ERROR)
  {
   cout<<"发送失败,错误ID为:"<<WSAGetLastError()<<endl;
   cout<<"程序出错,即将退出"<<endl;
   break;
  }
  else if(retval==0)
  {
   break;
  }
  else
  {
   cout<<"发送成功!"<<endl;
  }


  cout<<"等待服务器回应"<<endl;
  memset(strRecvMsg,0,sizeof(strRecvMsg));
  retval=recvfrom(m_socket,strRecvMsg,Const_BufLength,0,(SOCKADDR*)&SerAdd,&iLength);
  if(retval==SOCKET_ERROR)
  {
   cout<<"接受失败,错误ID为:"<<WSAGetLastError()<<endl;
   cout<<"程序出错,即将退出"<<endl;
   break;
  }
  else if(retval==0)
  {
   return 0;
  }
  else
  {
   cout<<"IP:Port\t"<<inet_ntoa(CliAdd.sin_addr)<<":"<<ntohs(CliAdd.sin_port)<<'\t'<<strRecvMsg<<endl;
  }
 }
 closesocket(m_socket);
 WSACleanup();
 return 0;
}


BOOL InitSocket(void)
{
 if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
 {
  cout<<"加载winsock失败,错误ID为:"<<WSAGetLastError()<<endl;
  return FALSE;
 }
 m_socket=socket(AF_INET,SOCK_DGRAM,0);
 if(INVALID_SOCKET==m_socket)
 {
  cout<<"套接字创建失败!错误ID为:"<<WSAGetLastError()<<endl;
  return FALSE;
 }
 SerAdd.sin_family=AF_INET;
 SerAdd.sin_port=htons(Const_Port);
 SerAdd.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
 return TRUE;
}



//////////////////////////服务端源码////////////////////////////
#include "iostream"
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#define Const_BufLength 1024
#define Const_Port 12345

BOOL InitSocket(void);
WSADATA wsaData;
SOCKET m_socket;
sockaddr_in SerAdd,CliAdd;
int main()
{
 
 if(!InitSocket())
 {
  cout<<"套接字初始化出错,即将退出"<<endl;
  WSACleanup();
  system("pause");
  return -1;
 }
 int iLength=sizeof(CliAdd);
 int retval;
 char strSendMsg[Const_BufLength];
 char strRecvMsg[Const_BufLength];


 while(1)
 {
  cout<<"等待客户端回应"<<endl;
  memset(strRecvMsg,0,sizeof(strRecvMsg));

  retval=recvfrom(m_socket,strRecvMsg,Const_BufLength,0,(SOCKADDR*)&CliAdd,&iLength);
  if(retval==SOCKET_ERROR)
  {
   cout<<"接受失败,错误ID为:"<<WSAGetLastError()<<endl;
   break;
  }
  else if(retval==0)
  {
   break;
  }
  else
  {
   cout<<"IP:Port\t"<<inet_ntoa(CliAdd.sin_addr)<<":"<<ntohs(CliAdd.sin_port)<<'\t'<<strRecvMsg<<endl;
  }


  memset(strSendMsg,0,sizeof(strSendMsg));
  cout<<"收到客户消息,直接转发消息"<<endl;
  strcpy(strSendMsg,strRecvMsg);
  if(strcmp(strSendMsg,"exit")==0)
  {
   strcpy(strSendMsg,"收到客户下线的消息,我是服务器,我也下线了");
   retval=sendto(m_socket,strSendMsg,sizeof(strSendMsg),0,(SOCKADDR*)&CliAdd,sizeof(CliAdd));
   closesocket(m_socket);
   WSACleanup();
   return 0;
  }
  retval=sendto(m_socket,strSendMsg,sizeof(strSendMsg),0,(SOCKADDR*)&CliAdd,sizeof(CliAdd));
  if(retval==SOCKET_ERROR)
  {
   cout<<"发送失败,错误ID为:"<<WSAGetLastError()<<endl;
   break;
  }
  else if(retval==0)
  {
   break;
  }
  else
  {
   cout<<"发送成功!"<<endl;
  }
 }
 closesocket(m_socket);
 WSACleanup();
 return 0;
}


BOOL InitSocket(void)
{
 if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
 {
  cout<<"加载winsock失败,错误ID为:"<<WSAGetLastError()<<endl;
  exit(0);
 }
 m_socket=socket(AF_INET,SOCK_DGRAM,0);
 if(INVALID_SOCKET==m_socket)
 {
  cout<<"套接字创建失败!错误ID为:"<<WSAGetLastError()<<endl;
  return FALSE;
 }
 SerAdd.sin_family=AF_INET;
 SerAdd.sin_port=htons(Const_Port);
 SerAdd.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

 int retval;
 retval=bind(m_socket,(SOCKADDR*)&SerAdd,sizeof(SOCKADDR));
 if(SOCKET_ERROR==retval)
 {
  closesocket(m_socket);
  cout<<"端口绑定失败! 错误ID为:"<<WSAGetLastError()<<endl;
  return FALSE;
 }
 return TRUE;
}

posted @ 2010-08-14 16:53 傅先生 阅读(186) | 评论 (0)编辑 收藏

仅列出标题
共6页: 1 2 3 4 5 6 

posts - 54, comments - 5, trackbacks - 0, articles - 2

Copyright © 傅先生