模糊查找算法
输入元素,便可查找数据结构(链表,数组等等都可)中所有含有输入元素的元素
例:链表中含有{“123”, “1234”, "12345}
查找1,则可输出“123”, “1234”, “12345”。
查找4,则可输出“1234”,“12345”。
C语言实现
这里我的例子是通过卡名(字符串类型)在链表中寻找卡信息,返回值Card*为符合条件的数组,形参pName为要查找的字符串,pIndex记录符合条件数。
算法原理是获取输入字符串的长度keyLen,遍历链表,将每个节点的卡名字符串都转换成keyLen长度的子串数组,再一一比较,有相同则将该节点保存在cards数组中,遍历结束后返回cards数组。
测试代码:
//卡信息
typedef struct Card {
char aName[18];//卡号
char aPwd[8];//密码
int nStatus;//卡状态 0-未上机;1-正在上机;2-已注销;3-失效
time_t tStart;//开卡时间
time_t tEnd;//截止时间
float fTotalUse;//累计金额
time_t tLast;//最后使用时间
int nUseConst;//使用次数
float fBalance;//余额
int nDel;//删除标记:0-未删除;1-已删除
} Card;
Card* queryCard(const char* pName, int* pIndex) {
getCardByB();//获得卡信息,将保存的卡信息读入链表
Card* cards = (Card*)malloc(sizeof(Card)*MAX_QUERY);//储存符合条件的元素
int index = 0;//记录符合元素个数
int keyLen = strlen(pName);//所查卡号长度
//遍历链表
CardNode* q = cardLinkList->next;
typedef struct {
char son[18];
} myArray1;
while (q != NULL) {
int qLen = strlen(q->data.aName);//链表中卡号长度
if (qLen < keyLen) {//卡号长于所查卡号才可查
q = q->next;
continue;
}
int strNum = qLen - keyLen + 1;//子串数量
//子串
myArray1* str = (myArray1*)malloc(sizeof(myArray1)*strNum);
//给子串赋值
int kIdx = 0;//控制总子串角标
int mIdx = 0;//控制父串开始处
int nIdx = 0;//控制父串角标
int jIdx = 0;//控制小子串角标
for (mIdx = 0; mIdx < (qLen - keyLen + 1); mIdx++) {//移动开始头
nIdx = mIdx;
for (jIdx = 0; jIdx < keyLen; jIdx++) {//给小子串复制
str[kIdx].son[jIdx] = q->data.aName[nIdx];
nIdx++;
}
str[kIdx].son[jIdx] = '\0';
kIdx++;
}
//挨个比较
for (int i = 0; i < strNum; i++) {
if (strcmp(str[i].son, pName) == 0) {
cards[index] = q->data;
index++;
break;
}
}
q = q->next;
}
(*pIndex) = index;
//清空链表,防止再次查询时重复
cardListClean(&cardLinkList);
return cards;
}
测试截图:
Java实现
这里我的例子是通过书名(字符串类型)在Vector数组中寻找图书信息,返回值为Vector符合条件的Vector数组,形参为储存信息的Vector数组。
算法主体思想与C语言相同,只在语法上有些许不同,使用了String和StringBuilder类 。
测试代码:
//查找一本书,若存在输出Book,不存在输出null
public Vector<Book> search(Vector<Book> books) {
Vector<Book> book = new Vector<Book>();//储存查找信息
//建立一个从键盘接收数据的扫描器
Scanner scanner = new Scanner(System.in);
System.out.print("请输入查询书籍的书号:");
String num = scanner.next();
int keyLen = num.length();//所查卡号长度
for(Book e : books) {
int qLen = e.getName().length();//数组链表中卡号长度
if (qLen < keyLen) {//卡号长于所查卡号才可查
continue;
}
int strNum = qLen - keyLen + 1;//子串数量
//子串
String[] str = new String[strNum];
//给子串赋值
int kIdx = 0;//控制总子串角标
int mIdx = 0;//控制父串开始处
int nIdx = 0;//控制父串角标
int jIdx = 0;//控制小子串角标
for (mIdx = 0; mIdx < (qLen - keyLen + 1); mIdx++) {//移动开始头
nIdx = mIdx;
for (jIdx = 0; jIdx < keyLen; jIdx++) {//给小子串复制
StringBuilder strB = new StringBuilder(18);
strB.append(e.getName().charAt(nIdx));
str[kIdx] = strB.toString();
nIdx++;
}
kIdx++;
}
//挨个比较
for (int i = 0; i < strNum; i++) {
//符合条件则放入book数组
if (str[i].equals(num)) {
book.add(e);
break;
}
}
}
return book;
}
测试截图:
其实也可以用字符串数组char[]实现
Java中String类不可修改,StringBuider类可修改,使用StringBuider生成子串后使用toString函数转化为String类。
特别注意StringBuider中setCharAt(int index, Char ch)函数只能在有值时修改值,无值时要使用append(Char ch)函数添加,否则会抛出NullPointerException错误(setCharAt(int index, Char ch)函数在index为负数或超出字符串长度时抛出此类错误)。