c语言重建
1. c语言数据结构 堆的建立和维护
主要函数功能:1、通过输入的数组,建立堆结构
2、将堆结构按小顶堆排列
3、输入POP命令提取一个顶元素,存放在数组中。
(删除顶节点,重新初始化堆结构,重新按小顶堆排列)
4、输入PUSH命令将一个数值插入到堆末尾。
(新数值插入数组末尾,用新数组重建堆,重新按小顶堆排列)
5、打印所有POP提取的顶元素
#include<stdio.h>
#include<malloc.h>
#include<string.h>
typedefstructnode
{
int*data;
structnode*left;
structnode*right;
structnode*brother;
structnode*father;
}NODE;
typedefstructheapTree
{
intsize;
int*nums;//节点数值对应的数组
NODE**nodes;//所有的节点指针,用于释放堆
structnode*rootNode;//根节点
structnode*lastNode;//从上往下,从左往右数最后一个节点
}HEAP;
HEAP*initHeap(int*nums,intsize);//初始化堆
voidrecom(NODE*lastNode,intb);//重组堆,按小顶堆排列。先和子女比较,再兄弟和子女比较,再父亲和子女比较。
//参数:lastNode最后一个节点;b避免兄弟间无限循环,b=2跳出兄弟,进行父亲与子女比较,首次调用b传值1
voidprintfHeap(NODE*rootNode);//测试调试使用:遍历并打印堆数值
voidfreeHeap(HEAP*heap);//释放堆内存
intgetRootNode(HEAP*heap);//取出顶元素
voidaddRootNode(HEAP*heap,intnum);//插入节点元素
intmain()
{
inti,m,n,*nums=NULL,*rootNums=NULL,rNumSize=0,xwNum;//xwNum询问数值
charxwStr[5];//询问字符串POP或PUSH
HEAP*heap=NULL;
printf("输入n,m的值:
");
scanf("%d%d",&n,&m);
nums=(int*)malloc(sizeof(int)*n);
printf("输入%d个数字:
",n);
for(i=0;i<n;i++)
scanf("%d",&nums[i]);
heap=initHeap(nums,n);
recom(heap->lastNode,1);
//printfHeap(heap->rootNode);//测试:顺序打印节点
printf("等待%d次询问,请输入POP或PUSH命令:
",m);
while(1)
{
scanf("%s",xwStr);
if(strcmp(xwStr,"POP")==0)
{
rNumSize++;
if(rootNums==NULL)
rootNums=(int*)malloc(sizeof(int)*rNumSize);
else
rootNums=(int*)realloc(rootNums,sizeof(int)*rNumSize);//扩展原取值的存储内存
rootNums[rNumSize-1]=getRootNode(heap);//取出顶元素
//printfHeap(heap->rootNode);//测试:顺序打印节点
}
elseif(strcmp(xwStr,"PUSH")==0)
{
scanf("%d",&xwNum);
addRootNode(heap,xwNum);//插入新元素
//printfHeap(heap->rootNode);//测试:顺序打印节点//插入后重新排序有问题
}
m--;
if(m==0)
break;
}
printf("所有取出的顶端数值为:
");
for(i=0;i<rNumSize;i++)
printf("%d",rootNums[i]);
printf("
");
return0;
}
voidaddRootNode(HEAP*heap,intnum)//插入节点元素
{
inti,*numsSave=NULL,*nums=heap->nums,size=heap->size;
numsSave=(int*)malloc(sizeof(int)*(size+1));
for(i=0;i<size;i++)
numsSave[i]=nums[i];
nums=NULL;
numsSave[i]=num;//将新元素添加在数组末尾
freeHeap(heap);//释放堆内存
heap=initHeap(numsSave,size+1);//重新初始新的堆
recom(heap->lastNode,1);//重新小顶堆排列
}
intgetRootNode(HEAP*heap)//取出顶元素
{
inti,*numsSave=NULL,*nums=heap->nums,size=heap->size,rootNum;
rootNum=*heap->rootNode->data;
*heap->rootNode->data=nums[size-1];//根节点对应值换成数组最后一位地址值
numsSave=(int*)malloc(sizeof(int)*(size-1));
for(i=0;i<size-1;i++)
numsSave[i]=nums[i];
nums=NULL;//原数组空间将在freeHeap函数中一并释放
freeHeap(heap);//释放堆内存
heap=initHeap(numsSave,size-1);//重新初始新的堆
recom(heap->lastNode,1);//重新小顶堆排列
returnrootNum;
}
voidfreeHeap(HEAP*heap)//释放堆内存
{
inti;
for(i=0;i<heap->size;i++)//释放所有节点空间
{
heap->nodes[i]->data=NULL;
heap->nodes[i]->brother=NULL;
heap->nodes[i]->father=NULL;
heap->nodes[i]->left=NULL;
heap->nodes[i]->right=NULL;
free(heap->nodes[i]);
}
free(heap->nums);
heap->nums=NULL;
heap->nodes=NULL;
heap->lastNode=NULL;
heap->rootNode=NULL;
heap->size=0;
free(heap);
}
voidprintfHeap(NODE*rootNode)//遍历并打印堆数值
{
printf("%d",*rootNode->data);
if(rootNode->father==NULL&&rootNode->left!=NULL)//根节点
printfHeap(rootNode->left);
elseif(rootNode->father->left==rootNode&&rootNode->father->right!=NULL)//如果第左,那么找右
printfHeap(rootNode->father->right);
elseif(rootNode->father->right==rootNode&&rootNode->brother->left!=NULL)//如果第右,那么找左的左儿子
printfHeap(rootNode->brother->left);
else
printf("
");
}
HEAP*initHeap(int*nums,intsize)
{
inti;
NODE*newNode=NULL;
HEAP*heap=(HEAP*)malloc(sizeof(HEAP));
heap->rootNode=NULL;
heap->lastNode=NULL;
heap->nodes=(NODE**)malloc(sizeof(NODE*)*size);
heap->nums=nums;
for(i=0;i<size;i++)
{
newNode=(NODE*)malloc(sizeof(NODE));
heap->nodes[i]=newNode;
newNode->data=&nums[i];
newNode->left=NULL;
newNode->right=NULL;
newNode->brother=NULL;
newNode->father=NULL;
if(heap->rootNode==NULL)
heap->rootNode=newNode;
elseif(heap->lastNode->father==NULL)//上一个节点为根节点没有兄弟,新节点放在左位置
{
heap->lastNode->left=newNode;
newNode->father=heap->lastNode;
}
elseif(heap->lastNode->father->left==heap->lastNode)//上一个非根左节点,新节点放兄弟位置
{
heap->lastNode->brother=newNode;
newNode->brother=heap->lastNode;
newNode->father=heap->lastNode->father;
newNode->father->right=newNode;
}
elseif(heap->lastNode->father->right==heap->lastNode)//上一个非根右节点,新节点放兄弟左儿子位置
{
heap->lastNode->brother->left=newNode;
newNode->father=heap->lastNode->brother;
}
heap->lastNode=newNode;
}
heap->size=size;
returnheap;
}
voidrecom(NODE*lastNode,intb)//重组堆,按小顶堆排列。先和子女比较,再兄弟和子女比较,再父亲和子女比较。
//参数:lastNode最后一个节点;b避免兄弟间无限循环,b=2跳出兄弟,进行父亲与子女比较
{
intnumSave;
NODE*minNode=NULL,*fNode=lastNode->father,*bNode=lastNode->brother,*lNode=lastNode->left,*rNode=lastNode->right;
if(lNode!=NULL)
{
minNode=lastNode;
if(*minNode->data>*lNode->data)
{
numSave=*minNode->data;
*minNode->data=*lNode->data;
*lNode->data=numSave;
}
}
if(rNode!=NULL)
{
if(*minNode->data>*rNode->data)
{
numSave=*minNode->data;
*minNode->data=*rNode->data;
*rNode->data=numSave;
}
}
if(b==2)
recom(fNode,1);
elseif(bNode!=NULL)
recom(bNode,2);
}
2. c语言\r什么意思
\r是回车符,\n是换行符。
计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。
于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,告诉打字机把纸向下移一行。
这就是“换行”和“回车”的来历,从它们的英语名字上也可以看出一二。
后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。Unix 系统里,每行结尾只有“<换行>”,即“\n”;Windows系统里面,每行结尾是“<回车><换行>”,即“ \r\n”;Mac系统里,每行结尾是“<回车>”。一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。
3. C语言编译后显示没有这样的文件或目录是什么意思
最好上个截图,应该是库文件的路径设置不对。通常在集成环境的选项中有连接文件库的路径设置。
4. c语言问题
在 VC6.0 中新建一个工程,添加 fun.c、main.c 两个源文件和 fun.h 一个头文件,内容如下:
fun.c
#include <stdio.h>
int fun1(){
printf("The first function!\n");
return 0;
}
int fun2(){
printf("The second function!\n");
return 0;
}
int fun3(){
printf("The third function!\n");
return 0;
}
fun.h
#ifndef _FUN_H
#define _FUN_H
extern int fun1(void);
extern int fun2(void);
extern int fun3(void);
#endif
main.c
#include <stdio.h>
#include <stdlib.h>
#include "fun.h"
int main(){
fun1();
fun2();
fun3();
system("pause");
return 0;
}
对上面的每个 .c 文件都进行编译,然后链接并运行:
The first function!
The second function!
The third function!
上面的例子,函数定义放在 fun.c 文件中,在 fun.h 头文件中对函数进行声明,暴露接口,然后在主文件 main.c 中引入 fun.h。
注意:编译是针对单个 .c 文件的,如果项目中有多个 .c 文件,需要逐一编译,然后链接,或者使用“组建 -> 全部重建”选项,一次性编译并链接所有文件。
多文件编程时,只能有一个文件包含 main() 函数,因为一个工程只能有一个入口函数。我们把包含 main() 函数的文件称为主文件。
可以在其他 .c 文件中对函数进行定义,在 .h 中对函数进行声明,只要主文件包含进相应的头文件,就能使用这些函数。实际开发中,很少有简单到只有几十行代码的C语言项目,合理的组织代码和文件,是开发大中型项目的必备技能。
为了更好的组织各个文件,一般情况下一个 .c 文件对应一个 .h 文件,并且文件名要相同,例如 fun.c 和 fun.h。如果 fun.c 使用到了 fun.h 的宏定义、类型定义等,还需要在 fun.c 中 #include "fun.c"。
.c 文件主要包含各个函数的定义,.h 文件声明函数原型,向外暴露接口,供主文件调用。另外也可以在 .h 中包含宏定义、类型定义。
注意:.h 文件头文件中不能有可执行代码,也不能有变量定义,只能有宏、类型( typedef,struct,union,menu )定义和变量、函数的声明。
这倒不是说在 .h 中定义变量或函数会有语法错误,实际上#icnlude机制很简单,就是把#include所包含的文件中的内容直接复制到#include所在的位置并替换#include语句。但是这样做不符合模块化编程的惯例,也不利于文件的组织,不利于二次开发,不利于团队协作。
以上是网上找来的。
实际上只要一个工程里面有多个文件,那么都会编译到。
5. 这种c语言怎么处理
这段条件语句,应写成:
if (a!=b){
if (a>b) printf("A>B\n"); else printf("A<B\n");
} else printf("A=B\n");
----------
至于编译错误,要看到完整程序才行。因涉及 main () 的问题和变量重复定义问题,它们有可能是 花括号 配对出错引起,也可能有别的问题。
6. c语言大师 看一下 编译成功 无法创建目标
你这个文件叫什么名字? 错误中显示你的工程里面有两个主函数。
还有一个是lsq.c里面的。
你查一下是不是重复文件了。
不行的话,关掉project 然后重建一个。
7. 怎样在c语言中修改已录入的文件信息,谢谢
用FILE定义文件指针
FILE
*fp;
fp=fopen("文件名","a");//往原文件追加数据
fp=fopen("文件名","w");//重建文件,采用这种方式之前你应该将原文件中的数据都存储到内存中
操作完毕后应该用fclose(fp);关闭文件,否则会丢失数据
8. 如何用c语言建立哈希表 存有序对
#include<ctype.h>
#include<malloc.h>
#include<limits.h>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define SUCCESS 1
#define UNSUCCESS 0
#define DUPLICATE -1
#define NULLKEY 0 // 0为无记录标志
#define N 10 // 数据元素个数
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)<(b))
#define LQ(a,b) ((a)<=(b))
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int Boolean; // Boolean是布尔类型,其值是TRUE或FALSE
typedef int KeyType; // 设关键字域为整型
struct ElemType // 数据元素类型
{
KeyType key;
int ord;
};
int hashsize[]={11,19,29,37}; // 哈希表容量递增表,一个合适的素数序列
int m=0; // 哈希表表长,全局变量
struct HashTable
{
ElemType *elem; // 数据元素存储基址,动态分配数组
int count; // 当前数据元素个数
int sizeindex; // hashsize[sizeindex]为当前容量
};
Status InitHashTable(HashTable &H)// 操作结果: 构造一个空的哈希表
{ int i;
H.count=0; // 当前元素个数为0
H.sizeindex=0; // 初始存储容量为hashsize[0]
m=hashsize[0];
H.elem=(ElemType*)malloc(m*sizeof(ElemType));
if(!H.elem)
exit(OVERFLOW); // 存储分配失败
for(i=0;i<m;i++)
H.elem[i].key=NULLKEY; // 未填记录的标志
return OK;
}
void DestroyHashTable(HashTable &H)// 初始条件: 哈希表H存在。操作结果: 销毁哈希表H
{ free(H.elem);
H.elem=NULL;
H.count=0;
H.sizeindex=0;
}
unsigned Hash(KeyType K)// 一个简单的哈希函数(m为表长,全局变量)
{ return K%m;
}
void collision(int &p,int d) // 线性探测再散列
{
p=(p+d)%m;// 开放寻址法处理冲突
}
Status SearchHash(HashTable H,KeyType K,int &p,int &c)// 在开放寻址哈希表H中查找关键码为K的元素,若查找成功,以p指示待查数据
{ p=Hash(K); // 求得哈希地址
while(H.elem[p].key!=NULLKEY&&!EQ(K,H.elem[p].key))
{ // 该位置中填有记录.并且关键字不相等
c++;
if(c<m)
collision(p,c); // 求得下一探查地址p
else
break;
}
if EQ(K,H.elem[p].key)
return SUCCESS; // 查找成功,p返回待查数据元素位置
else
return UNSUCCESS; // 查找不成功(H.elem[p].key==NULLKEY),p返回的是插入位置
}
Status InsertHash(HashTable &,ElemType); // 对函数的声明
void RecreateHashTable(HashTable &H) // 重建哈希表
{ int i,count=H.count;
ElemType *p,*elem=(ElemType*)malloc(count*sizeof(ElemType));
p=elem;
printf("重建哈希表\n");
for(i=0;i<m;i++) // 保存原有的数据到elem中
if((H.elem+i)->key!=NULLKEY) // 该单元有数据
*p++=*(H.elem+i);
H.count=0;
H.sizeindex++; // 增大存储容量
m=hashsize[H.sizeindex];
p=(ElemType*)realloc(H.elem,m*sizeof(ElemType));
if(!p)
exit(OVERFLOW); // 存储分配失败
H.elem=p;
for(i=0;i<m;i++)
H.elem[i].key=NULLKEY; // 未填记录的标志(初始化)
for(p=elem;p<elem+count;p++) // 将原有的数据按照新的表长插入到重建的哈希表中
InsertHash(H,*p);
}
Status InsertHash(HashTable &H,ElemType e)// 查找不成功时插入数据元素e到开放寻址哈希表H中,并返回OK;
{ int c,p;
c=0;
if(SearchHash(H,e.key,p,c)) // 表中已有与e有相同关键字的元素
return DUPLICATE;
else if(c<hashsize[H.sizeindex]/2) // 冲突次数c未达到上限,(c的阀值可调)
{ // 插入e
H.elem[p]=e;
++H.count;
return OK;
}
else
RecreateHashTable(H); // 重建哈希表
return ERROR;
}
void TraverseHash(HashTable H,void(*Vi)(int,ElemType))// 按哈希地址的顺序遍历哈希表
{
printf("哈希地址0~%d\n",m-1);
for(int i=0;i<m;i++)
if(H.elem[i].key!=NULLKEY) // 有数据
Vi(i,H.elem[i]);
}
Status Find(HashTable H,KeyType K,int &p)// 在开放寻址哈希表H中查找关键码为K的元素,若查找成功,以p指示待查数据
{ int c=0;
p=Hash(K); // 求得哈希地址
while(H.elem[p].key!=NULLKEY&&!EQ(K,H.elem[p].key))// 该位置中填有记录.并且关键字不相等
{ c++;
if(c<m)
collision(p,c); // 求得下一探查地址p
else
return UNSUCCESS; // 查找不成功(H.elem[p].key==NULLKEY)
}
if EQ(K,H.elem[p].key)
return SUCCESS; // 查找成功,p返回待查数据元素位置
else
return UNSUCCESS; // 查找不成功(H.elem[p].key==NULLKEY)
}
void print(int p,ElemType r)//输出
{
printf("address=%d (%d,%d)\n",p,r.key,r.ord);
}
void main()
{
ElemType r[N]={{17,1},{60,2},{29,3},{38,4},{1,5},{2,6},{3,7},{4,8},{60,9},{13,10}};
HashTable h;
int i,p;
Status j;
KeyType k;
InitHashTable(h);
for(i=0;i<N-1;i++)// 插入前N-1个记录
{
j=InsertHash(h,r[i]);
if(j==DUPLICATE)
printf("表中已有关键字为%d的记录,无法再插入记录(%d,%d)\n",r[i].key,r[i].key,r[i].ord);
}
printf("按哈希地址的顺序遍历哈希表:\n");
TraverseHash(h,print);
printf("请输入待查找记录的关键字: ");
scanf("%d",&k);
j=Find(h,k,p);
if(j==SUCCESS)
print(p,h.elem[p]);
else
printf("没找到\n");
j=InsertHash(h,r[i]); // 插入第N个记录
if(j==ERROR) // 重建哈希表
j=InsertHash(h,r[i]); // 重建哈希表后重新插入
printf("按哈希地址的顺序遍历重建后的哈希表:\n");
TraverseHash(h,print);
printf("请输入待查找记录的关键字: ");
scanf("%d",&k);
j=Find(h,k,p);
if(j==SUCCESS)
print(p,h.elem[p]);
else
printf("没找到\n");
DestroyHashTable(h);
}
9. c语言如何读写与重建MBR
int biosdisk(int cmd, int drive, int head, int track, int sector, int nsects, void *buffer);
cmd为功能号:
0 重置软磁盘系统.这强迫驱动器控制器来执行硬复位.忽略所有其它参数.
1 返回最后的硬盘操作状态.忽略所有其它参数
2 读磁盘,读的位置由head、track、sector给出,读取nsects个扇区到buffer中;
3 写磁盘。写的位置是head、track、sector开始的nsects个扇区。要写的数据在buffer中。
drive为驱动器号(0=A,1=B,0x80=C,0x81=D,0x82=E,依次类推)
head为磁头 track为磁道 sector为扇区
nsects为要读或写的扇区数
MBR在磁盘的0面0道1扇区,长度为512字节,所以读取第1块硬盘的MBR可以用:
char mbr_buffer[512];
biosdisk(2, 0x80, 0, 0, 1, 1, mbr_buffer);
但是,这不是C语言的标准函数,而是某些编译器的扩展,本质上是BIOS软中断INT13H的接口。所以兼容性受到很大限制,比如正常情况下,在Windows环境中不允许这样直接访问硬件的程序运行的,可以在实模式下试试。而且一定要小心,读还可以,千万不要轻易写,一旦出错就麻烦了。
10. c语言在执行的时候编译没有问题,组建的时候错误什么问题
这个没有问题的。
至少我测试是正常的
你可以重新启动一下你的 IDE,然后再试试;如果还是不行,将目录下的一些文件给删除——保留你的CPP文件,重新编译试试;如果还是不行,重建一个工程再试试。
如果以上方法都还不行,那才叫有问题了。