b树c语言,B树——思路、及C语言代码的实现

合并:

在此先声明,因为一开始只考虑B树的阶为4的情况,后来改为使用宏定义阶M的数值,所以这段代码存在BUG,只支持阶为3或4的B树= =。

思路还是挺清晰的,首先先向兄弟结点借元素,如果兄弟能够借给你元素的话(即借了你之后并不会小于最少的分支),那么直接从兄弟那里取元素,否则,和兄弟合并。

合并其实是分裂反过来的情况,从父亲结点那里取出一个key值介于要合并的两个结点之间的元素,插入左部分最末尾处,同时右部分插到左部分后面,然后父亲结点元素依次往前挪。从而实现合并操作。之后,也必须对父亲结点进行判断是否小于最小的分支数,如果也小于,对父亲节点进行递归操作。

/***

*  @name          Status borrowBNode(BTree &T)

*  @description    递归实现,向兄弟借元素,否则和兄弟合并

*  @return        成功返回OK,否则返回ERROR

*  @notice        这种情况应该是T为单元素结点

***/

Status borrowBNode(BTree T)

{

int mynum, bronum, index;

BTree b = NULL, f = NULL;

if (T == NULL) return ERROR;

f = T->parent;

if (f == NULL)//考虑父亲结点不存在的情况

{

if (T->keynum == 0)

{

f = T->ptr[0];

if (f == NULL)

{

free(T);

return EMPTY;

}

for (index = 0;index <= f->keynum;index++)

{

T->key[index] = f->key[index];

T->ptr[index] = f->ptr[index];

}

T->keynum = f->keynum;

free(f);

renewParent(T);

}

return OK;

}

mynum = whichSon(T);

if (mynum == 0)

bronum = 1;

else

bronum = mynum - 1;

b = f->ptr[bronum];

if (b->keynum == (m + 1) / 2 - 1) //如果兄弟帮不了你了

{

//那么就和这个兄弟合体

if (bronum < mynum)                    //如果我不是第一个

{

b->keynum++;

b->key[b->keynum] = f->key[mynum];

b->ptr[b->keynum] = T->ptr[0];

for (index = 1;index <= T->keynum;index++)

{

b->key[index + b->keynum] = T->key[index];

b->ptr[index + b->keynum] = T->ptr[index];

b->keynum++;

}

free(T);

for (index = mynum;index <= f->keynum;index++)

{

f->key[index] = f->key[index + 1];

f->ptr[index] = f->ptr[index + 1];

}

f->keynum--;

}

else

{

T->keynum++;

T->key[T->keynum] = f->key[bronum];

T->ptr[T->keynum] = b->ptr[0];

for (index = 1;index <= b->keynum;index++)

{

T->key[index + T->keynum] = b->key[index];

T->ptr[index + T->keynum] = b->ptr[index];

T->keynum++;

}

free(b);

for (index = bronum;index <= f->keynum;index++)

{

f->key[index] = f->key[index + 1];

f->ptr[index] = f->ptr[index + 1];

}

f->keynum--;

}

renewParent(f);

if (f->keynum == (m + 1) / 2 - 2)

{

//调用借兄弟的函数

return borrowBNode(f);

}

}

else//如果兄弟能够帮你

{

if (bronum < mynum)                    //如果我不是第一个

{

for (index = 1;index <= T->keynum;index++)

{

T->key[index + 1] = T->key[index];

T->ptr[index + 1] = T->ptr[index];

}

T->ptr[1] = T->ptr[0];

T->key[1] = f->key[mynum];

T->ptr[0] = b->ptr[b->keynum];

T->keynum++;

f->key[mynum] = b->key[b->keynum];

b->key[b->keynum] = 0;

b->ptr[b->keynum] = NULL;

b->keynum--;

}

else                                    //如果我是第一个

{

T->keynum++;

T->key[T->keynum] = f->key[1];

T->ptr[T->keynum] = b->ptr[0];

f->key[1] = b->key[1];

b->ptr[0] = b->ptr[1];

for (index = 1;index <= b->keynum;index++)

{

b->key[index] = b->key[index + 1];

b->ptr[index] = b->ptr[index + 1];

}

b->keynum--;

}

}

return OK;

}

遍历,输出:

为了让B树更容易看,代码更容易调试,我同时还用队列写了个层次遍历,这个看看就好,实现起来挺麻烦的。而且可能代码实现也存在问题

/***

*  @name          Status ergodic(BTree T, LinkList L, int newline, int sum)

*  @description    print需要用到的递归遍历程序

*  @return        成功返回OK

*  @notice        此处用到队列

***/

Status ergodic(BTree T, LinkList L, int newline, int sum)

{

int index;

BTree p;

if (T != NULL)

{

printf("[ ");

Enqueue_L(L, T->ptr[0]);

for (index = 1;index <= T->keynum; index++)

{

printf("%d ", T->key[index]);

Enqueue_L(L, T->ptr[index]);

}

sum += T->keynum + 1;

printf("]");

if (newline == 0)

{

printf("\n");

newline = sum - 1;

sum = 0;

}

else

{

--newline;

}

}

if (IfEmpty(L) == FALSE)

{

Dequeue_L(L, p);

ergodic(p, L, newline, sum);

}

return OK;

}

/***

*  @name          Status print(BTree T)

*  @description    层次遍历并分层输出B树

*  @return        成功返回OK

*  @notice

***/

Status print(BTree T)

{

LinkList L;

if (T == NULL)

{

printf("[ ]\n");

return OK;

}

InitQueue_L(L);

ergodic(T, L, 0, 0);

DestroyQueue(L);

return OK;

}

3.测试

743663500a182904ae11623295cd894c.png

82527ccca7f245992c62a6da0a071ccf.png

4.总结

以目前所掌握的知识,终于把B树做出来了,整个过程没有参考过其他人的代码,所以并不知道自己的一些思路是否得当,如有错误,多多包涵。在整个过程中,最难,卡的最久的也就是合并操作了,这块的代码也是乱得掉渣,以后有时间把他完善了。最后附上完整代码。

#define _CRT_SECURE_NO_WARNINGS

#include

#include

#include

#define BTREELENGTH 50

#define BTLEN (sizeof(BTNode))

#define MAXINT 100

typedef enum status

{

TRUE,

FALSE,

OK,

ERROR,

OVERFLOW,

EMPTY

}Status;

typedef int KeyType;

//**********************************B树****************************************

#define  m  3  // B树的阶,此设为4

typedef struct

{

KeyType  key;

char    data;

} Record;

typedef struct BTNode

{

int            keynum;        // 结点中关键字个数,即结点的大小

struct BTNode  *parent;        // 指向双亲结点

KeyType        key[m + 1];      // 关键字向量,0号单元未用

struct BTNode  *ptr[m + 1];      // 子树指针向量

//  Record        *recptr[m + 1];  // 记录指针向量,0号单元未用

//在此添加其他自定义数据

} BTNode, *BTree;                // B树结点和B树的类型

typedef struct

{

BTNode  *pt;      // 指向找到的结点

int      i;      // 1..m,在结点中的关键字序号

int      tag;    // 1:查找成功,0:查找失败

} Result;          // 在B树的查找结果类型

//**********************************B树****************************************

//**********************************队列***************************************

typedef struct LNode {

BTree data;    // 数据域

struct LNode *next;    // 指针域

} LNode, *LinkList;

//**********************************队列***************************************

/***

*  @name          Status InitQueue_L(LinkList &L)

*  @description    初始化队列

*  @return        成功返回OK,开辟空间失败返回OVERFLOW

*  @notice

***/

Status InitQueue_L(LinkList &L)

{ // 初始化一个只含头结点的空单链表L

if (NULL == (L = (LNode*)malloc(sizeof(LNode)))) // 生成新结点

return OVERFLOW;

L->next = NULL;

return OK;

}

/***

*  @name          LNode* MakeNode_L(BTree e)

*  @description    构造队列结点

*  @return        返回结点地址

*  @notice

***/

LNode* MakeNode_L(BTree e)

{ // 构造数据域为e的单链表结点

LNode *p;

p = (LNode*)malloc(sizeof(LNode)); // 分配结点空间

if (p != NULL)

{

p->data = e;

p->next = NULL;

}

return p;

}

/***

*  @name          Status Enqueue_L(LNode *p, BTree e)

*  @description    队列的入队

*  @return        成功返回OK,否则返回ERROR

*  @notice

***/

Status Enqueue_L(LNode *p, BTree e)

{ //在p结点之后插入q结点

if (NULL == p) return ERROR; // 参数不合理

while (p->next != NULL)

p = p->next;

p->next = MakeNode_L(e);        // 对应图4.11(b)的②,修改p结点的指针域

return OK;

}

/***

*  @name          Status Dequeue_L(LNode *p, BTree &e)

*  @description    队列的出队

*  @return        成功返回OK,否则返回ERROR

*  @notice

***/

Status Dequeue_L(LNode *p, BTree &e)

{

// 删除p结点的直接后继结点并用参数e返回被删结点的值

LNode *q;

if (NULL == p || NULL == p->next) return ERROR; // 删除位置不合理

q = p->next;

p->next = q->next; // 修改被删结点q的指针域

e = q->data;

free(q); // 释放结点q

return OK;

}

/***

*  @name          void DestroyQueue(LinkList L)

*  @description    队列的销毁

*  @return        无返回

*  @notice

***/

void DestroyQueue(LinkList L)

{

// 销毁整个链表

LinkList p;

if (L != NULL)

{

p = L;

L = L->next;

free(p);

DestroyQueue(L);

}

}

/***

*  @name          Status  IfEmpty(LinkList L)

*  @description    判断队列是否为空

*  @return        空返回TRUE,不空返回FALSE,否则返回ERROR

*  @notice

***/

Status  IfEmpty(LinkList L)

{

if (L == NULL) return ERROR;

if (L->next == NULL) return TRUE;

return FALSE;

}

/***

*  @name          Status ergodic(BTree T, LinkList L, int newline, int sum)

*  @description    print需要用到的递归遍历程序

*  @return        成功返回OK

*  @notice        此处用到队列

***/

Status ergodic(BTree T, LinkList L, int newline, int sum)

{

int index;

BTree p;

if (T != NULL)

{

printf("[ ");

Enqueue_L(L, T->ptr[0]);

for (index = 1;index <= T->keynum; index++)

{

printf("%d ", T->key[index]);

Enqueue_L(L, T->ptr[index]);

}

sum += T->keynum + 1;

printf("]");

if (newline == 0)

{

printf("\n");

newline = sum - 1;

sum = 0;

}

else

{

--newline;

}

}

if (IfEmpty(L) == FALSE)

{

Dequeue_L(L, p);

ergodic(p, L, newline, sum);

}

return OK;

}

/***

*  @name          Status print(BTree T)

*  @description    层次遍历并分层输出B树

*  @return        成功返回OK

*  @notice

***/

Status print(BTree T)

{

LinkList L;

if (T == NULL)

{

printf("[ ]\n");

return OK;

}

InitQueue_L(L);

ergodic(T, L, 0, 0);

DestroyQueue(L);

return OK;

}

/***

*  @name          Status findMax(BTree T, BTree &p,int ans)

*  @description    寻找最大关键字的结点,T为要寻找的树,p为返回的节点,ans为第几个

*  @return        成功返回OK,否则返回ERROR

*  @notice

***/

Status findMax(BTree T, BTree &p, int &ans)

{

if (T == NULL)

return ERROR;

p = T;

while (p->ptr[p->keynum] != NULL)

{

p = p->ptr[p->keynum];

}

ans = p->keynum;

return OK;

}

/***

*  @name          Status findMin(BTree T, BTree &p,int ans)

*  @description    寻找最小关键字的结点,T为要寻找的树,p为返回的节点,ans为第几个

*  @return        成功返回OK,否则返回ERROR

*  @notice

***/

/***

*  @name          Status findBTree(BTree T, BTree &p, int &ans, KeyType k)

*  @description    寻找 ,T为要寻找的树,p为返回的节点,ans为第几个元素,k为要找的值

*  @return        成功返回OK,否则返回ERROR

*  @notice

***/

Status findBTree(BTree T, BTree &p, int &ans, KeyType k)

{

BTree q;

int index = 1;

KeyType  keynow;

if (T == NULL)

return ERROR;

q = T;

keynow = T->key[1];

while (q != NULL)                //深度的遍历

{

index = 1;

keynow = q->key[index];

while (index <= q->keynum) //节点内对各真值进行遍历

{

if (k == keynow)          //找到元素

{

p = q;

ans = index;

return TRUE;

}

if (k > keynow)

{

if (index == q->keynum)

{

if (q->ptr[index] == NULL)

{

p = q;

ans = q->keynum + 1;

return FALSE;

}

q = q->ptr[index];

break;

}

++index;

keynow = q->key[index];

continue;

}

if (k < keynow)

{

if (q->ptr[index - 1] == NULL)

{

p = q;

ans = index;

return FALSE;

}

q = q->ptr[index - 1];

break;

}

}

}

return ERROR;

}

/***

*  @name          Status renewParent(BTree p)

*  @description    告诉孩子们亲身爸爸是谁

*  @return        成功返回OK,否则返回ERROR

*  @notice

***/

Status renewParent(BTree p)

{

int index;

if (p == NULL) return ERROR;

for (index = 0;index <= p->keynum;++index)

{

if (p->ptr[index] != NULL)

{

p->ptr[index]->parent = p;

renewParent(p->ptr[index]);

}

}

return OK;

}

/***

*  @name          int whichSon(BTree T)

*  @description    找出是父亲的第几个孩子

*  @return        成功返回第几个孩子,否则返回-1

*  @notice

***/

int whichSon(BTree T)

{

int index = -1;

if (T == NULL) return -1;

for (index = 0;index <= T->parent->keynum;++index) //找出是父亲的第几个孩子

{

if (T->parent->ptr[index] == T) return index;

}

return -1;

}

/***

*  @name          status splitBTree(BTree T)

*  @description    递归实现分裂节点操作

*  @return        成功返回OK,否则返回ERROR

*  @notice

***/

Status splitBTree(BTree T) //此时分裂的节点一定会是超出最大值的。

{

BTree t1, t2;

int index, index_1;

if (T->parent == NULL)

{

t1 = (BTree)malloc(BTLEN);

if (NULL == t1) return OVERFLOW;

t2 = (BTree)malloc(BTLEN);

if (NULL == t2) return OVERFLOW;

t1->keynum = m / 2;

t2->keynum = m - (m / 2) - 1;

t1->parent = T;

t2->parent = T;

for (index = 0;index <= m; ++index)  //先全部初始化

{

t1->ptr[index] = NULL;

t1->key[index] = 0;

t2->ptr[index] = NULL;

t2->key[index] = 0;

}

for (index = 0;index <= m / 2; ++index)  //初始化t1

{

t1->ptr[index] = T->ptr[index];

t1->key[index] = T->key[index];

}

t2->ptr[0] = T->ptr[(m / 2) + 1];

for (index = (m / 2) + 2;index <= m; ++index)  //初始化t2

{

t2->ptr[index - ((m / 2) + 1)] = T->ptr[index];

t2->key[index - ((m / 2) + 1)] = T->key[index];

}

T->keynum = 1;

T->ptr[0] = t1;

T->ptr[1] = t2;

T->key[1] = T->key[m / 2 + 1];

for (index = 2;index <= m; ++index)  //初始化T

{

T->ptr[index] = NULL;

T->key[index] = 0;

}

return OK;

}

index = whichSon(T);

for (index_1 = T->parent->keynum;index_1 > index;--index_1) //腾出父亲的位置

{

T->parent->ptr[index_1 + 1] = T->parent->ptr[index_1];

T->parent->key[index_1 + 1] = T->parent->key[index_1];

}

T->parent->keynum++;

T->parent->key[index + 1] = T->key[m / 2 + 1];

t2 = T->parent->ptr[index + 1] = (BTree)malloc(BTLEN);

if (NULL == t2) return OVERFLOW;

for (index = 0;index <= m; ++index)  //先全部初始化

{

t2->ptr[index] = NULL;

t2->key[index] = 0;

}

t2->keynum = m - (m / 2) - 1;

t2->parent = T->parent;

t2->ptr[0] = T->ptr[(m / 2) + 1];

for (index = (m / 2) + 2;index <= m; ++index)  //初始化t2

{

t2->ptr[index - ((m / 2) + 1)] = T->ptr[index];

t2->key[index - ((m / 2) + 1)] = T->key[index];

}

T->keynum = m / 2;

for (index = (m / 2) + 1;index <= m; ++index)  //初始化t2

{

T->ptr[index] = NULL;

T->key[index] = 0;

}

if (T->parent->keynum == m)

{

splitBTree(T->parent);

}

return OK;

}

/***

*  @name          Status insertBTree(BTree &T, Record e)

*  @description    插入实现元素的插入

*  @return        成功返回OK,如果存在则返回FALSE,否则返回ERROR

*  @notice

***/

Status insertBTree(BTree &T, Record e)

{

BTree p;

int index, temp;

Status find_flag;

if (NULL == T)

{

T = (BTree)malloc(BTLEN);

if (NULL == T) return OVERFLOW;

T->keynum = 1;

T->parent = NULL;

for (index = 0;index <= m; ++index)

{

T->ptr[index] = NULL;

T->key[index] = 0;

}

T->key[1] = e.key;

return OK;

}

find_flag = findBTree(T, p, temp, e.key);

if (find_flag == TRUE)

{

return FALSE;

}

if (find_flag == FALSE)

{                                //不管怎样先直接插入

p->keynum++;

for (index = p->keynum;index > temp;--index)

{

p->key[index] = p->key[index - 1];

p->ptr[index] = p->ptr[index - 1];

}

p->ptr[temp] = NULL;

p->key[temp] = e.key;

if (p->keynum == m)      //这种情况得分裂

{

splitBTree(p);

}

renewParent(T);

return OK;

}

return ERROR;

}

/***

*  @name          Status borrowBNode(BTree &T)

*  @description    递归实现,向兄弟借元素,否则和兄弟合并

*  @return        成功返回OK,否则返回ERROR

*  @notice        这种情况应该是T为单元素结点

***/

Status borrowBNode(BTree T)

{

int mynum, bronum, index;

BTree b = NULL, f = NULL;

if (T == NULL) return ERROR;

f = T->parent;

if (f == NULL)//考虑父亲结点不存在的情况

{

if (T->keynum == 0)

{

f = T->ptr[0];

if (f == NULL)

{

free(T);

return EMPTY;

}

for (index = 0;index <= f->keynum;index++)

{

T->key[index] = f->key[index];

T->ptr[index] = f->ptr[index];

}

T->keynum = f->keynum;

free(f);

renewParent(T);

}

return OK;

}

mynum = whichSon(T);

if (mynum == 0)

bronum = 1;

else

bronum = mynum - 1;

b = f->ptr[bronum];

if (b->keynum == (m + 1) / 2 - 1) //如果兄弟帮不了你了

{

//那么就和这个兄弟合体

if (bronum < mynum)                    //如果我不是第一个

{

b->keynum++;

b->key[b->keynum] = f->key[mynum];

b->ptr[b->keynum] = T->ptr[0];

for (index = 1;index <= T->keynum;index++)

{

b->key[index + b->keynum] = T->key[index];

b->ptr[index + b->keynum] = T->ptr[index];

b->keynum++;

}

free(T);

for (index = mynum;index <= f->keynum;index++)

{

f->key[index] = f->key[index + 1];

f->ptr[index] = f->ptr[index + 1];

}

f->keynum--;

}

else

{

T->keynum++;

T->key[T->keynum] = f->key[bronum];

T->ptr[T->keynum] = b->ptr[0];

for (index = 1;index <= b->keynum;index++)

{

T->key[index + T->keynum] = b->key[index];

T->ptr[index + T->keynum] = b->ptr[index];

T->keynum++;

}

free(b);

for (index = bronum;index <= f->keynum;index++)

{

f->key[index] = f->key[index + 1];

f->ptr[index] = f->ptr[index + 1];

}

f->keynum--;

}

renewParent(f);

if (f->keynum == (m + 1) / 2 - 2)

{

//调用借兄弟的函数

return borrowBNode(f);

}

}

else//如果兄弟能够帮你

{

if (bronum < mynum)                    //如果我不是第一个

{

for (index = 1;index <= T->keynum;index++)

{

T->key[index + 1] = T->key[index];

T->ptr[index + 1] = T->ptr[index];

}

T->ptr[1] = T->ptr[0];

T->key[1] = f->key[mynum];

T->ptr[0] = b->ptr[b->keynum];

T->keynum++;

f->key[mynum] = b->key[b->keynum];

b->key[b->keynum] = 0;

b->ptr[b->keynum] = NULL;

b->keynum--;

}

else                                    //如果我是第一个

{

T->keynum++;

T->key[T->keynum] = f->key[1];

T->ptr[T->keynum] = b->ptr[0];

f->key[1] = b->key[1];

b->ptr[0] = b->ptr[1];

for (index = 1;index <= b->keynum;index++)

{

b->key[index] = b->key[index + 1];

b->ptr[index] = b->ptr[index + 1];

}

b->keynum--;

}

}

return OK;

}

/***

*  @name          Status deleteBTreeRecord(BTree &T, Record e)

*  @description    实现B树元素的删除

*  @return        成功返回OK,否则返回ERROR

*  @notice

***/

Status deleteBTreeRecord(BTree &T, Record e)

{

BTree p, q;

int num, temp, index;

Status find_flag;

if (T == NULL)

return ERROR;

find_flag = findBTree(T, p, temp, e.key);

if (find_flag == FALSE)

{

return FALSE;

}

if (find_flag == TRUE)

{

//deleteBTreeBNode(p,temp);

if (p->ptr[temp] == NULL)                //如果是叶子节点的话

{

for (index = temp;index <= p->keynum;++index)

{

p->key[index] = p->key[index + 1];

p->ptr[index] = p->ptr[index + 1];

}

p->keynum--;

if (p->keynum == (m + 1) / 2 - 2)

{

//调用借兄弟的函数

if (borrowBNode(p) == EMPTY) T = NULL;

else renewParent(T);

}

return OK;

}

else                                    //不是叶子结点的话

{

//遍历

findMax(p->ptr[temp - 1], q, num);//返回的q一定会是叶子节点

p->key[temp] = q->key[num];

q->key[num] = 0;

q->keynum--;

if (q->keynum == (m + 1) / 2 - 2)

{

//调用借兄弟的函数

if (borrowBNode(q) == EMPTY) T = NULL;

else renewParent(T);

}

return OK;

}

return OK;

}

return ERROR;

}

/***

*  @name          Status initBTree(BTree &t)

*  @description    初始化一个空B树

*  @return        成功返回OK

*  @notice

***/

Status initBTree(BTree &t)

{

t = NULL;

return OK;

}

/***

*  @name          Status test()

*  @description    针对数据结构实验做的测试函数

*  @return        成功返回OK

*  @notice

***/

Status test()

{

// 测试代码

int n, i;

int arr[BTREELENGTH];

BTree a;

Record  d;

srand((unsigned)time(NULL));

n = rand() % BTREELENGTH;

//scanf("%d", &n);                    //可以改为自己输入数据

printf("B树的阶为:%d,插入次数为:%d\n", m, n);

initBTree(a);

for (i = 0;i < n;i++)

{

d.key = rand() % MAXINT;

//scanf("%d", &d.key);            //可以改为自己输入数据

arr[i] = d.key;

if (insertBTree(a, d) == OK)

printf("第%d次插入%d:\n", i + 1, d.key);

else

printf("第%d次插入%d不成功:\n", i + 1, d.key);

print(a);

}

for (i = 0;i < n;i++)

{

d.key = arr[i];

if (deleteBTreeRecord(a, d) == OK)

printf("第%d次删除%d:\n", i + 1, d.key);

else

printf("第%d次删除%d不成功:\n", i + 1, d.key);

print(a);

}

return OK;

}

/***

主函数

***/

int  main()

{

test();

return 0;

}

BTree

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于你的第一个问题——如何在 C 语言中实现幂率变换和直方图均衡下的灰度变换,我可以给你一些参考的思路代码示例。 首先,幂率变换是一种常见的灰度变换方法,它可以增强图像的对比度和清晰度。幂率变换的公式如下: ``` g(x,y) = c * f(x,y)^r ``` 其中,`f(x,y)` 是原始图像的灰度值,`g(x,y)` 是变换后的图像灰度值,`r` 为幂率参数,`c` 为比例参数。 在 C 语言中实现幂率变换,可以使用如下的代码: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #define r 1.5 // 幂率参数 #define c 1.0 // 比例参数 int main(int argc, char* argv[]) { if (argc != 3) { printf("Usage: %s [input_file] [output_file]\n", argv[0]); return 1; } const char* infile = argv[1]; const char* outfile = argv[2]; FILE* fpin = fopen(infile, "rb"); FILE* fpout = fopen(outfile, "wb"); if (!fpin || !fpout) { printf("Failed to open file: %s\n", !fpin ? infile : outfile); return 1; } unsigned char header[54], data[3], *buf = NULL; int width, height, row, col, bpp, size, i, j; fread(header, 1, 54, fpin); width = *(int*)(header + 18); height = *(int*)(header + 22); bpp = *(short*)(header + 28) / 8; size = width * height * bpp; buf = (unsigned char*)malloc(size); fread(buf, 1, size, fpin); for (i = 0, row = 0; row < height; ++row) { for (col = 0; col < width; ++col, i += bpp) { for (j = 0; j < bpp; ++j) { data[j] = buf[i + j]; } int gray = (data[0] * 299 + data[1] * 587 + data[2] * 114 + 500) / 1000; int new_gray = (int)(c * pow(gray / 255.0, r) * 255 + 0.5); if (new_gray > 255) new_gray = 255; if (new_gray < 0) new_gray = 0; for (j = 0; j < bpp; ++j) { buf[i + j] = new_gray; } } } fwrite(header, 1, 54, fpout); fwrite(buf, 1, size, fpout); fclose(fpin); fclose(fpout); free(buf); return 0; } ``` 以上图像处理程序的功能为,读取一个 BMP 格式的图像文件,对其进行幂率变换,并输出到另一个图像文件中。程序使用的头文件包括 stdio.h、stdlib.h 和 math.h,主函数中先检查参数是否合法,然后读取图像文件的头部信息,分别获取图像的宽、高、位深和数据大小,再读取图像数据存储到一个缓冲区中。 之后,程序使用两重循环分别遍历图像的每个像素并进行幂率变换。对于每个像素,我们将其 R、G、B三个分量按照灰度权值调和公式计算出对应的灰度值,并进行幂率变换。变换后的灰度值可能超过 0-255 范围,因此需要进行截断处理。最后,我们将变换后的灰度值写回到缓冲区中。 最后,程序输出处理后的图像数据并释放缓冲区。注意,该程序的实现仅仅是一个示例,仍有很多需要改进和完善的地方。另外,如果需要进行图像的直方图均衡化操作,可以使用类似的思路和方法进行实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值