将txt文件的十六进制按照每个字节创建链表并实现排序功能。

继上一期写的博文:https://blog.csdn.net/weixin_47604497/article/details/126548679?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22126548679%22%2C%22source%22%3A%22weixin_47604497%22%7D

 

上期已经实现了将十六进制转二进制的操作,现在这期写的是将txt文件里的十六进制的每两个字节合成一个十六进制的一个字节,把每个字节当做一个节点建立链表。再将他们进行排序,这里面用到的是快速排序法,快速排序不懂原理的童鞋可以先看这个视频:https://www.bilibili.com/video/BV1at411T75o?spm_id_from=333.337.search-card.all.click&vd_source=b9705750db39c27d796acd63578ceb55

快速排序法用数组遍历的方法排序是很简单的,若要用链表遍历,难度会变大点,因此要实现快速排序法,需要用到数组的思想实现快速排序。我这里封装了一个seekLinkAdd函数,通过链表的遍历能够找到某个元素的值,然后返回某个元素的地址。调用这个函数时用*取值符,能得到某个元素的值。快速排序中将某元素的地址传过来,再对里面的值进行修改,这样就可以实现数组的快速排序思想。

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include<assert.h>

struct charLink
{	
	int c;
	struct charLink *next;
	
};

uint32_t a = 0;
uint32_t cnt = 0;
struct charLink *head = NULL;
struct charLink *new = NULL;
int out, in;


//尾插法动态添加结点
struct charLink *addLink(struct charLink *head,struct charLink *new)
{	
	struct charLink *p =head;
	if(head == NULL)
	{
		return new;
	}
	//遍历到最后一个
	while(p->next != NULL )
	{	
		p = p->next;
	}
//然后让新节点作为头结点
		p->next = new;
		
	return head;
}
//统计结点个数
int sumNode(struct charLink* head)
{
	int data=0;
	while(head != NULL)
	{
		data++;
		head = head->next;
	}
	
	return data;
}
//查找某个元素的地址
int* seekLinkAddr(struct charLink *head,int idx)
{
	int data = sumNode(head);
	//printf("idx = %d\n",idx);
//断言,如果不满足0=<idx<data,编译器会报错
	assert(idx>=0 && idx< data);
	struct charLink *p = head;
//遍历到某个元素的位置
	while(p !=NULL && idx !=0)
	{
			p=p->next;
			idx--;
	}
//然后返回某个元素的地址
	return &(p->c);
}
//打印链表
void printLink(struct charLink*head)
{
	struct charLink *point = head;
	while(point != NULL){	
		printf("%02x\n",point->c);
		point = point->next;	
	}
	putchar('\n');
}

//字节的合成
int handChar(char *filename,FILE *fp)
{
	
	int data[2];
	while (1)
	{
		out = fgetc(fp);
		if (out == EOF)
		{
			if (a == 1)
			{
				fputc(data[0], fp);
				cnt++;
			}
			break;
		}
		
		else if (out == ' ' || out == '\n' || out == '\r')
		{
			continue;
		}
		else if (out >= '0' && out <= '9')
		{
			out = out - '0';
		}
		else if (out >= 'a' && out <= 'f')
		{
			out = out - 'a' + 10;
		}
		else if (out >= 'A' && out <= 'F')
		{
			out = out - 'A' + 10;
		}
		else
		{
			printf("存在其他二进制文件!\n");
			fclose(fp);
			return -1;
		}
		
		data[a] = out;
		a++;
		if (a == 2)
		{
			a = 0;
			
			new = (struct charLink*)malloc(sizeof(struct charLink));
			new->next=NULL;
			new->c = (data[0] * 16) + data[1];
			
			fputc(new->c, fp);
			head = addLink(head,new);
			cnt++;
		}
	}
	
	return 1;
	fclose(fp);
	
}
//快速排序法
void quickSort(struct charLink* head,int left,int right)
{
	int i = left;
	int j = right;
	//int temp;
//选第一个为准基数
	int pivot=*seekLinkAddr(head,i);
	if(i>=j)
	{
		return ;
	}
	
	while(i<j)
	{
		
		//printf("i = %d,j = %d\n",i,j);
		//printf("j = %02x\n",*seekLinkAddr(head,i));
//如果这个数比准基数大,则右边退一个
		while( *seekLinkAddr(head,j) >= pivot && i<j)
		{
			
			j--;
		}
		//否则比他小的话就将i的位置赋值j的值

		*seekLinkAddr(head,i) = *seekLinkAddr(head,j);
		//如果这个数比准基数大,则左边前进一个
		while( (*seekLinkAddr(head,i)) <= pivot && i<j)
		{
			i++;
		}
		//否则的话将j的位置赋值i的值
		*seekLinkAddr(head,j)=*seekLinkAddr(head,i);
		
		*seekLinkAddr(head,i) = pivot;
//将左边递归,重复以上动作
		if(i-1>left){  //注意 要写i-1<left  这个条件,不然会出现段错误
			quickSort(head,left,i-1);
		}
//将右边递归,重复以上动作
		if(i+1<right){
			quickSort(head,i+1,right);
		}
		//printf("i = %d,j = %d\n",i,j);

	}
	
	
}

int main()
{
	FILE* fp;
	int ret=0;
	int i;
	char filename[12]="src.txt";
	
	/*if(argc <=1)
	{
		printf("please input ./a.out xxx.txt\n");
	}*/

	fp = fopen(filename, "r");
	if (fp ==NULL)
	{
		//printf("%s cannot be open!\n", argv[1]);
		return -1;
	}
	//字节的合成
	handChar(filename,fp);
//节点数
	int len = sumNode(head);
	
	//head = twoSort(head);
	//BubbleSort(head);
	quickSort(head,0,len-1);
	printf("done!\n");
//打印链表
	printLink(head);
	
	return 0;
}

实现的效果显示:

  • 10
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值