[C++]数据结构之堆-上滤下滤以及用于排序

#include<iostream>
using namespace std;

/*
* 堆,就是一棵完全二叉树,物理存储方式是数组,一般情况下,都牺牲第一个元素arr[0],剩下的就满足了从1开始计数
* 若堆从1开始计数,那么对于一个节点i,2*i是它的左孩子,2*i+1是它的右孩子
* 对的最基本操作,包括上滤和下滤
* 上滤是指:h(1,n-1)是堆,h(1,n)不是堆,因此通过将arr[n]元素上滤,来达到调整堆的目的
* 下滤是指:h(2,n)是堆,h(1,n)不是堆,因此通过将arr[1]元素下滤,来达到调整堆的目的
*/

#define HEAP_SIZE 10 //这里,我要要建一个堆,堆里面要放10个元素
#define ARR_SIZE (HEAP_SIZE+1) //之前说过,堆默认的实现是牺牲掉第0个元素
#define HeapElemType int //定义堆的元素类型

//HeapElemType  HeapArray[ARR_SIZE];//堆的存储空间

/*
* 大顶堆,上面的,是最大的
* 堆的基本操作:上滤
* h(1,n-1)是堆,h(1,n)非堆,也就是说,只要调整第n个元素,就是一个新堆了
* 注意:n是当前可用元素的最大下标,它是不能超过ARR_SIZE的
*/
void shiftUp(HeapElemType  HeapArray[], int n){
    HeapElemType tmp = HeapArray[n];
    while(n/2>=1 && tmp>HeapArray[n/2]){
        HeapArray[n] = HeapArray[n/2];
        n = n/2;
    }
    HeapArray[n] = tmp;
}

/*
* 大顶堆,上面的,是最大的
* 堆的基本操作:下滤
* h(2,n)是堆,h(1,n)不是堆,也就是所,只要调整第1个元素,就是一个新的大顶堆
* 注意:n是当前堆中元素的最大下表,是不能超过ARR_SIZE的
*/
void shiftDown(HeapElemType  HeapArray[], int first, int n){
    HeapElemType tmp = HeapArray[first];
    int father=first,child;
    while( (child=2*father) <= n){
        //获取孩子中较大的孩子下标
        if(child+1<=n && HeapArray[child]<HeapArray[child+1]) child++;
        //比较源节点和较大孩子,看是否需要继续调整
        if(tmp>HeapArray[child]) break;
        //否则的话,孩子往上走
        HeapArray[father] = HeapArray[child];
        father = child;
    }
    HeapArray[father] = tmp;
}
void printHeapArr(const HeapElemType  HeapArray[], const int n){
    for(int i=1; i<=n; ++i){
        cout<<HeapArray[i]<<" ";
    }
    cout<<endl;
}
void swap(HeapElemType  HeapArray[],int i,int j){
    HeapElemType tmp =     HeapArray[i];
    HeapArray[i] = HeapArray[j];
    HeapArray[j] = tmp;
}
/*
* 堆排序:用堆的属性,即大顶堆最顶部的就是最大的节点
* 因此我们可以每次将根节点和末尾节点交换,然后将除了末尾节点的其他节点重新调整一个堆,然后循环
* 在做上一步之前,需要将杂乱的节点调整成一个堆
*/
void heapsort(HeapElemType  HeapArray[],int n){
    //第一步,先将杂乱的数组调整成一个大顶堆,需要n/2次调整就可以
    int tmp=0;
    for(tmp=n/2; tmp>=1; tmp--){
        shiftDown(HeapArray,tmp,n);
    }
    //第二步,交换第一个节点(最大值)和末尾节点,然后调整除了末尾节点的其他节点为一个新大顶堆
    for(tmp=n;tmp>1;tmp--){
        swap(HeapArray,1,tmp);
        shiftDown(HeapArray,1,tmp-1);
    }
}
void main(){
    cout<<"上滤"<<endl;
    HeapElemType  HeapArray[ARR_SIZE]={0,5,4,2,3,6};
    int n=5;
    printHeapArr(HeapArray,n);
    shiftUp(HeapArray,n);
    printHeapArr(HeapArray,n);

    cout<<"下滤"<<endl;
    HeapElemType  HeapArraySec[ARR_SIZE]={0,1,5,2,3,4};
    n=5;
    printHeapArr(HeapArraySec,n);
    shiftDown(HeapArraySec,1,n);
    printHeapArr(HeapArraySec,n);

    cout<<"排序"<<endl;
    HeapElemType  HeapArraySort[ARR_SIZE]={0,1,4,2,3,5,6};
    n=6;
    printHeapArr(HeapArraySort,n);
    heapsort(HeapArraySort,n);
    printHeapArr(HeapArraySort,n);

    system("pause");
}

 

C++拆分字符串代码(实现split)

以下C++实现一个将字符串拆分以后,存放到一个string当中的代码,使用的时候传入三个参数即可,非常好用:

#ifndef FUNCTIONS_H
#define FUNCTIONS_H

#include <iostream>
#include <string>
#include <algorithm>     
#include <functional>
using namespace std;
#include <vector>


inline string&  lTrim(string   &ss)     
{     
    string::iterator   p=find_if(ss.begin(),ss.end(),not1(ptr_fun(isspace)));     
    ss.erase(ss.begin(),p);     
    return  ss;     
}     
  
inline  string&  rTrim(string   &ss)     
{     
    string::reverse_iterator  p=find_if(ss.rbegin(),ss.rend(),not1(ptr_fun(isspace)));     
    ss.erase(p.base(),ss.end());     
    return   ss;     
}     
  
inline   string&   trim(string   &st)     
{     
    lTrim(rTrim(st));     
    return   st;     
} 

//将一个以par分割的整个字符串,分割以后存到vec里面
void splitStr(vector<string> &vec, string str, string par){
    string::size_type pos=0,previousPos=0;//查找到的位置和前一个位置
    //处理并没有分割符的情况
    if(str.find(par,0)==string::npos){
        if(!trim(str).empty())    vec.push_back(trim(str));
        return;
    }
    string strtmp;
    for( pos=str.find(par,0); pos!=string::npos; previousPos=pos+par.size(), pos=str.find(par,pos+par.size()) ){
        strtmp = str.substr(previousPos,pos-previousPos);
        if(!trim(strtmp).empty()) vec.push_back(strtmp);
    }
    strtmp = str.substr(previousPos,pos-previousPos);
    if(!trim(strtmp).empty()) vec.push_back(strtmp);
}


#endif

 

本函数可以用以下示例调用:

void main()
        vector<string> vec;
        splitStr(vec, "C$D$E$F$G","$");
        cout<<"分割前的字符串:"<<str<<endl;
        cout<<"分割后的子串:"<<endl;
        for(int i=0; i!=vec.size(); ++i){
            cout<<"#"<<vec[i]<<"#"<<endl;
        }
        cout<<endl;
    }

 

c/c++批量向mysql插入数据

先给个MYSQL对于C的API

具体代码,改为手动提交,每次5W数据

//mysql所需的头文件和库文件

//mysql所需的头文件和库文件  
#include "winsock.h" 

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

#include "mysql.h"
#include<fstream>
#include <string>
#include <vector>
#include <iostream>
using namespace std;

int main()
{
    //配置文件
    ifstream configFin("config.txt");
    ifstream filefin("filelist.txt");//要处理的文件列表

    string processFile;//要处理的文件名字
    string dbhost;//数据库主机
    string dbuser;//数据库用户名
    string dbpwd;//数据库密码
    string dbname;//数据库名字
    int eachProcessCount=50000;//每次处理的个数
    string tmp;

    //将文件列表放到vector里
    vector<string> filevec;
    while(filefin>>tmp) filevec.push_back(tmp);

    configFin>>tmp>>dbhost>>tmp>>dbuser>>tmp>>dbpwd>>tmp>>dbname>>tmp>>eachProcessCount;

    unsigned int port = 3306;           //server port       

    for(int fi=0; fi!=filevec.size(); ++fi){
        //每次循环,处理一个文件
        processFile = filevec[fi];
        cout<<"文件:"<<processFile<<endl;
        MYSQL myCont;
        mysql_init(&myCont);
        string uid, friendid;

        ifstream fin(processFile.c_str());
        int i=0;
        int eachCount = 0;
        string sql;
        while(!fin.eof()){
            if(mysql_real_connect(&myCont,dbhost.c_str(),dbuser.c_str(),dbpwd.c_str(),dbname.c_str(),port,NULL,CLIENT_MULTI_STATEMENTS)){
                mysql_autocommit(&myCont,0);

                mysql_query(&myCont, "SET NAMES utf8");
                for(eachCount=0; eachCount<eachProcessCount; ++eachCount){
                    if(fin>>uid>>friendid){
                        //如果还有内容,那么就构建插入语句
                        sql = "insert into friendlist values('"+uid+"','"+friendid+"');";
                        mysql_query(&myCont, sql.c_str());
                    } else {
                        break;
                    }
                }
                cout<<". ";
                mysql_commit(&myCont);
                mysql_close(&myCont);//断开连接
            }else{
                cout<<"connect failed!"<<endl;
            }

        }
        cout<<endl;
        fin.close();
    }

    system("pause");
    return 0;
}

 

大致说一下C链接MYSQL的方法:

1、去官方下载mysql和c的connector

2、拷贝里面的lib目录下的dll和lib文件到当前目录下

3、设置当前项目的头文件位下载的目录下的inlcude

4、设置一个lib库(在项目设置里),设置第2步的文件名

5、用上述程序就可以连接(数据库地址之类的,自己改掉)

[C++]win32输出当前系统时间函数,可用以程序计时

#include <string>
#include <iostream>
#include <time.h>
#include <fstream>
using namespace std;

//本函数用于获取当前系统的时间,使用前请传入获取时间的string的引用
void getSystemTime(string & stime){
    time_t t = time( 0 );
    char tmp[64];
    strftime( tmp, sizeof(tmp), "%Y/%m/%d %X ",localtime(&t) );
    stime=tmp;
}

int main(){
    string nowtime;//存储获取的系统的时间
    //输出起始时间
    getSystemTime(nowtime);
    cout<<nowtime<<endl;

    //这一步仅仅是为了耗费程序的时间
    ofstream fout("tt.txt");
    for(long i=0; i<1000*1000; ++i){fout<<i<<endl;}

    //输出结束时间
    getSystemTime(nowtime);
    cout<<nowtime<<endl;
    system("pause");
    return 0;
}

 

程序运行结果截图:

C++ Primer 4th:第九章 《顺序容器》学习心得

C++学到深入一点,就应该大量的了解STL的知识,而这其中支撑的部分就是容器,顺序容器包括vector,list,deque等,如果善加利用,能够很大程度上提升程序的开发速度和效率,同时也减少了出问题的几率。 继续阅读C++ Primer 4th:第九章 《顺序容器》学习心得

C++标准库string类型学习笔记

 String类型支持长度可变的字符串,需要包含头文件#include<string>

1、string对象的定义和初始化

string支持好几种初始化方式:

初始化方式

说明

String s1;

默认构造函数,s1是空串

String s2(s1)

s2初始化为s1的一个副本

String s3(“value”)

s3初始化为一个字符串字面值的副本

String s4(n, ‘c’)

s4初始化为字符’c’n个副本

  继续阅读C++标准库string类型学习笔记