c语言集合除去相同元素,使用C语言去掉字符串集合重复元素

有一种最直接的方法可以去掉一个集合中重复的元素,这种方法据说就是“交给下面去做”,然而有时候,你自己动手去做一下也是不错的。如果交给下面去做,最直接的选择就是使用map,在java中,我们有HashMap,TreeMap等等实现了map接口的类可用,c++中,同样有STL的同类集合可以使用,在各类高级语言中,就更不必说了,然而在c中,就没有那么幸运了,很多东西需要你来自己实现。

根据《C语言内力修炼与软件工程》,用c语言自行实现这个东西,其实对于软件工程而言没有必要,然而可以训练一下自己,增加一些内力。我不认为自己是个高手,更非大侠,然而因为我懂得少,只能自己重新来做,真恨自己没有在5年前多学习一些编程语言。

先来简单分析一下需求,就是一个字符串集合中,去掉重复的字符串,换句话说就是每一个字符串只保留一个。题目没有说是否保持原有的字符串输入顺序,作为完美主义的我,我还是将其当成了一个隐含的需求。那么下一步就是将问题进行简化和转化,如果我们能将这一堆字符串进行排序,那么最终遍历这个排过序的字符串集合,发现和前一个相同的字符串就跳过不输出,对于排序,再简单不过了,至少N中排序算法,本文不讨论各种排序算法,只使用最简单的冒泡排序来分析。那么怎么保留原有的输入序呢?这也很简单,就是在排序元素中增加一个指向原有序的指针即可,另外还有一种方法,那就是排序过程仅仅是一个删除重复元素的过程,而不影响原有的输入序列,这个动态行为可以用二叉树的插入来实现,或者其它的AVL树以及红黑树都可以,本文不会去谈这几棵树的特性,只是用最简单的排序二叉树来分析。

我们知道,在二叉树插入中,首先要进行一次查找,现在要做的是,如果没有找到相同的,则插入,如果找到了相同的,则不插入,同时为该元素置入删除标识。代码如下:

// // main.c // dup-del // // Created by ya zhao on 11-12-17. // Copyright 2011年 __MyCompanyName__. All rights reserved. // #include #include struct sorted_order_str_map_with_thread { char *sorted_order_str; //保存排序后的字符串 char *normal_order_str; //保存原始字符串 int tag; //指示是否要删除 struct sorted_order_str_map_with_thread *self; //指向原始的位置 }; void sort(struct sorted_order_str_map_with_thread smwt[], const int size, int (*cmp)(void *, void *), void (*swap)(void *q1, void *q2)); int cmp_node(void *, void *); //比较函数,如果相同则将其tag位设置为0,标示要删除 int cmp_node(void *q1, void *q2) { int res; struct sorted_order_str_map_with_thread *cmp1, *cmp2; cmp1 = (struct sorted_order_str_map_with_thread*)q1; cmp2 = (struct sorted_order_str_map_with_thread*)q2; res = strcmp(cmp1->sorted_order_str, cmp2->sorted_order_str); if (res == 0) { struct sorted_order_str_map_with_thread *p = cmp2->self; p->tag = 0; } return res; } //交换函数,不光要交换元素,还要交换其self指针 void swap_node(void *q1, void *q2) { struct sorted_order_str_map_with_thread *swp1, *swp2,*temp; char *strTemp; swp1 = (struct sorted_order_str_map_with_thread*)q1; swp2 = (struct sorted_order_str_map_with_thread*)q2; strTemp = swp1->sorted_order_str; temp = (swp1->self); swp1->sorted_order_str = swp2->sorted_order_str; swp1->self = swp2->self; swp2->sorted_order_str = strTemp; swp2->self = temp; } //标准冒泡排序 void sort(struct sorted_order_str_map_with_thread smwt[], const int size, int (*cmp)(void *q1, void *q2), void (*swap)(void *q1, void *q2)) { int flag = 1; for (int i = 0; i < size - 1; i ++) { flag = 1; for (int j = 0; j < size - i - 1; j ++) { int res = 0; if ((res = cmp(&smwt[j], &smwt[j+1])) > 0) { swap(&smwt[j], &smwt[j+1]); flag = 0; } } if (flag == 1) break; } } int main (int argc, const char * argv[]) { int i = 0; //为了简化,下面使用了最恶心的初始化方法。方便复制粘贴 struct sorted_order_str_map_with_thread smwt[20] = {{NULL, NULL, 0 NULL}}; smwt[0].sorted_order_str =smwt[0].normal_order_str = "323"; smwt[0].self = &smwt[0]; smwt[0].tag = 1; smwt[1].sorted_order_str = smwt[1].normal_order_str="223"; smwt[1].self = &smwt[1]; smwt[1].tag = 2; smwt[2].sorted_order_str =smwt[2].normal_order_str= "723"; smwt[2].self = &smwt[2]; smwt[2].tag = 3; smwt[3].sorted_order_str =smwt[3].normal_order_str= "823"; smwt[3].self = &smwt[3]; smwt[3].tag = 4; smwt[4].sorted_order_str =smwt[4].normal_order_str= "123"; smwt[4].self = &smwt[4]; smwt[4].tag = 5; smwt[5].sorted_order_str =smwt[5].normal_order_str= "423"; smwt[5].self = &smwt[5]; smwt[5].tag = 6; smwt[6].sorted_order_str =smwt[6].normal_order_str= "123"; smwt[6].self = &smwt[6]; smwt[6].tag = 7; smwt[7].sorted_order_str =smwt[7].normal_order_str= "723"; smwt[7].self = &smwt[7]; smwt[7].tag = 8; smwt[8].sorted_order_str = smwt[8].normal_order_str="523"; smwt[8].self = &smwt[8]; smwt[8].tag = 9; smwt[9].sorted_order_str =smwt[9].normal_order_str= "823"; smwt[9].self = &smwt[9]; smwt[9].tag = 10; sort(smwt, 10, cmp_node, swap_node); //下面使用了最恶心的输出,经典### for (i = 0; i< 10; i++) { printf("###:%s tag:%d\n", smwt[i].normal_order_str, smwt[i].tag); } for (i = 0; i< 10; i++) { printf("@@@:%s tag:%d\n", smwt[i].sorted_order_str, smwt[i].tag); } for (i = 0; i< 10; i++) { if (smwt[i].tag != 0){ printf("@@@&&:%s\n", smwt[i].normal_order_str); } } return 0; }

下面的一种方法使用了标准的二叉树插入,注意,插入仅仅是为了删除重复元素,实际上,各种语言各种库的标准Map实现很多也是使用了树,比如java.util中的TreeMap就是使用了红黑树。下面直接给出代码,基于排序二叉树的代码:

// // main.c // test-xcode // // Created by ya zhao on 11-12-17. // Copyright 2011年 __MyCompanyName__. All rights reserved. // #include #include #include struct string_node { char *string; int tag; //标示是否被删除 }; //标准排序二叉树 struct string_tree { struct string_node *strn; struct string_tree* left,*right; }; struct string_tree *add_node(struct string_tree *, struct string_node *str, int (*cmp)(struct string_node *, struct string_node *)); int normalcmp(struct string_node *, struct string_node *); //简单的字符串比较 int normalcmp(struct string_node *n1, struct string_node *n2) { return strcmp (n1->string,n2->string); } int main(int argc, char **argv) { int j = 0; for (j = 0; j < 1; j++) { struct string_tree *root; struct string_node str[9] = {{"123",1},{"456",1},{"234",1},{"123",1},{"347",1},{"129",1},{"888",1}, {"568",1}, {"456",1}}; root = NULL; int i = 0; while (i<9) { root = add_node(root, &str[i], normalcmp); i ++; } i=0; while (i<9){ if (str[i].tag) { printf("&&&:%s\n", str[i].string); } i++; } } return 0; } struct string_tree *add_node(struct string_tree *p, struct string_node *new, int (*cmp)(struct string_node *n1, struct string_node *n2)) { int cmp_ret; if (p == NULL) { p = (struct string_tree *)calloc(1, sizeof(struct string_tree)); p->strn = (struct string_node*)calloc(1, sizeof(struct string_node)); memcpy(p->strn, new, sizeof(struct string_node)); p->left = p->right = NULL; } else if ((cmp_ret = cmp(new, p->strn)) == 0) { new->tag =0; } else if (cmp_ret < 0) { p->left = add_node(p->left, new, cmp); } else { p->right = add_node(p->right, new, cmp); } return p; }

经过测试,自己实现的上述算法效率还可以,当然这里不该去比较效率,留下个思路即可,在没有库可用的情况下,也可以自己实现它。在现实中,特别是在软件工程中,还是使用现成的map比较好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/260049.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Zynq7000系列之芯片引脚功能综述

很多人做了很久的FPGA&#xff0c;知道怎么去给信号分配引脚&#xff0c;却对这些引脚的功能及其资源限制知之甚少&#xff1b;在第一章里对Zynq7000系列的系统框架进行了分析和论述&#xff0c;对Zynq7000系列的基本资源和概念有了大致的认识&#xff0c;然而要很好地进行硬件…

python模拟购物车购物过程_python实现购物车+ATM机 第五天

模拟实现一个ATM 购物商城程序1.额度 15000或自定义2.实现购物商城&#xff0c;买东西加入 购物车&#xff0c;调用信用卡接口结账3.可以提现&#xff0c;手续费5%4.每月22号出账单&#xff0c;每月10号为还款日&#xff0c;过期未还&#xff0c;按欠款总额 万分之5 每日计息5…

C#使用Cookie方法

代码Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> //写入protected void Button1_Click(object sender, EventArgs e){HttpCookie cookienew HttpCookie("MyCook");//初使化并设置Cookie的名称DateTime…

智能手机计步算法c语言实现,【转载】智能手机计步器算法的实现

现在的智能手机嵌入了一些微小的传感器&#xff0c;比如重力传感器、光传感器、声音传感器等。如何有效地利用这些传感器来开发一些应用&#xff0c;是一个值得深入研究的课题。比如开发医疗健康的应用、运动量监视器等。本文采用htc Touch Pro智能手机的重力传感器来开发一款监…

vue点击按钮怎么跳转图片_vue-router组件里面点击一个按钮跳转到一个新的组件该怎么实现...

展开全部直接修改地址栏中的路由地址即可&#xff1a;{{msg}}var testLogin Vue.component("login",{template:这是我的登录页面})var testRegister Vue.component("register",{template:这是我的注册页面})//配置路由词典//对象数组const myRoutes [//…

Arduino教程资料汇总(8月22日悄悄跟新了一下)

http://www.geek-workshop.com/thread-985-1-1.html 本帖最后由 迷你强 于 2013-8-31 12:36 编辑 F-101 arduino基础套件使用资料 Arduino入门教程--课前准备--Arduino驱动安装及1.0 IDE菜单介绍Arduino入门教程--第一课--板载Led闪烁实验Arduino入门教程--第二课--第一次面包板…

HTML5/CSS3系列教程:HTML5 区域(Sectioning)的重要性

日期&#xff1a;2013-2-4 来源&#xff1a;GBin1.com 不管你以前在web页面布局中如何称呼它们 - “区域”还是“块”&#xff0c;我们一直都在布局中将页面分成可视的不同区域。但真正的问题在于我们并没有使用任何正确的工具来实现。一般情况下我们使用典型的网格来划分页头…

CoreAnimation —— CAReplicatorLayer(拷贝图层)

2019独角兽企业重金招聘Python工程师标准>>> CAReplicatorLayer是一个layer容器&#xff0c;会对其中的subLayer进行一些差异处理&#xff08;它的子layer都可以拷贝&#xff09; 属性&#xff1a; //拷贝的次数 property NSInteger instanceCount; //是否开启景深效…

c语言用数组写密码程序,想程序高手求助--用C语言来编辑一个输入密码的程序...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼/*--------实现密码的隐式输入-----------------*/inputpw(char *password,int len) /*len为密码长度*/{int i0; /*密码数组索引值,同时也表示记录已显示*的数目*/char ch;fflush(stdin); /*清洗流&#xff0c;以防妨碍密码正确输入…

ps流 转发_RTP协议全解析(H264码流和PS流)(转)

&lbrack;LeetCode&rsqb; Arranging Coins 排列硬币You have a total of n coins that you want to form in a staircase shape, where every k-th row must ha ...使用Jenkins可持续集成maven项目首先下载最新的Jenkins的war包,放在tomcat的webapps的目录下,然后运行,例…

android 接收短信代码,短信接收功能实现的代码

其中包含了widget必备的要素以及对应文件分别为&#xff1a;appwidgetprovider--------------------------SmsWidget.javawidget的config--------------------------SmsWidgetConfig.javawidget引发的app-------------------------SmsAider.javaappwidgetproviderinfo---------…

使用MeanJS Yeoman Generator

1、首先全局安装该生成器 sudo npm install -g generator-meanjs 2、为项目创建一个路径 mkdir xmen && cd xmen 3、创建app yo meanjs 根据提示&#xff0c;输入应用名&#xff0c;描述&#xff0c;关键词&#xff0c;是否创建crud例子。。 4、运行app sudo NODE_ENVd…

Entity Framework With Oracle

虽然EF6都快要出来了&#xff0c;但是对于Oracle数据库&#xff0c;仍然只能用DB first和Model First来编程&#xff0c;不能用Code First真是一个很大的遗憾啊。 好了&#xff0c;废话少说&#xff0c;我们来看看EF中是如何用DB first和Model First来对Oracle编程的。 首先我们…

(三)Maven仓库介绍与本地仓库配置

1.Maven本地仓库/远程仓库的基本介绍 示意图&#xff1a; 本地仓库是指存在于我们本机的仓库&#xff0c;在我们加入依赖时候&#xff0c;首先会跑到我们的本地仓库去找&#xff0c;如果找不到则会跑到远程仓库中去找。对于依赖的包大家可以从这个地址进行搜索&#xff1a;http…

大数据时代下的迁移学习_继深度学习后,下一个热点技术是迁移学习

最早提出大数据时代到来的是知名咨询公司麦肯锡&#xff0c;麦肯锡称&#xff1a;“数据&#xff0c;已经渗透到当今每一个行业和业务职能领域&#xff0c;成为重要的生产因素。人们对于海量数据的挖掘和运用&#xff0c;预示着新一波生产率增长和消费者盈余浪潮的到来。”其实…

手机广告投放(phone advertising)唯一标识

手机标示&#xff0c;为了识别用户&#xff0c;方面advertising。 使用设备id&#xff0c;相当于暴露用户隐私。慢慢已不允许使用。、 &#xff08;长时间跟踪用户无异于暴露用户隐私&#xff0c;虽然大量数据适合兴趣建模&#xff0c;广告个性化推荐。但复杂多样会降低总体的准…

android分辨率比例成像,像素不是唯一 决定成像效果你必知的真相

像素并不是唯一如今不少人在选购一部手机时&#xff0c;非常重视手机摄像头的像素大小&#xff0c;因为一部高像素的手机可以为不少喜爱拍照的人省去买单反的费用&#xff0c;而且携带起来也非常方便。不过&#xff0c;手机并不能与专业的单反相机相比&#xff0c;成像效果并不…

vim——打开多个文件、同时显示多个文件、在文件之间切换

打开多个文件&#xff1a; 1.vim还没有启动的时候&#xff1a; 在终端里输入 vim file1 file2 ... filen便可以打开所有想要打开的文件 2.vim已经启动 输入 :open file 可以再打开一个文件&#xff0c;并且此时vim里会显示出file文件的内容。 同时显示多个文件&#xff1a; :s…

Android底部导航栏实现(一)之BottomNavigationBar

BottomNavigationBar这个控件的使用之前已经写过&#xff0c;这里不再赘述&#xff0c;详情请参考BottomNavigationBar的使用。 下面直接上代码&#xff1a; 初始化及相关设置&#xff1a; mBottomNavigationBar (BottomNavigationBar) view.findViewById(R.id.bottom_navigat…

jq 组装数组_Jquery 数组操作

1、数组的创建var arrayObj new Array(); //创建一个数组var arrayObj new Array([size]); //创建一个数组并指定长度&#xff0c;注意不是上限&#xff0c;是长度var arrayObj new Array([element0[, element1[, ...[, elementN]]]]); 创建一个数组并赋值要说明的是&…