二叉树递归遍历查找问题 10C

如题,利用递归在二叉树中查找一个值,若二叉树中存在该值则输出1,否则输出0.我想用遍历进行查找,但是却无法进行,代码如下:
#include
#include
#include
#include
using namespace std;

class Tree_Node {
public:
char data; //数据
Tree_Node *left;
Tree_Node *right;

Tree_Node(char da) {
    left = right = NULL;
    data = da;
}

};
//删除二叉树 内联函数 减少时间花销
inline void free_Tree(Tree_Node *p) {
if(p -> left != NULL) {
free_Tree(p -> left);
}
if(p -> right != NULL){
free_Tree(p -> right);
}
delete(p);
}

void post_order(Tree_Node *p) {
if(p) {
post_order(p -> left);
post_order(p -> right);
cout << p -> data;
}
}

bool search(Tree_Node *p, char k) {
if(p -> data == k) {
return true;
}
if(p) {
search(p -> left, k);
search(p -> right, k);
}
}

void build_Tree(Tree_Node &p, string a) {
char ch;
int index = 0;
stack <Tree_Node
> s;
// stack s2;
ch = a[index++];
while(ch != '\0'){
p = new Tree_Node(ch);
if(s.size() > 0) {
p -> left = s.top();
s.pop();
}
s.push(p);
ch = a[index++];
if(ch == '\0') {
break;
}
if(ch != '\0' && s.top() -> left == NULL) {
p = s.top();
s.pop();
p -> left = new Tree_Node(ch);
ch = a[index++];
s.push(p);
}
if(ch == '\0') {
break;
}
if(ch != '\0') {
p = s.top();
s.pop();
p -> right = new Tree_Node(ch);
s.push(p);
ch = a[index++];
s.push(p);
}
if(ch == '\0') {
break;
}
}
p = s.top();
s.pop();
}

int main() {
string s;
char c;
Tree_Node *tree;
cin >> s >> c;
build_Tree(tree, s);
post_order(tree);
cout << endl;
if(search(tree, c)) {
cout << 1 << endl;
}
else {
cout << 0 << endl;
}
cout << 1 << endl;
free_Tree(tree);
return 0;
}
还有一个问题是不知道失败的判定条件,请大神帮帮忙修改一下代码

4个回答

写代码注释多一点让人一眼能看懂。

查找那里出错了,结果没有通过回溯传递。

我给你改一下

bool search(Tree_Node *p, char k) {
if(p -> data == k) {
return true;
}

return p ? search(p -> left, k) || search(p -> right, k) : false;
}

至于建树的话看你写的太冗长就没看~~

wang19950207
CimZzz 之前写的有空指针异常,这次不会错了
大约 3 年之前 回复
wang19950207
CimZzz 回复Shigure_Q: if(!p)return false;if(p -> data == k) { return true; } return search(p -> left, k) || search(p -> right, k); }
大约 3 年之前 回复
Shigure_Q
Shigure_Q 还是有问题啊...不能正确返回,输入之后,后序遍历输出完,还没判断是否找到就直接出错了
大约 3 年之前 回复

把你的错误提示贴出来,看看。

bool search(Tree_Node *p, char k) {
if(p -> data == k) {
return true;
}
if(p) {
search(p -> left, k);
search(p -> right, k);
}
}

你这代码一看就是错的啊,p如果为空呢,你都木有考虑。。。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
C语言二叉树的节点查找问题(递归方法)
用的递归的方法查找元素 有点类似于二叉树建立 代码如下 ``` struct node *search(struct node *n,int v){//查找 struct node *p; p=n; if(p->value==v){//找到 return p; } else if(v<p->value){//左边部分查找 if(p->left==NULL) return NULL;//未找到 else{ p=p->left; search(p,v); } } else{//v>p->value,右边部分查找 if(p->right==NULL) return NULL;//未找到 else{ p=p->right; search(p,v); } } } ``` main方法中:point=search(root,20); 用这种方法 总是返回根节点的值 而不是要查找的值或者null
求二叉树问题的C程序代码
//从终端输入一个整数序列,构建一棵允许具有重复结点的二叉排序树(左子树元素小,右子树不小): //(1) 使用依次插入元素的方法(InsertBST)构建二叉排序树; //(2) 分别写出二叉树的前序、中序、后序遍历递归算法; //(3) 写出前序遍历序列的非递归算法(使用以前写好的堆栈代码); //(4) 使用递归算法求该二叉树中叶子结点和非叶子结点的个数; //(5) 使用递归算法求该二叉树的高度; //(6) 层次遍历该二叉树(使用以前写好的队列代码); //(7) 从终端输入一个整数,查找这个整数是否在该二叉树中,成功返回true,否则false(要求使用非递归); //(8) 销毁这个二叉树,释放其中的每一个结点;
C++二叉树应用问题求助
实习三 二叉树及其应用 题目一:二叉树基本算法的实现 功能要求: ➢键盘输入二叉树结点前序序列,创建- -棵二叉 树 ➢实现SwapTree方法,以根结点为参数,交换每; 个结点的左子树和右子树(提示:前序递归) ➢实现Find方法,查找值为key的结点,并输出该 结点的所有祖先结点必你可以选择: ➢对BinaryTree模板进行功能扩 充; ➢自己定义并实现二叉树类 二叉树的创建要求 ✧要求键盘输入二叉树前序序列(程序5.12) ✧空结点以#表示; 前序: ABC##DE#G##F### A--------# | B------------D------------F---------# | | | | | # C---# E-----G------# | | | # # #
根据前序和中序非递归创建二叉树
怎样才能创建二叉树?传入参数T后,T不断被改变,我只想创建T的子树。然后以T为头节点。 struct BTNode { char data; BTNode *lchild ; BTNode *rchild; //左右孩子指针 } ; typedef BTNode *BT; /*由先序和中序非递归创建二叉树*/ void CreatBT2(BT &T, string preStr, string inStr) { stack<BT> stack; int index1,index2,preStrflag[N]; int i=0,j=0,k,m; preStr = preStr + '#'; //由于先序序列采用字符串形式,末尾加上#便于处理 while (preStr[j] != '#') {/*while循环将先序对应的数组全部标记为0*/ preStrflag[j]=0; j++; } if (preStr.length() == 0 || inStr.length() == 0) {/*处理特殊情况*/ T = NULL; return; } else {/*依次对先序序列中的每个字符进行存储,若一个*/ T = new BTNode; T->data = preStr[i]; preStrflag[i]=1; i++; stack.push(T); while (preStr[i] != '#') { preStrflag[i]=1; index1 = inStr.find(preStr[i]); index2 = inStr.find(preStr[i-1]); if (index1< index2) {/*处理:如果在先序中为...AB...,中序中为..B..A..*/ T=T->lchild; T=new BTNode; T->data = preStr[i]; stack.push(T); } else if (index1 == index2 + 1) {/*处理:如果在先序中为...AB...,中序中为..AB..*/ T=T->rchild; T=new BTNode; T->data = preStr[i]; stack.push(T); } else {/*处理:如果在先序中为...AB...,中序中为..A..B..*/ k = inStr.find(preStr[i])-1; m = preStr.find(inStr[k]); while (preStrflag[m] == 0) {/*在中序中依次往前遍历,查找第一个已存在树中的字符*/ k--; m = preStr.find(inStr[k]); } while (inStr[k] != T->data){ T= stack.top(); stack.pop(); } T=T->rchild; T=new BTNode; T->data = preStr[i]; stack.push(T); } i++; } } }
在查找方面二叉排序树效率与顺序查找的效率谁高(这里一般二叉排序树 不是指平衡二叉树)
写二叉排序树 ,它的作用是查找,过程是 一个值一个值插入创建二叉树,这样就顺带排序了,然后查找,,,可是为什么不直接在插入时候每一个节点和key.value比较一下呢,,,创建完二叉树还要递归查找多麻烦,那样的话似乎和直接用线性表顺序查找 有个p区别。。。 **顺序查找的时间复杂度是O(n),创建二叉排序树的时间复杂度是O(nlog2n),然后二叉排序树查找是O(log2n)** **O(nlog2n)+O(log2n) 怎么看都比O(n)大的样子啊。**
JAVA数据结构 用栈替换所有与pattern匹配的子树为bitree
问题:改了很多次,左边的树不匹配,但是右边的树匹配,怎么回到左节点看接下来的树是否匹配啊!问题应该在replaceALL方法里。 ![图片说明](https://img-ask.csdn.net/upload/201912/28/1577507308_187767.jpg) ![图片说明](https://img-ask.csdn.net/upload/201912/28/1577506948_684289.png) ``` //10-24 以中根和后根遍历序列构造二叉树,替换所有与pattern匹配的子树为bitree。 public class BinaryTree<T> { public BinaryNode<T>root; public BinaryTree() { this.root = null; } public boolean isEmpty() //判断是否是空 { return this.root == null; } public String toString()//输出带空子树先跟序列 { return toString(this.root); } public String toString(BinaryNode<T>p) { if(p==null) return "^"; return p.data.toString()+""+toString(p.left)+toString(p.right); } public BinaryTree(T inlist[],T postlist[]) { this.root=BinaryTreecreate(inlist,0,inlist.length-1,postlist,0,postlist.length-1); } //由后根遍历的次序可知,该二叉树的根是potlist[n-1];改节点必定在中根次序中 //由中根遍历次序可知,Inlist[i]节点前段节点在根的左子树上,inlist[i]后的所有节点在根节点的右子树上 private BinaryNode<T> BinaryTreecreate(T[] inlist, int inbegin, int inend, T[] postlist, int postbegin, int postend) { if (postbegin < 0 || inbegin > inend) //递归结束条件 return null; BinaryNode<T> p = new BinaryNode<T>(postlist[postend]); int j = inbegin; //标记查找到的根结点的位置 while (j <= inend&&inlist[j] != postlist[postend]) { //遍历查找 j++; } p.left = BinaryTreecreate(inlist, inbegin, j - 1, postlist, postbegin, postbegin + j - inbegin - 1); //递归构造左子树 p.right = BinaryTreecreate(inlist, j + 1, inend, postlist, postbegin + j - inbegin, postend - 1); ////递归构造右子树 return p; } public BinaryTree(T[] prelist)//构造二叉树,prelist数组指定二叉树标明空子树的先根遍历序列 { this.root=create(prelist); } //以从i开始的标明空子树的先根序列,创建一颗以prelist[i]为根的子树,返回根结点,递归方法 private int i=0; private BinaryNode<T>create(T[] prelist) { BinaryNode<T>p=null; if(i<prelist.length) { T elem=prelist[i]; i++; if(elem!=null) //不能elem!="kong",因为T不一定是String { p=new BinaryNode<T>(elem); //创建叶子结点 p.left=create(prelist); //创建P的左子树,递归调用 p.right=create(prelist); //创建P的右子树,递归调用 } } return p; } //比较 public boolean equals(BinaryNode<T> p,BinaryNode<T> q) { return (p==null&&q==null)||(p!=null&&q!=null)&&(q.data.equals(p.data))&& equals(p.left,q.left)&&equals(p.right,q.right); } //对象复制 BinaryTree(BinaryTree<T> bitree) //实现BinaryTree<T>二叉树类声明的深拷贝构造方法 { this.root = copy(bitree.root); } private BinaryNode<T> copy(BinaryNode<T> p) //方法实现 { BinaryNode<T> q = null; if (p != null) { q = new BinaryNode<T>(p.data); q.left = copy(p.left); q.right = copy(p.right); } return q; } public void replaceAll(BinaryTree<T> pattern, BinaryTree<T> bitree) { if(equals(pattern)) this.root=this.copy(bitree.root); else ** this.replaceall(this.root,pattern.root,bitree.root); ** //可不写 } **_ public void replaceall(BinaryNode<T> p,BinaryNode<T> pattern,BinaryNode<T> bitree) //parent指向this的结点;pattern指向pattern的结点;bitree指向bitree的结点; { //parent指向this的结点;p指向pattern的结点;m指向bitree的结点; System.out.print("替换后:"); //优先遍历的非递归算法 P154 LinkedStack<BinaryNode<T>>stack=new LinkedStack<BinaryNode<T>>();//创建的这个空栈为链式栈,使用单链表存储数据且实现栈接口 P91 while(p!=null||!stack.isEmpty())//P非空或栈非空时 { if( p!= null&&pattern!=null) { if(this.equals(p.left, pattern)) { // System.out.print(pattern); p.left=this.copy(bitree); // stack.push(p); // p=p.left; } if(this.equals(p.right, pattern)) { // System.out.print(pattern); p.right=this.copy(bitree); p=stack.pop(); // p=p.right; } else { // // System.out.print(p.data); stack.push(p); p=p.left; } } //p==null&&! if(stack.isEmpty()||p==null) { // // System.out.print("^"); // p=stack.pop(); // P指向出栈结点 if(stack.isEmpty()) ** p=p.right; // 进入右子树** else if (p==null) { p = stack.pop(); p = p.right; } } // System.out.print(""); //} } }**_ public static void main(String args[]) { String[] parent={"A","B","D",null,"G",null,null,"D",null,"G",null,null,"C","E",null,null,"F","H",null,null,"D",null,"G"}; String[] inlist={"D","G","B","A","E","C","H","F"}; //中根次序 String[] postlist={"G","D","B","E","H","F","C","A"}; //后根次序 String[] pattern1={"D",null,"G"}; String[] bitree1={"M","D",null,"G"}; BinaryTree<String> values=new BinaryTree<String>(parent); BinaryTree<String> pattern=new BinaryTree<String>(pattern1); BinaryTree<String> bitree=new BinaryTree<String>(bitree1); BinaryTree<String> tree=new BinaryTree<String>(inlist,postlist); System.out.println("构造出来的二叉树以先根次序输出为:"+tree); System.out.println("替换前树values的序列: "+values); //输出替换前树values的序列 System.out.println("pattern序列: "+pattern); System.out.println("bitree序列: "+bitree); ** values.replaceAll(pattern,bitree); //替换** // System.out.print(values); //System.out.println("替换后树values的序列: "+values); //输出替换后树values的序列 } } ```
利用二叉排序树可以实现集合的插入,删除和查找操作求怎么把只能输入数值转换成英文单词的查找
**如何改动数值为英文单词,求大神指教** #include<iostream> #include <vector> using namespace std; typedef struct TreeNode//声明树的结构 { int key;//存放关键字 struct TreeNode *left;//存放左子树的指针 struct TreeNode *right;//存放右子树的指针 }treeNode; class BiSortTree { public: BiSortTree(void); void desplayTree(void);//显示这个树 void insertTree(int key);//在树中插入一个结点 int deleteTree(int key);//在树中删除一个结点 treeNode* searchTree(int key);//在树中查找一个结点 ~BiSortTree(); private: treeNode* buildTree(treeNode* head,int number);//建立一个树 treeNode* search(treeNode* head ,int key);//查找 treeNode* BiSortTree::searchParent(treeNode* head,treeNode* p);//查找出p的父亲节点的指针 treeNode* BiSortTree::searchMinRight(treeNode* head);//找到右子树中最小的节点 void showTree(treeNode* head);//显示 void destroyTree(treeNode* head);//删除 treeNode *Head; }; BiSortTree::BiSortTree() { cout<<"建立一棵二叉排序树,请输入你要建树的所有数(以-1 作为结束标志!): "<<endl;//循环输入调用BuildTree函数 Head=NULL; int number; cin>>number; while(number!=-1) { Head=buildTree(Head,number); cin>>number; } } treeNode* BiSortTree::buildTree(treeNode* head,int number)//建立一个二叉排序树 { treeNode *p; p=new treeNode; p->key=number; p->left=p->right=NULL; if(head==NULL) { return p; } else { if(p->key<head->key) head->left=buildTree(head->left,number); else head->right=buildTree(head->right,number); return head; } } void BiSortTree::insertTree(int key)//插入一个结点通过调用BuildTree 函数 { Head=buildTree(Head,key); } treeNode* BiSortTree::searchTree(int key)//查找一个节点调用search函数 { return search(Head,key); } treeNode*BiSortTree::search(treeNode* head ,int key)//查找 { if(head==NULL) return NULL; if(head->key==key) return head; else { if(key<head->key )//如果所要查找的关键字的值小于根结点则在其左子树中查找否则在其右子树中查找 return search( head->left,key); else return search(head->right,key); } } int BiSortTree::deleteTree(int key)//删除一个结点 { treeNode *p; p=NULL; p=search(Head,key);//通过search函数先找到关键字 if(p==NULL)//结点为空找不到关键字 { cout<<"Can't find the key"; } if(p==Head)//如果为头结点则直接删除 { Head=NULL; } else//否则分为叶子结点,有孩子的结点和左右孩子都有的结点讨论 { treeNode* parent; parent=searchParent(Head,p); if(p->left==NULL&&p->right==NULL)//叶子节点即p的左右子树都为空 { if(parent->left==p)//if(!parent) { parent->left=NULL; } else { parent->right=NULL; } } else//非叶子节点 { if(p->right==NULL)//该节点没有右孩子 { if(parent->left==p) { parent->left=p->left ; } else { parent->right=p->left; } } else//该点有左右孩子 { treeNode * rightMinSon,* secondParent;//secondParent为右子树中的最小节点的父亲 rightMinSon=searchMinRight(p->right); secondParent=searchParent(p->right ,rightMinSon); secondParent->left=rightMinSon->right; if(p->right==rightMinSon)//右子树中的最小节点的父亲为p { p->right=rightMinSon->right ; } p->key=rightMinSon->key ; } } } return 1; } treeNode* BiSortTree::searchParent(treeNode* head,treeNode* p)//寻找父亲结点 { if(head->left==p||head->right==p||head==p||head==NULL) return head; else { if(p->key<head->key) return searchParent(head->left ,p); else return searchParent(head->right ,p); } } treeNode* BiSortTree::searchMinRight(treeNode* head)//找到右子树中最小的节点 { if(head->left ==NULL||head==NULL) { return head; } else { return searchMinRight(head->left); } } void BiSortTree::desplayTree(void)//递归中序遍历输出 { showTree(Head); cout<<endl; } void BiSortTree::showTree(treeNode* Head) { if(Head!=NULL) { showTree(Head->left ) ; cout<<Head->key<<' ' ; showTree(Head->right) ; } } BiSortTree::~BiSortTree() //调用析构函数,运用递归删除所有的New结点 { cout<<"已经消除了一棵树!!!!"<<endl; destroyTree(Head); } void BiSortTree::destroyTree(treeNode* head ) { if(head!=NULL) { destroyTree(head->left ); destroyTree(head->right ); delete head; } } void print() { cout<<"*************以下是对二叉排序树的基本操作*************"<<endl; cout<<" 1.输出二叉树 "<<endl; cout<<" 2.插入一个节点 "<<endl; cout<<" 3.查找一个节点 "<<endl; cout<<" 4.删除一个节点 "<<endl; } int main() { BiSortTree tree; int number; int choiceNumber; char flag; while(1) { print() ; cout<<"请选择你要进行的操作(1~4)"<<endl; cin>>choiceNumber; switch(choiceNumber) { case 1: tree.desplayTree();break; case 2: cout<<"请插入一个结点: "<<endl; cin>>number; tree.insertTree(number); tree.desplayTree(); break; case 3: cout<<"请输入你要查找的结点: "<<endl; cin>>number; if(tree.searchTree(number)==NULL) { cout<<"未找到所要查找的结点"<<endl; } else { cout<<"已找到所要查找的结点"<<endl; } break; case 4: cout<<"请输入你要删除的数: "<<endl; cin>>number; tree.deleteTree(number); tree.desplayTree(); break; default: break; } cout<<"你是否要继续(Y/N)?"<<endl; cin>>flag; if(flag=='N'||flag=='n') break;} return 1;}
数据结构相关问题,一直没有找到错误。代码哪里出错了呢?
■问题描述: 建立一棵二叉树,编程实现从根结点到给定结点之间的路径。 ■基本要求: 建立一棵以二叉链表存储的二叉树,以bt指向根节点、 p指向任一给定结点, 编程实现“以字符形式输出从根结点到给定结点之间的路径”。 ■测试数据: 自行建立一棵以序列{A, B, C, D, E, F, G, H, I, J}中的英文字母为结点 的任意一棵二叉树。 ■实现提示: (1)以某种遍历方式建立二叉树的二叉链表存储结构; (2)以非递归的后序方式遍历二叉树bt,并将访问过的结点依次存储到一个 顺序栈S中; (3)当后序遍历访问到结点*p时,此时栈S中存放的所有结点均为给定结点*p 的祖先,而由这些祖先,便构成了一条从根结点到结点*p之间的路径。 错误提示 :[Error] expected ';', ',' or ')' before '&' token 代码如下: #include <stdio.h> #include <stdlib.h> #define MAXLEN 100 typedef struct BiTNode // 定义二叉树结点结构 { char data; // 数据域 struct BiTNode *LChild,*RChild; // 左右孩子指针域 }BiTNode,*BiTree; int found=0; BiTree p=NULL; //临时结点 //1.建立二叉树 void CreateBiTree(BiTree &bt) {//按照先序序列建立二叉树的二叉链表 char ch; printf("请输入结点:\n"); scanf("%c",&ch); if(ch=='#') bt=NULL; else { bt=(BiTNode*)malloc(sizeof(BiTNode));//生成一个新结点 bt->data=ch; //生成根结点 CreateBiTree(bt->LChild); //生成左子树 CreateBiTree(bt->RChild); //生成子树 } } //2.后序遍历使结点入栈并求结点路径 void NodePath(BiTree bt,BiTNode*ch) { BiTNode*stack[MAXLEN]; //定义栈 int tag[MAXLEN]; // int i,top=0,find=0; BiTNode *s=bt; //临时指针 do{ while(s!=NULL) { //扫描左子树 top++; stack[top]=s; tag[top]=0; s=s->LChild; } if(top>0) { //栈非空 s=stack[top]; if(tag[top]==1) { if(s==ch) {//遇到给定结点输出路径 for(i=1;i<=top;i++) printf("-%c",stack[i]->data); find=1; } else top--; s=stack[top]; } if(top>0&&!find) { if(tag[top]!=1) {//扫描右子树 s=s->RChild; tag[top]=1; } else s=NULL; } } } while(!find&&top!=0); } BiTNode *FindBT(BiTree bt,char x) { if((bt!=NULL)&&!found) { if(bt->data==x) { p=bt; found=1; } else { FindBT(bt->LChild,x);//遍历查找左子树 遍历查找左子树 FindBT(bt->RChild,x);//遍历查找右子树 遍历查找右子树 } } return(p); } int main() {//主程序界面函数 BiTree bt; char s; system("color 1f"); system("mode con:cols=78 lines=35"); printf("\t 求二叉树上给定结点的路径\n"); printf("\n***********************************************\n"); printf("\t 1.建立二叉树\n"); printf("\t 2.求结点路径\n"); printf("\t 3.退出系统\n"); printf("\t 欢迎使用系统!\n"); printf("\n***********************************************\n"); printf("请选择您想要的服务:"); scanf("%s",&s); switch(s) { case '1': printf("请输入二叉树的结点序列 \n"); CreateBiTree(bt); printf("二叉树建立成功\n"); break; case '2': printf("输入求路径的结点:"); s=getchar(); p=NULL; found=0; FindBT(bt,s); if(p!=NULL) { NodePath(bt,p); printf("\n"); } else printf("没有该结点! \n"); break; case '3':exit(0); default:printf("输入有误");break; } return 0; }
二叉查找树 删除结点
/*包含头文件*/ #include "stdio.h" #include "stdlib.h" #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define MAXSIZE 20 typedef int Status; /* 二叉树的二叉链表结点结构定义 */ typedef struct BiTNode /* 结点结构 */ { int data; /* 结点数据 */ struct BiTNode *lchild, *rchild; /* 左右孩子指针 */ } BiTNode, *BiTree; /**BiTree等价于typedef BiTNode *BiTree*/ /*查找二叉排序树T中是否存在key(递归查找)*/ Status Search(BiTree T, int key, BiTree f, BiTree *p) { if (!T) /* 查找不成功 */ { *p = f; return FALSE; } else if (key==T->data) /* 查找成功 */ { *p = T; return TRUE; } else if (key<T->data) return Search(T->lchild, key, T, p); /* 在左子树中继续查找 */ else return Search(T->rchild, key, T, p); /* 在右子树中继续查找 */ } /* 当二叉排序树T中不存在关键字等于key的数据元素时, */ /* 插入key并返回TRUE,否则返回FALSE */ Status Insert(BiTree *T, int key) { BiTree p,s; if (!Search(*T, key, NULL, &p)) /* 查找不成功 */ { s = (BiTree)malloc(sizeof(BiTNode)); s->data = key; s->lchild = s->rchild = NULL; if (!p) *T = s; /* 插入s为新的根结点 */ else if (key<p->data) p->lchild = s; /* 插入s为左孩子 */ else p->rchild = s; /* 插入s为右孩子 */ return TRUE; } else return FALSE; /* 树中已有关键字相同的结点,不再插入 */ } /* 从二叉排序树中删除结点p,并重接它的左或右子树。 */ Status DeleteBST(BiTree &p) { BiTree q,s; if(p->rchild==NULL) /* 右子树空则只需重接它的左子树(待删结点是叶子也走此分支) */ { **_ q=p; p=p->lchild; free(q);_** } else if(p->lchild==NULL) /* 只需重接它的右子树 */ { _** q=p; p=p->rchild; free(q);**_ } else /* 左右子树均不空 */ { q=p; s=p->lchild; while(s->rchild) /* 转左,然后向右到尽头(找待删结点的前驱) */ { q=s; s=s->rchild; } p->data=s->data; /* s指向被删结点的直接前驱(将被删结点前驱的值取代被删结点的值) */ if(q!=p) q->rchild=s->lchild; /* 重接q的右子树 */ else q->lchild=s->lchild; /* 重接q的左子树 */ free(s); } return TRUE; } /* 若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素结点, */ /* 并返回TRUE;否则返回FALSE。 */ Status Delete(BiTree &T,int key) { if(!T) /* 不存在关键字等于key的数据元素 */ return FALSE; else { if (key==T->data) /* 找到关键字等于key的数据元素 */ return DeleteBST(T); else if (key<T->data) return Delete(T->lchild,key); else return Delete(T->rchild,key); } } /*二叉树中序遍历*/ void LDR(BiTree T) { if (T!=NULL) { LDR(T->lchild); printf("%d ",T->data); LDR(T->rchild); } } #define N 10 void main() { int i,j; BiTree T=NULL; //定义数组和初始化SeqList int d[N]={62,88,58,47,35,73,51,99,37,93}; for (i=0;i<N;i++) { Insert(&T,d[i]); } printf("***************二叉排序树查找(C版)***************\n"); printf("初始化二叉排序树\n中序遍历数据:"); LDR(T); printf("\n***************删除节点1***************\n"); Delete(T,93); printf("删除叶节点93\n中序遍历后:"); LDR(T); printf("\n***************删除节点2***************\n"); Delete(T,47); printf("删除双孩子节点47\n中序遍历后:"); LDR(T); printf("\n***************删除节点3***************\n"); Delete(T,58); printf("删除单孩子节点58\n中序遍历后:"); LDR(T); getchar(); } 删除结点的部分 if(p->rchild==NULL) /* 右子树空则只需重接它的左子树(待删结点是叶子也走此分支) */ { q=p; p=p->lchild; free(q); } else if(p->lchild==NULL) /* 只需重接它的右子树 */ { q=p; p=p->rchild; free(q); } 要删除p指向的结点,那么应该把p->lchild或p->rchild赋给p指向结点的双亲啊,为什么要给p呢?
(C语言)在二叉搜索树的学习时遇到了问题,求大佬帮忙看看
如题,在学习二叉搜索树时想要自己添加一些内容,但是不知道为什么就是会出错,自己感觉好像问题出在创建二叉树的地方,但是不知道怎么改.希望大佬能帮忙看看,如果能配上讲解就更好了,感谢. 下面贴上代码,之后是罗列的一些问题,如果代码中还有问题希望大佬能指点下我,谢谢: 项目总共三个文件,二叉搜索树头文件.h和.c文件,然后一个用于测试的主函数.c (二叉搜索树头文件) BSTree.h ``` #ifndef BSTREE_H #define BSTREE_H typedef int DataType; //二叉排序树节点定义 struct BinSearchTreeNode { DataType data; struct BinSearchTreeNode *leftchild; struct BinSearchTreeNode *rightchild; }; typedef struct BinSearchTreeNode *BSTreeNode; typedef struct BinSearchTreeNode *BinSearchTree; /****************************************************************/ /* BinSearchTree *create() */ /* 功能:创建二叉排序树 */ /* 输入参数:无 */ /* 返回值:二叉排序树 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ BinSearchTree create(); /****************************************************************/ /* void InOrder(BinSearchTree ptree) */ /* 功能:中序遍历二叉排序树 */ /* 输入参数ptree:二叉排序树 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void InOrder(BinSearchTree ptree); /****************************************************************/ /* BSTreeNode BSTSearch(BinSearchTree bt, DataType key) */ /* 功能:检索二叉排序树 */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要检索的元素 */ /* 返回值:成功返回NULL,失败返回元素插入的父结点位置 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ BSTreeNode BSTSearch(BinSearchTree bt, DataType key); /****************************************************************/ /* int BSTInsert(BinSearchTree bt, DataType key) */ /* 功能:在二叉排序树中插入元素key */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要插入的元素 */ /* 返回值:成功插入返回1,否则返回0 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ int BSTInsert(BinSearchTree bt, DataType key); /****************************************************************/ /* int BSTgetMax(BinSearchTree *bt) */ /* 功能:查找二叉排序树的最大值 */ /* 输入参数bt:二叉排序树的根 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void BSTgetMax(BinSearchTree *bt); /****************************************************************/ /* int BSTgetMin(BinSearchTree *bt) */ /* 功能:查找二叉排序树的最小值 */ /* 输入参数bt:二叉排序树的根 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void BSTgetMin(BinSearchTree *bt); /****************************************************************/ /* int BSTDelete1(BinSearchTree *bt, DataType key) */ /* 功能:删除二叉排序树中的元素key,方法1 */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要删除的元素 */ /* 返回值:成功删除返回1,否则返回0 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ int BSTDelete1(BinSearchTree *bt, DataType key); /****************************************************************/ /* int BSTDelete2(BinSearchTree *bt, DataType key) */ /* 功能:删除二叉排序树中的元素key,方法2 */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要删除的元素 */ /* 返回值:成功删除返回1,否则返回0 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ int BSTDelete2(BinSearchTree *bt, DataType key); /****************************************************************/ /* void BST_Destory(BinSearchTree bt) */ /* 功能:销毁二叉排序树 */ /* 输入参数bt:二叉排序树的根 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void BST_Destory(BinSearchTree bt); #endif // BSTREE_H ``` 对应的c文件 BSTree.c ``` #include <stdio.h> #include <stdlib.h> #include "BSTree.h" /****************************************************************/ /* BinSearchTree create() */ /* 功能:创建二叉排序树,注意这里输入的应该是先序序列,并且保证是一*/ /* 个二叉排序树的先序序列 */ /* 输入参数:无 */ /* 返回值:二叉排序树 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ BinSearchTree create() { int ch = 0;//初始化 BinSearchTree bt; scanf_s("%d", &ch); if (ch == -1) { bt = NULL; } else { bt = (BSTreeNode *)malloc(sizeof(struct BinSearchTreeNode)); bt->data = ch; //递归赋值左子树 bt->leftchild = create(); //递归赋值右子树 bt->rightchild = create(); } //返回根节点 return bt; } /****************************************************************/ /* void InOrder(BinSearchTree ptree) */ /* 功能:中序遍历二叉排序树 */ /* 输入参数ptree:二叉排序树 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void InOrder(BinSearchTree ptree) { if (ptree == NULL) { return; } InOrder(ptree->leftchild); printf("%d", ptree->data); InOrder(ptree->rightchild); } /****************************************************************/ /* BSTreeNode BSTSearch(BinSearchTree bt, DataType key) */ /* 功能:检索二叉排序树 */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要检索的元素 */ /* 返回值:成功返回NULL,失败返回元素插入的父结点位置 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ BSTreeNode BSTSearch(BinSearchTree bt, DataType key) { BSTreeNode p, parent; p = bt; parent = p; //记录待插入结点的父结点 while (p) { parent = p; //当查找到时提示,返回NULL if (p->data == key) { printf("Exist this key\n"); return NULL; } //根结点大于要查的结点,进入左分支查找 if (p->data > key) { p = p->leftchild; } //根结点小于要查的结点,进入右分支查找 else { p = p->rightchild; } }//p=NULL,跳出循环 return parent; //查找失败,返回parent }//return NULL和parent是为了便于之后的操作 /****************************************************************/ /* int BSTInsert(BinSearchTree bt, DataType key) */ /* 功能:在二叉排序树中插入元素key */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要插入的元素 */ /* 返回值:成功插入返回1,否则返回0 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ int BSTInsert(BinSearchTree bt, DataType key) { BSTreeNode p, temp; temp = BSTSearch(bt, key); //temp保存查找之后的结果 //已存在,返回0 if (temp == NULL) { printf("Exist this key\n"); return 0; } //申请结点的内存空间 p = (BSTreeNode *)malloc(sizeof(struct BinSearchTreeNode)); //申请失败提示 if (p == NULL) { printf("Alloc Failure!\n"); return 0; } p->data = key; //数据域赋值,左右指针域默认为空 //p->leftchild = NULL; //左子树指针域赋值 //p->rightchild = NULL; //右子树指针域赋值 if (key < temp->data) { temp->leftchild = p; //作为左子树插入 } else { temp->rightchild = p; //作为右子树插入 } return 1; } /****************************************************************/ /* int BSTgetMax(BinSearchTree bt) */ /* 功能:查找二叉排序树的最大值 */ /* 输入参数bt:二叉排序树的根 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void BSTgetMax(BinSearchTree *bt) { BSTreeNode temp; temp = bt; if (temp) { while (temp->leftchild) { temp = temp->leftchild; } printf("%d", temp->data); } } /****************************************************************/ /* int BSTgetMin(BinSearchTree bt) */ /* 功能:查找二叉排序树的最小值 */ /* 输入参数bt:二叉排序树的根 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void BSTgetMin(BinSearchTree *bt) { BSTreeNode temp; temp = bt; if (temp) { while (temp->rightchild) { temp = temp->rightchild; } printf("%d", temp->data); } } /****************************************************************/ /* int BSTDelete1(BinSearchTree *bt, DataType key) */ /* 功能:删除二叉排序树中的元素key,方法1 */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要删除的元素 */ /* 返回值:成功删除返回1,否则返回0 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ int BSTDelete1(BinSearchTree *bt, DataType key) { BSTreeNode parent, p, maxpl; p = *bt; parent = NULL; //查找被删除的结点 while (p != NULL) { if (p->data == key) break; //查找到了,跳出循环 if (p->data > key) p = p->leftchild; else p = p->rightchild; }//查询结束 if (p == NULL) { printf("%d not exist\n", key); return 0; } //只有右子树的情况 if (p->leftchild == NULL) { //如果被删除的结点是根结点,那就要修改的是二叉排序树的根 if (parent == NULL) *bt = p->rightchild; //检查是左孩子还是右孩子 else if (parent->leftchild == p) parent->leftchild = p->rightchild; else parent->rightchild = p->rightchild; } //既有左子树也有右子树 if (p->leftchild != NULL) { BSTreeNode parentp; //parentp记录maxpl的父结点 parentp = p; maxpl = p->leftchild; //对称遍历中,右侧的总是大的数 //定位p的左子树中的最大结点maxpl while (maxpl->rightchild != NULL) { parentp = maxpl; maxpl = maxpl->rightchild; } p->data = maxpl->data; //修改p的数据域为maxpl的值 if (parentp == p) //如果maxpl的父结点是p p->leftchild = maxpl->leftchild; //修改p结点的左指针 else parentp->rightchild = maxpl->leftchild; //修改父结点的右指针 p = maxpl; //更新p指针为maxpl结点以便删除 } //释放空间 free(p); return 1; } /****************************************************************/ /* int BSTDelete2(BinSearchTree *bt, DataType key) */ /* 功能:删除二叉排序树中的元素key,方法2 */ /* 输入参数bt:二叉排序树的根 */ /* 输入参数key:要删除的元素 */ /* 返回值:成功删除返回1,否则返回0 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ int BSTDelete2(BinSearchTree *bt, DataType key) { //parent记录p的父结点,maxpl记录p的左子树中的关键码最大结点 BSTreeNode parent, p, maxpl; p = *bt; parent = NULL; //查找被删除的结点 while (p != NULL) { if (p->data == key) break; //查找到了,跳出循环 parent = p; //注意这一句 if (p->data > key) p = p->leftchild; else p = p->rightchild; }//查找结束 if (p == NULL) { printf("%d not exist!\n", key); return 0; } //只有右子树的情况 if (p->leftchild == NULL) { //删除的是根结点,做特殊处理 if (parent == NULL) *bt = p->rightchild; //p是父结点parent的左孩子,则修改父结点的左指针 else if (parent->leftchild == p) parent->leftchild = p->rightchild; else parent->rightchild = p->rightchild; } //以上和方法1几乎完全相同 //有左子树和右子树 if (p->leftchild != NULL) { maxpl = p->leftchild; //定位左子树中的最大结点maxpl while (maxpl->rightchild != NULL) maxpl = maxpl->rightchild; maxpl->rightchild = p->rightchild; if (parent == NULL) *bt = p->leftchild; //p是父结点parent的左孩子,则修改父结点的左指针 else if (parent->leftchild == p) parent->leftchild = p->leftchild; //p是父结点parent的右孩子,则修改父结点的右指针 else parent->rightchild = p->leftchild; } free(p); //释放结点p return 1; } /****************************************************************/ /* void BST_Destory(BinSearchTree *bt) */ /* 功能:递归销毁二叉排序树 */ /* 输入参数bt:二叉排序树的根 */ /* 返回值:无 */ /* 创建日期:2019-5-21 Author:Cyber Kaka */ /****************************************************************/ void BST_Destory(BinSearchTree bt) { if (bt) { BST_Destory(bt->leftchild); BST_Destory(bt->rightchild); free(bt); } } ``` 主函数.c文件 main.c ``` #include <stdio.h> #include <stdlib.h> #include "BSTree.h" //用于测试的二叉树先序序列,-1表示空 //40 10 5 -1 -1 -1 55 45 -1 48 47 -1 -1 52 -1 -1 60 -1 70 -1 -1 void main() { BinSearchTree bt; int n = 0; printf("输入二叉排序树的先序序列:\n"); bt = create(); printf("输入要查找的元素,存在返回1,不存在返回0,插入:"); scanf_s("%d", &n); printf("%d\n", BSTSearch(bt, n)->data); printf("输入要插入的元素,成功插入返回1,否则返回0:"); scanf_s("%d", &n); printf("%d\n", BSTInsert(bt, n)); //printf("二叉排序树的中序遍历序列:\n"); //InOrder(bt); printf("\n第一种删除方法,输入要删除的元素,成功返回1,不成功返回0:"); scanf_s("%d", &n); printf("%d\n", BSTDelete1(&bt, n)); //printf("二叉排序树的中序遍历序列:\n"); //InOrder(bt); printf("\n第二种删除方法,输入要删除的元素,成功返回1,不成功返回0:"); scanf_s("%d", &n); printf("%d\n", BSTDelete2(&bt, n)); //printf("二叉排序树的中序遍历序列:\n"); //InOrder(bt); } ``` **问题:**<br> <br> * [0]生成解决方案的时候有警告,但是我忽略了,因为显示程序生成成功了,感觉这几个警告是最大的问题,第4个问题中我详细列出了这些内容<br> <br> * [1]二叉树的递归创建自己感觉有问题,尤其是内存申请这里<br> <br> <code>bt = (BSTreeNode *)malloc(sizeof(struct BinSearchTreeNode));</code><br> <br> * [2]中序遍历的内容在搜索到左子树底的时候本应返回上一步时会出现异常,建立断点异常内容如下:<br> 引发了异常: 读取访问权限冲突。<br> **ptree** 是 0xCDCDCDCD。<br> <br> * [3]由于中序遍历有异常,所以我注释掉了所有的相关内容,编译时没什么问题,但是删除结点的函数也会出现类似的异常,异常内容如下:<br> 引发了异常: 读取访问权限冲突。<br> **maxpl** 是 0xCDCDCDCD。<br> <br> <br> * [4]好吧,我就都注释掉了,看看别的代码是不是有问题,重新生成解决方案,熟悉的警告出现了,c语言是速成的结构体这块不是很明了,感觉应该是创建二叉搜索树的代码有问题,或者是结构体创建有问题,以下是警告的内容:<br> */bstree.c(24): warning C4047: “=”:“BinSearchTree”与“BSTreeNode *”的间接级别不同<br> */bstree.c(108): warning C4047: “=”:“BSTreeNode”与“BSTreeNode *”的间接级别不同<br> *\bstree.c(139): warning C4047: “=”:“BSTreeNode”与“BinSearchTree *”的间接级别不同<br> *\bstree.c(160): warning C4047: “=”:“BSTreeNode”与“BinSearchTree *”的间接级别不同<br> <br> 第24行:<br> BinSearchTree create()<br> {<br> &nbsp;&nbsp;...<br> &nbsp;&nbsp;&nbsp;&nbsp;bt = (BSTreeNode *)malloc(sizeof(struct BinSearchTreeNode));<br> &nbsp;&nbsp;...<br> }<br> <br> 第108行:<br> int BSTInsert(BinSearchTree bt, DataType key)<br> {<br> &nbsp;&nbsp;...<br> &nbsp;&nbsp;&nbsp;&nbsp;//申请结点的内存空间<br> &nbsp;&nbsp;&nbsp;&nbsp;p = (BSTreeNode *)malloc(sizeof(struct BinSearchTreeNode));<br> &nbsp;&nbsp;...<br> }<br> <br> 第139行:<br> void BSTgetMax(BinSearchTree *bt)<br> {<br> &nbsp;&nbsp;...<br> &nbsp;&nbsp;&nbsp;&nbsp;temp = bt;<br> &nbsp;&nbsp;...<br> }<br> <br> 第160行:<br> void BSTgetMin(BinSearchTree *bt)<br> {<br> &nbsp;&nbsp;...<br> &nbsp;&nbsp;&nbsp;&nbsp;temp = bt;<br> &nbsp;&nbsp;...<br> }<br> <br> 以上,求各位大佬指点迷津<br>
求解课设过程中出现的这个问题
使用二叉树完成的通讯录管理,输出的时候重复输出。。 代码:#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> using namespace std; /***************************************************** Description: 基于二叉排序树的通讯录管理系统 Function List: initdata() 初始化内置数据 insert() 添加联系人 find() 查找联系人 change() 修改联系人信息 del() 删除联系人 destory() 释放空间 *******************************************************/ typedef struct student { char name[12]; char sex[2]; char hometown[20]; char tel_num[20]; char post[6]; char email[20]; char QQ[20]; }student; //定义二叉链表结构体 //查找结果标记 student myClass[50]; int count = 0; //通讯录人数初始化 int flag; typedef struct tree { struct student *people; struct tree *left; struct tree *right; }tree; //定义树 tree *root = NULL; //根节点初始化为空 void initdata() //内置的联系人的初始化 { strcpy( myClass[count].name,"张小三"); strcpy( myClass[count].sex,"男"); strcpy( myClass[count].hometown,"南京"); strcpy( myClass[count].tel_num,"152****6578"); strcpy( myClass[count].post,"222666"); strcpy( myClass[count].email,"871011891@qq.com"); strcpy( myClass[count].QQ,"871011891"); count++; strcpy( myClass[count].name,"李小四"); strcpy( myClass[count].sex,"男"); strcpy( myClass[count].hometown,"上海"); strcpy( myClass[count].tel_num,"134****1786"); strcpy( myClass[count].post,"222787"); strcpy( myClass[count].email,"789455511@qq.com"); strcpy( myClass[count].QQ,"789455511"); count++; strcpy( myClass[count].name,"王二虎"); strcpy( myClass[count].sex,"女"); strcpy( myClass[count].hometown,"北京"); strcpy( myClass[count].tel_num,"177****4572"); strcpy( myClass[count].post,"244761"); strcpy( myClass[count].email,"1543694145@qq.com"); strcpy( myClass[count].QQ,"1543694145"); root = (tree *)malloc(sizeof(tree)); root->people = &myClass[0]; //记录下people的初始地址 root->left = NULL; root->right = NULL; } void insert(tree * root,student *q) //排序二叉树按姓名递归插入 { flag = 0; if(strcmp(root->people->name,q->name) == 0) { printf("插入不成功,相同姓名的人已存在\n"); flag = 1; return; } if( strcmp(root->people->name,q->name) > 0 )//调用strcmp函数比较字符串,判断是否有名字重复 { if(root->left == NULL) { tree *p = (tree *)malloc(sizeof(tree)); //给指针p分配一个tree型结构体大小的内存 p->people = q; p->left = NULL; p->right = NULL; root->left = p; } else { insert(root->left,q); //递归调用insert插入联系人 } } else { if( root->right == NULL) { tree *p = (tree *)malloc(sizeof(tree)); p->people= q; p->left = NULL; p->right = NULL; root->right = p; } else { insert(root->right,q); } } } int find(tree *root,char *p) //先跟遍历查找 { int flag; if( root!= NULL ) { if( strcmp(root->people->name,p) == 0) { printf("已找到该联系人:\n"); printf("姓名:%s 性别:%s 家乡:%s 电话:%s 邮编:%s Email:%s QQ:%s\n",root->people->name,root->people->sex,root->people->hometown,root->people->tel_num,root->people->post,root->people->email,root->people->QQ); return 1; //查找成功标记 } flag = find(root->left,p); if(flag>0) { return 1; } flag = find(root->right,p); if(flag > 0) { return 1; } } return 0; } /*修改联系人信息操作*/ int change(tree *root,char *p) //先根遍历,查找到后修改 { int flag; if(root != NULL) { if( strcmp(root->people->name,p) == 0) { int accept = 0; char buff[20]; while(1) { if(accept == 6) { system("cls"); break; } printf("姓名:%s 性别:%s 家乡:%s 电话:%s 邮编:%s Email:%s QQ:%s\n",root->people->name,root->people->sex,root->people->hometown,root->people->tel_num,root->people->post,root->people->email,root->people->QQ); printf("请输入要修改的选项:\n"); printf("1 修改姓名\n"); printf("2 修改性别\n"); printf("3 修改家乡\n"); printf("4 修改电话\n"); printf("5 修改邮编\n"); printf("6 修改Email\n"); printf("7 修改QQ\n"); printf("8 退出\n"); printf("请输入:"); scanf("%d",&accept); switch(accept) { case 1: { system("cls"); printf("你想把名字修改为:"); scanf("%s",buff); strcpy(root->people->name,buff); printf("修改成功\n"); break; } case 2: { system("cls"); printf("你想把性别修改为:"); scanf("%s",buff); strcpy(root->people->sex,buff); printf("修改成功\n"); break; } case 3: { system("cls"); printf("你想家乡把修改为:"); scanf("%s",buff); strcpy(root->people->hometown,buff); printf("修改成功\n"); break; } case 4: { system("cls"); printf("你想把电话修改为:"); scanf("%s",buff); strcpy(root->people->tel_num,buff); printf("修改成功\n"); break; } case 5: { system("你想把邮编修改为:"); scanf("%s,buff"); strcpy(root->people->post,buff); break; } case 6: { system("你想把Email修改为:"); scanf("%s,buff"); strcpy(root->people->email,buff); break; } case 7: { system("你想把QQ修改为:"); scanf("%s,buff"); strcpy(root->people->QQ,buff); break; } case 8:{ break;} default: { printf("输入有误,请重新输入\n"); break; } } } return 1; } flag = change(root->left,p); if(flag >0 ) { return 1; } flag = change(root->right,p); if(flag >0) { return 1; } } return 0; } /*打印出联系人信息*/ void print(tree *root) { if(root != NULL) { printf("姓名:%s 性别:%s 家乡:%s 电话:%s 邮编:%s Email:%s QQ:%s\n",root->people->name,root->people->sex,root->people->hometown,root->people->tel_num,root->people->post,root->people->email,root->people->QQ); print(root->left); putchar('\n'); print(root->right); } } tree * findparent(char *p,tree *root,tree *parent) //找寻待删除结点的父母结点 { if( root != NULL) { if( strcmp(root->people->name,p) == 0 ) { return parent; //和返回结点所在层次类似 } parent = findparent(p,root->left,root); if(parent != NULL) { return parent; } parent = findparent(p,root->right,root); if(parent != NULL) { return parent; } } return NULL; } void my_remove(tree *parent,tree *child) //删除结点 { if(child->left == NULL && child->right == NULL) //叶子节点 { tree *temp = child; if(temp == root) //删除的是根 { root = NULL; free(temp); return; } if(parent->left == child) //判断是父母的左孩子还是右孩子 { parent->left = NULL; } else { parent->right = NULL; } free(temp); } else { if( child->left != NULL && child->right == NULL) //1度结点 { if(parent == NULL) //删除的是根结点 { root = root->left; free(child); return; } if( parent->left == child) //判断左右孩子,由其父母收养 { parent->left = child->left; } else { parent->right = child->left; } free(child); } else if( child->left == NULL && child->right != NULL) { if(parent == NULL) { root = root->right; free(child); return; } if( parent->left == child) { parent->left = child->right; } else { parent->right = child->right; } free(child); } else //二度结点 { tree *temp,*temppar; temp = child->right; temppar = child; while(temp->left != NULL) //找其中根遍历下的后继结点 { temppar = temp; temp = temp->left; } strcpy(child->people->name,temp->people->name); strcpy(child->people->sex,temp->people->sex); strcpy(child->people->hometown,temp->people->hometown); strcpy(child->people->tel_num,temp->people->tel_num); strcpy(child->people->post,temp->people->post); strcpy(child->people->email,temp->people->email); strcpy(child->people->QQ,temp->people->QQ); if( temppar == child) //后继结点为待删除结点右孩子 { //注意这种情况 temppar->right = temp->right; } else { temppar->left = temp->right; } free(temp); } } } /*联系人的删除操作*/ void del(char *q) { tree *parent; parent = findparent(q,root,NULL); if( parent == NULL && ( strcmp( root->people->name,q) != 0 ))//判断通讯录是否为空以及传进来的联系人是否存在 { printf("通讯录中没有此联系人,删除失败\n"); return; } if( parent == NULL) //调用my_remove函数,//删除分两步,先找到其父母结点,再分情况删除 { my_remove(parent,root); } else { if( parent->left != NULL && (strcmp(parent->left->people->name,q) == 0 ) ) { my_remove(parent,parent->left); } else { my_remove(parent,parent->right); } } } void destory(tree *root) { if(root != NULL) //释放空间 { destory(root->left); destory(root->right); free(root); } } /*通讯录功能的展示界面以及联系人的显示界面*/ void disp() { int fun; char accept[20]; while(1) { printf("现有联系人按先序遍历如下:\n"); print(root); printf(" 请输入要选择的功能\n"); printf("/************************************/\n"); printf(" 1.添加联系人\n"); printf(" 2.修改联系人信息\n"); printf(" 3.查找联系人\n"); printf(" 4.删除联系人\n"); printf(" 5.退出\n"); printf("/************************************/\n"); printf("请输入:"); scanf("%d",&fun); switch(fun) { case 1: { system("cls"); if(root == NULL) { count++; root = (tree *)malloc(sizeof(tree)); printf("请输入要添加联系人的姓名\n"); scanf("%s",accept); strcpy(myClass[count].name,accept); printf("请输入要添加联系人的性别\n"); scanf("%s",accept); strcpy(myClass[count].sex,accept); printf("请输入要添加联系人的家乡\n"); scanf("%s",accept); strcpy(myClass[count].hometown,accept); printf("请输入要添加联系人的电话\n"); scanf("%s",accept); strcpy(myClass[count].tel_num,accept); printf("请输入要添加联系人的邮编\n"); scanf("%s",accept); strcpy(myClass[count].post,accept); printf("请输入要添加联系人的email\n"); scanf("%s",accept); strcpy(myClass[count].email,accept); printf("请输入要添加联系人的QQ\n"); scanf("%s",accept); strcpy(myClass[count].QQ,accept); root->people = &myClass[count]; root->left = NULL; root->right = NULL; printf("添加完成\n"); break; } count++; printf("请输入要添加联系人的姓名\n"); scanf("%s",accept); strcpy(myClass[count].name,accept); printf("请输入要添加联系人的性别\n"); scanf("%s",accept); strcpy(myClass[count].sex,accept); printf("请输入要添加联系人的家乡\n"); scanf("%s",accept); strcpy(myClass[count].hometown,accept); printf("请输入要添加联系人的电话\n"); scanf("%s",accept); strcpy(myClass[count].tel_num,accept); printf("请输入要添加联系人的邮编\n"); scanf("%s",accept); strcpy(myClass[count].post,accept); printf("请输入要添加联系人的email\n"); scanf("%s",accept); strcpy(myClass[count].email,accept); printf("请输入要添加联系人的QQ\n"); scanf("%s",accept); strcpy(myClass[count].QQ,accept); insert(root,&myClass[count]); if(flag == 1) { break; } printf("添加完成\n"); break; } case 2: { system("cls"); if(root == NULL) { printf("通讯录为空\n"); break; } printf("请输入要修改的联系人姓名:\n"); scanf("%s",accept); fun = change(root,accept); if(fun == '\0') { printf("没有你要联系人\n"); } break; } case 3: { system("cls"); if(root == NULL) { printf("通讯录为空\n"); break; } printf("请输入要查找的联系人姓名:\n"); scanf("%s",accept); fun = find(root,accept); if(fun == 0) { printf("联系人未找到\n"); } break; } case 4: { system("cls"); if( root == NULL) { printf("通讯录为空\n"); break; } printf("请输入要删除的联系人姓名:"); scanf("%s",accept); del(accept); break; } case 5: { system("cls"); printf("正在清除数据\n"); destory(root); printf("欢迎使用本通讯录,seeyou!\n"); exit(0); } default: { system("cls"); printf("输入有误,请重新输入!\n"); break; } } } } int main() { int i; printf("正在初始化系统\n"); initdata(); for(i = 1;i <= count;i++) { insert(root,&myClass[i]); } disp(); return 0; }![图片](https://img-ask.csdn.net/upload/201701/01/1483283932_867316.png)
[C++数据结构]自己按书中代码打了一个二叉查找树模板类,发现不能在树上正常插入元素
以下代码分为一个头文件和一个.cpp文件,可复制粘贴直接运行,头文件记得命名为BST.h 我的运行环境是vs2017,编译没有出错,插入函数也是照书中代码一点点打的,保证没有抄错。但是无法正常插入,麻烦大佬们花两分钟帮忙看看,是不是代码的错,在下C++才学一年,希望能大家能多指教,非常感谢! 代码出自《数据结构与算法分析 C++语言描述 第2版》Larry Nyhoff著 清华大学出版社 第600页 ``` /* 头文件名字如下: BST.h 这是一个二叉查找树模板类,我只定义了元素插入二叉树的函数 代码出自《数据结构与算法分析 C++语言描述 第2版》Larry Nyhoff著 第600页 保证没有抄错,大佬们可以直接复制粘贴到编译器中执行 后面有测试的test.cpp文件,也可以直接复制粘贴 */ #include <iostream> #include <new>//我不知道该头文件的用处,书上是这么写的 using namespace std; #ifndef BINARY_SEARCH_TREE_H #define BINARY_SEARCH_TREE_H template <typename DataType> class BinarySearchTree { private: /*节点类*/ class BinNode { public: DataType data; BinNode * left; BinNode * right; BinNode() :left(0),right(0){} BinNode(DataType item) :data(item), left(0), right(0) {} };//节点类声明结束 typedef BinNode * BinNodePointer;//用BinNodePointe来代替BinNode * //类成员 BinNode * myRoot; public: BinarySearchTree();//构造 void insert(const DataType & item)const;//插入 private: void insertAux(BinNodePointer subtreeRoot, const DataType & item)const;//插入辅助函数 };//模板类声明结束 //以下是函数定义 //构造 template <typename DataType> inline BinarySearchTree<DataType>::BinarySearchTree():myRoot(0){} //插入 template<typename DataType> inline void BinarySearchTree<DataType>::insert(const DataType & item) const { insertAux(myRoot, item); } //插入辅助函数定义,用了递归 template<typename DataType> void BinarySearchTree<DataType>::insertAux( BinarySearchTree<DataType>::BinNodePointer subtreeRoot, const DataType & item) const { if (subtreeRoot == 0){ subtreeRoot = new BinarySearchTree<DataType>::BinNode(item); cout<<"xxx\n";//之后用for循环测试是否插入成功,如果成功只显示一次,失败显示n次。 } else if (item < subtreeRoot->data)//左子树 insertAux(subtreeRoot->left, item); else if (subtreeRoot->data)//右子树 insertAux(subtreeRoot->right, item); else cerr << "Item already in the tree\n"; } #endif ``` 下面是测试用的main函数 ``` #include <iostream> #include "BST.h" using namespace std; int main() { BinarySearchTree<int> bst; //测试插入函数 int number; for (number=0;;) { number++; if (number == 999)break; bst.insert(number); }//如果一直是空树的话会不断的输出"xxx" return 0; } ```
用fscanf和fgets从文件读取数据存储到链表失败是为什么??
我建立了链表结构,然后从文件导入数据,然后输出链表内容,发现输出的内容顺序不对内容也有点地方出错了! (下面是代码) #include <iostream> #include<fstream> #include<stdlib.h> #include<string.h> #include<stdio.h> typedef struct node{ char question[200]; char option_A[50]; char option_B[50]; char option_C[50]; char option_D[50]; char answer[3]; char respond[3]; char analysis[200]; int length; struct node *next; }LNODE,*LinkList; int main(void) { LNODE *L; L=new LNODE; L->next=NULL; L->length=0; LNODE *p; LNODE *q; q=L; int i; FILE *tk; if((tk=fopen("//Users//apple//Documents//Test System//test question.txt","r"))==NULL) { printf("File open error!\n"); exit(0); } while(!feof(tk)) { fgets(q->question,sizeof(LNODE),tk); fgets(q->option_A,sizeof(LNODE),tk); fgets(q->option_B,sizeof(LNODE),tk); fgets(q->option_C,sizeof(LNODE),tk); fgets(q->option_D,sizeof(LNODE),tk); fgets(q->answer,sizeof(LNODE),tk); fgets(q->analysis,sizeof(LNODE),tk); p=new LNODE; p->next=NULL; q->next=p; q=q->next; } if(fclose(tk)) { printf("Can not close the file!\n"); exit(0); } q=L; while(q->next) { printf("%s",q->question); printf("%s",q->option_A); printf("%s",q->option_B); printf("%s",q->option_C); printf("%s",q->option_D); printf("%s",q->answer); printf("%s",q->analysis); q=q->next; } } (这是文档里的内容) 在数据结构中,从逻辑结构上可以把数据结构分成() A.动态结构和静态结构 B.紧凑结构和非紧凑结构 C.线性结构和非线性结构 D.内部结构和外部结构 C 略 与数据元素本身的形式,内容,相对位置,个数无关的是数据的() A.存储结构 B.存储实现 C.逻辑结构 D.运算实现 C 略 通常要求同一逻辑结构中的所有数据元素具有相同的特性,这意味着() A.数据具有同一特点 B.每个数据元素都一样 C.不仅每个数据元素所包含的数据项都一样,而且对应数据项的类型要一致 D.数据元素所包含的数据项的个数要相等 C 只有这样系统才能高效统一的对数据进行管理。 算法的时间复杂度取决于() A.问题的规模 B.待处理的数据的初态 C.计算机的配置 D.A和B D 略 顺序表中第一个元素的储存地址是100,每个元素的长度为2,则第5个元素的地址是() A.100 B.108 C.100 D.120 B 100+(5-1)*2==108 线性表若采用链式存储结构,要求内存中可用存储单元的地址() A.部分是连续的 B.一定是不连续的 C.必须是连续的 D.连续或不连续都可以 D 因为链表有指针跟踪从而连不连续都可以。 用链接方式存储的队列,在进行删除运算时() A.仅修改头指针 B.仅修改尾指针 C.头尾指针都一定要修改 D.头尾指针可能都要修改 D 一般只修改头指针,但是删除的结点若为最后一个时,则要重新对尾指针赋值。 一个递归算法必须包括() A.递归部分 B.终止条件和递归部分 C.迭代部分 D.终止条件和迭代部分 D 略 串是一种特殊的线性表,其特殊性体现在() A.可以顺序储存 B.可以链式储存 C.数据元素是单个字符 D.数据元素可以是多个字符 C 串是一种内容受限的线性表。 把一棵树转化为二叉树后,这棵二叉树的形态是() A.唯一的 B.有多种 C.有多种,但根结点都没有左孩子 D.有多种,但根结点都没有右孩子 A 略。 利用二叉链表存储树,则根结点的右指针() A.指向最左孩子 B.指向最右孩子 C.非空 D.为空 C 右指针指向兄弟结点。 在以下的存储形式中,不是树的存储形式的是() A.双亲表示法 B.孩子链表表示法 C.孩子兄弟表示法 D.顺序存储表示法 D 常用孩子兄弟表示法转化为二叉树进行储存。 在一个无向图,所有顶点的度数之和等于图的边数的()倍 A.1/2 B.1 C.2 D.4 A 略 折半查找与二叉排序树的时间性能() A.相同 B.完全不同 C.有时不相同 D.数量级都是O(log2n) C 要看初始数据的状态。 堆的形状是一棵() A.二叉排序树 B.满二叉树 C.完全二叉树 D.平衡二叉树 C 略 若一组记录的排序码为(46,79,56,38,40,84),则利用堆排序的方式建立的初始堆为() A.79,46,56,38,40,84 B.84,79,56,38,40,46 C.84,79,56,46,40,38 D.84,56,79,40,46,38 C 画出图去找矛盾。 快速排序在下列()最易发挥作用 A.被排序的数据中具有多个相同的排序码 B.被排序的数据已经基本有序 C.被排序的数据完全无序 D.被排序的数据中的最大值和最小值相差悬殊 C 完全无序时用快速排序。 (这是输出后的内容,第一行与原文档的根本不同,而且后面也有很多乱的错误的) ![图片说明](https://img-ask.csdn.net/upload/201812/31/1546187214_133620.jpeg) 有哪位大神指导一下小白!!
用fgets或者fscanf从文件输入到链表中的内容错误!!
#include <iostream> #include<fstream> #include<stdlib.h> #include<string.h> #include<stdio.h> typedef struct node{ char question[200]; char option_A[50]; char option_B[50]; char option_C[50]; char option_D[50]; char answer[3]; char respond[3]; char analysis[200]; int length; struct node *next; }LNODE,*LinkList; int main(void) { LNODE *L; L=new LNODE; L->next=NULL; L->length=0; LNODE *p; LNODE *q; q=L; int i; FILE *tk; if((tk=fopen("//Users//apple//Documents//Test System//test question.txt","r"))==NULL) { printf("File open error!\n"); exit(0); } while(!feof(tk)) { fgets(q->question,sizeof(LNODE),tk); fgets(q->option_A,sizeof(LNODE),tk); fgets(q->option_B,sizeof(LNODE),tk); fgets(q->option_C,sizeof(LNODE),tk); fgets(q->option_D,sizeof(LNODE),tk); fgets(q->answer,sizeof(LNODE),tk); fgets(q->analysis,sizeof(LNODE),tk); p=new LNODE; p->next=NULL; q->next=p; q=q->next; } if(fclose(tk)) { printf("Can not close the file!\n"); exit(0); } q=L; while(q->next) { printf("%s",q->question); printf("%s",q->option_A); printf("%s",q->option_B); printf("%s",q->option_C); printf("%s",q->option_D); printf("%s",q->answer); printf("%s",q->analysis); q=q->next; } } ```下面是文档的内容,图片是输出后的内容,第一题的题目变成了略,是为什么?已经崩溃了!求大神救救小白! 在数据结构中,从逻辑结构上可以把数据结构分成() A.动态结构和静态结构 B.紧凑结构和非紧凑结构 C.线性结构和非线性结构 D.内部结构和外部结构 C 略 与数据元素本身的形式,内容,相对位置,个数无关的是数据的() A.存储结构 B.存储实现 C.逻辑结构 D.运算实现 C 略 通常要求同一逻辑结构中的所有数据元素具有相同的特性,这意味着() A.数据具有同一特点 B.每个数据元素都一样 C.不仅每个数据元素所包含的数据项都一样,而且对应数据项的类型要一致 D.数据元素所包含的数据项的个数要相等 C 只有这样系统才能高效统一的对数据进行管理。 算法的时间复杂度取决于() A.问题的规模 B.待处理的数据的初态 C.计算机的配置 D.A和B D 略 顺序表中第一个元素的储存地址是100,每个元素的长度为2,则第5个元素的地址是() A.100 B.108 C.100 D.120 B 100+(5-1)*2==108 线性表若采用链式存储结构,要求内存中可用存储单元的地址() A.部分是连续的 B.一定是不连续的 C.必须是连续的 D.连续或不连续都可以 D 因为链表有指针跟踪从而连不连续都可以。 用链接方式存储的队列,在进行删除运算时() A.仅修改头指针 B.仅修改尾指针 C.头尾指针都一定要修改 D.头尾指针可能都要修改 D 一般只修改头指针,但是删除的结点若为最后一个时,则要重新对尾指针赋值。 一个递归算法必须包括() A.递归部分 B.终止条件和递归部分 C.迭代部分 D.终止条件和迭代部分 D 略 串是一种特殊的线性表,其特殊性体现在() A.可以顺序储存 B.可以链式储存 C.数据元素是单个字符 D.数据元素可以是多个字符 C 串是一种内容受限的线性表。 把一棵树转化为二叉树后,这棵二叉树的形态是() A.唯一的 B.有多种 C.有多种,但根结点都没有左孩子 D.有多种,但根结点都没有右孩子 A 略。 利用二叉链表存储树,则根结点的右指针() A.指向最左孩子 B.指向最右孩子 C.非空 D.为空 C 右指针指向兄弟结点。 在以下的存储形式中,不是树的存储形式的是() A.双亲表示法 B.孩子链表表示法 C.孩子兄弟表示法 D.顺序存储表示法 D 常用孩子兄弟表示法转化为二叉树进行储存。 在一个无向图,所有顶点的度数之和等于图的边数的()倍 A.1/2 B.1 C.2 D.4 A 略 折半查找与二叉排序树的时间性能() A.相同 B.完全不同 C.有时不相同 D.数量级都是O(log2n) C 要看初始数据的状态。 堆的形状是一棵() A.二叉排序树 B.满二叉树 C.完全二叉树 D.平衡二叉树 C 略 若一组记录的排序码为(46,79,56,38,40,84),则利用堆排序的方式建立的初始堆为() A.79,46,56,38,40,84 B.84,79,56,38,40,46 C.84,79,56,46,40,38 D.84,56,79,40,46,38 C 画出图去找矛盾。 快速排序在下列()最易发挥作用 A.被排序的数据中具有多个相同的排序码 B.被排序的数据已经基本有序 C.被排序的数据完全无序 D.被排序的数据中的最大值和最小值相差悬殊 C 完全无序时用快速排序。 ```[图片说明](https://img-ask.csdn.net/upload/201812/31/1546186739_926263.jpeg) [图片说明](https://img-ask.csdn.net/upload/201812/31/1546186723_760510.jpeg)
做了一个小时的面试题(没有过 希望大家帮忙答下 虽然很幼稚 毕竟每个人都是这么过来的吗 感激了!)
XX软件工程师笔试试题 注:1、请参考人员将答案写在答题纸上,勿将答案写在此卷上。 2、请参考人员将编号与姓名填写在答题纸上。 1、 以下数据结构中不属于线性数据结构的是()。 A、队列 B、线性表 C、二叉树 D、栈 我的答案:C 2、 在结构化方法中,用数据流程图(DFD)作为描述工具的软件开发阶段是()。 A、 可行性分析 B、需求分析 C、详细设计 D、程序编码 我的答案:B 3、 结构化程序设计主要强调的是()。 A、 程序的规模 B、程序的易读性 C、程序的执行效率 D、程序的可移植性 我的答案:C 4、 在软件生命周期中,能准确地确定软件系统必须做什么和必须具备哪些功能的阶段()。 A、 概要设计 B、详细设计 C、可行性分析 D、需求分析 我的答案:B 5、 下列关于栈的叙述中正确的是()。 A、 在栈中只能插入数据 B、在栈中只能删除数据 B、 栈是先进先出的线性表 D、栈是先进后出的线性表 我的答案:D 6、 下面不属于软件设计原则的是()。 A、 抽象 B、模块化 C、自底向上 D、信息隐蔽 我的答案:C 7、 对长度为N的线性表进行顺序查找,在最坏情况下所需要的比较次数为()。 A、 N+1 B、N C、(N+1)/2 D、N/2 我的答案:C 8、 视图设计一般有3种设计次序,下列不属于视图设计的是()。 A、 自顶向下 B、由外向内 C、由内向外 D、自底向上 我的答案:C 9、下列有关数据库的描述,正确的是()。 A、数据库是一个DBF文件 B、数据库是一个关系 C、数据库是一个结构化的数据集合 D、数据库是一组文件 我的答案:C 10、下列说法中,不属于数据模型所描述的内容的是()。 A、数据结构 B、数据操作 C、数据查询 D、数据约束 我的答案:A 11、若按功能划分,软件测试的方法通常分为白盒测试方法和(黑盒测试方法)。 12、数据库系统的三级模式分别为(级联)模式、内部级模式与外部级模式。 13、在最坏情况下,冒泡排序的时间复杂度为(N+1/2)。 14、在面向对象方法中,信息隐蔽是通过对象的(封装)性来实现的。 15、关系模型的数据操纵既是建立在关系上的数据操纵,一般有(插入)、增加、删除、和修改四种操作。 16、TIME()的返回值的数据类型是(String)类型。 17、编写SQL语句 1)、创建一张学生表,包含以下信息,学号,姓名,年龄,性别,家庭住址,联系电话 我的答案: create table student( studentCardNo number(2) primary key, name char(10), age number(2), sex char(2) check(sex in (‘男’,’女’)), address varchar2(100), tel number(2) ) 2)、修改学生表的结构,添加一列信息,学历 我的答案: alter table student add(xueli varchar2(20)); 3)、修改学生表的结构,删除一列信息,家庭住址 我的答案: alter table student drop column address; 4)、向学生表添加如下信息: 学号 姓名 年龄 性别 联系电话 学历 1 A 22 男 123456 小学 2 B 21 男 119 中学 3 C 23 男 110 高中 4 D 18 女 114 大学 我的答案: insert into student values(‘&1’,’&2’,’&3’); 一次一次添加 5)修改学生表的数据,将电话号码以11开头的学员的学历改为“大专” 我的答案: update student set xueli=”大专” where tel like 11%; 6)删除学生表的数据,姓名以C开头,性别为‘男’的记录删除 我的答案: delete student where name like C% or sex=”男”; 7)查询学生表的数据,将所有年龄小于22岁的,学历为“大专”的,学生的姓名和学号显示出来 我的答案: select name,studentCardNo from student where age<22 and xueli=”大专”; 8)查询学生表的数据,查询所有信息,列出前25%的记录 我的答案: select top*0.25 from student; 9)查询出所有学生的姓名,性别,年龄降序排列 我的答案: select name,sex,age from student where age desc; 10)按照性别分组查询所有的平均年龄 我的答案: select avg(age) from student group by sex; 18、什么是存储过程?为什么存储过程要比单纯的SQL语句执行起来要快? 我的答案: 存储过程算是一种优化查询需要比单存SQL语句执行的要快 19、两张关联表,删除主表中已经在副表中没有的信息 我的答案 delete from fubiao a where a.fid not in(select id from zhubiao) 20、程序题: 用1、2、2、3、4、5这六个数字,用java或你熟悉的语言,打印出所有不同的排列,如:512234、412345等,要求:“4”不能再第三位,“3”与“5”不能相连。并将这些数据按从小到大输出。 我的答案 我的写的不好 没贴下 笔试的时候没写全 21、String 和 StringBuffer的区别 我的答案 String定长 StringBuffer 变长 22、&和&&的区别 我的答案 &短路与 &&逻辑与 网上答案: & 是位运算符,表示按位与运算, && 是逻辑运算符,表示逻辑与(and)。 23、final,finally,finalize的区别 我的答案 Final静变量关键字,finally异常关键字,finalize 网上答案 final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 finally是异常处理语句结构的一部分,表示总是执行。 finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法, 可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。 24、数组有没有length()这个方法?String有没有length()这个方法? 我的答案: 数组没有length()这个方法,有length的属性。 String有length()这个方法。 25、是否可以继承String类? 我的答案: 不可以 解释的很乱 26、说出数据连接池的工作机制是什么? 我的答案: 反正解释的很乱我感觉 27、垃圾回收的优点和原理。并考虑2种回收机制。 我的答案: 动态回收 解释的很乱 网上答案: Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解, 它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念, 只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。 垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有 使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。 回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。 28、你所知道的集合类都有哪些?区别?主要方法? 我的答案: Arraylist 非线性的、Vertor线性的 29、JSP的内置对象及方法。 我的答案: Page,exception,out,page content,application,request,reponse,session,config 30、页面间对象传递的方法。 我的答案: 那几个方法都写错了 31、你知道Request对象的主要方法有哪些? 32、J2EE是技术还是平台还是框架? 我的答案: J2EE是技术也是平台 网上答案: J2EE本身是一个标准,一个为企业分布式应用的开发提供的标准平台。 J2EE也是一个框架,包括JDBC、JNDI、RMI、JMS、EJB、JTA等技术。 33、我们在web应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种(例如GBK编码类型)编码的字符串? Request encording(“GBK”) 34、j2ee常用的设计模式?说明工厂模式。 Gof23种设计模式 工厂模式:Factory 网上答案: Java中的23种设计模式: Factory(工厂模式), Builder(建造模式), Factory Method(工厂方法模式), Prototype(原始模型模式),Singleton(单例模式), Facade(门面模式), Adapter(适配器模式), Bridge(桥梁模式), Composite(合成模式), Decorator(装饰模式), Flyweight(享元模式), Proxy(代理模式), Command(命令模式), Interpreter(解释器模式), Visitor(访问者模式), Iterator(迭代子模式), Mediator(调停者模式), Memento(备忘录模式), Observer(观察者模式), State(状态模式), Strategy(策略模式), Template Method(模板方法模式), Chain Of Responsibleity(责任链模式) 工厂模式:工厂模式是一种经常被使用到的模式,根据工厂模式实现的类可以根据提供的数据生成一组类中某一个类的实例, 通常这一组类有一个公共的抽象父类并且实现了相同的方法,但是这些方法针对不同的数据进行了不同的操作。 首先需要定义一个基类,该类的子类通过不同的方法实现了基类中的方法。 然后需要定义一个工厂类,工厂类可以根据条件生成不同的子类实例。 当得到子类的实例后,开发人员可以调用基类中的方法而不必考虑到底返回的是哪一个子类的实例。 35、JSP四种会话跟踪技术 我的答案: Application cookie session 36、排序都有哪几种方法?请举例 冒泡 选择 快序 二分查找 网上答案: 排序的方法有:插入排序(直接插入排序、希尔排序), 交换排序(冒泡排序、快速排序), 选择排序(直接选择排序、堆排序), 归并排序,分配排序(箱排序、基数排序) 快速排序的伪代码。 //使用快速排序方法对a[ 0 :n- 1 ]排序 从a[ 0 :n- 1 ]中选择一个元素作为m i d d l e,该元素为支点 把余下的元素分割为两段left 和r i g h t,使得l e f t中的元素都小于等于支点,而right 中的元素都大于等于支点 递归地使用快速排序方法对left 进行排序 递归地使用快速排序方法对right 进行排序 所得结果为l e f t + m i d d l e + r i g h t 37、关于模块间的设计原则? 规范要一样 38、项目过程一般是怎样的?你参加过几个项目开发?参加过的项目流程是怎样的?自己负责与人合作工作内容及自我评价? 从需求调研——设计开发——实施 参加过网站的实施 模板的制作 39、tomcat自动关闭常见原因? 我的答案: 现在没遇到过 40、如何设置TOMCAT内存和连接数? 我的答案: Tomcat群集 41、你如何理解Tomcat是什么? 我的答案: Tomcat是JSP Servlet 容器恰当的说 42、静态变量和实例变量的区别? 我的答案: 静态变量域用final修饰,每次都被调用 实例变量则不会 43、IE、FF下面CSS的解释区别 我的答案: 自己编的 44、web前端技术你了解哪些技术? 我的答案: JAVAScript,CSS,DIV,Ajax,Ajax框架,DWR,dojo,jguery 45、什么是报表?什么是报表控件,作用是什么?你了解哪些报表工具? 我的答案: 解释的很乱 46、你了解的那些统计图表类型? 我的答案: 自己编的 47、Flex与数据库连接的三种方式? 我的答案: 自己编的 ------------------------------------------------------- 我答错的、 错在哪里? 没答上的帮忙解答下? 感激了 !
相见恨晚的超实用网站
相见恨晚的超实用网站 持续更新中。。。
字节跳动视频编解码面经
三四月份投了字节跳动的实习(图形图像岗位),然后hr打电话过来问了一下会不会opengl,c++,shador,当时只会一点c++,其他两个都不会,也就直接被拒了。 七月初内推了字节跳动的提前批,因为内推没有具体的岗位,hr又打电话问要不要考虑一下图形图像岗,我说实习投过这个岗位不合适,不会opengl和shador,然后hr就说秋招更看重基础。我当时想着能进去就不错了,管他哪个岗呢,就同意了面试...
Java学习的正确打开方式
在博主认为,对于入门级学习java的最佳学习方法莫过于视频+博客+书籍+总结,前三者博主将淋漓尽致地挥毫于这篇博客文章中,至于总结在于个人,实际上越到后面你会发现学习的最好方式就是阅读参考官方文档其次就是国内的书籍,博客次之,这又是一个层次了,这里暂时不提后面再谈。博主将为各位入门java保驾护航,各位只管冲鸭!!!上天是公平的,只要不辜负时间,时间自然不会辜负你。 何谓学习?博主所理解的学习,它是一个过程,是一个不断累积、不断沉淀、不断总结、善于传达自己的个人见解以及乐于分享的过程。
程序员必须掌握的核心算法有哪些?
由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散的,并没有一本把他们全部覆盖的书籍。下面是我觉得值得学习的一些算法以及数据结构,当然,我也会整理一些看过...
大学四年自学走来,这些私藏的实用工具/学习网站我贡献出来了
大学四年,看课本是不可能一直看课本的了,对于学习,特别是自学,善于搜索网上的一些资源来辅助,还是非常有必要的,下面我就把这几年私藏的各种资源,网站贡献出来给你们。主要有:电子书搜索、实用工具、在线视频学习网站、非视频学习网站、软件下载、面试/求职必备网站。 注意:文中提到的所有资源,文末我都给你整理好了,你们只管拿去,如果觉得不错,转发、分享就是最大的支持了。 一、电子书搜索 对于大部分程序员...
linux系列之常用运维命令整理笔录
本博客记录工作中需要的linux运维命令,大学时候开始接触linux,会一些基本操作,可是都没有整理起来,加上是做开发,不做运维,有些命令忘记了,所以现在整理成博客,当然vi,文件操作等就不介绍了,慢慢积累一些其它拓展的命令,博客不定时更新 free -m 其中:m表示兆,也可以用g,注意都要小写 Men:表示物理内存统计 total:表示物理内存总数(total=used+free) use...
比特币原理详解
一、什么是比特币 比特币是一种电子货币,是一种基于密码学的货币,在2008年11月1日由中本聪发表比特币白皮书,文中提出了一种去中心化的电子记账系统,我们平时的电子现金是银行来记账,因为银行的背后是国家信用。去中心化电子记账系统是参与者共同记账。比特币可以防止主权危机、信用风险。其好处不多做赘述,这一层面介绍的文章很多,本文主要从更深层的技术原理角度进行介绍。 二、问题引入 假设现有4个人...
python学习方法总结(内附python全套学习资料)
不要再问我python好不好学了 我之前做过半年少儿编程老师,一个小学四年级的小孩子都能在我的教学下独立完成python游戏,植物大战僵尸简单版,如果要肯花时间,接下来的网络开发也不是问题,人工智能也可以学个调包也没啥问题。。。。。所以python真的是想学就一定能学会的!!!! --------------------华丽的分割线-------------------------------- ...
python 简易微信实现(注册登录+数据库存储+聊天+GUI+文件传输)
socket+tkinter详解+简易微信实现 历经多天的努力,查阅了许多大佬的博客后终于实现了一个简易的微信O(∩_∩)O~~ 简易数据库的实现 使用pands+CSV实现数据库框架搭建 import socket import threading from pandas import * import pymysql import csv # 创建DataFrame对象 # 存储用户数据的表(...
程序员接私活怎样防止做完了不给钱?
首先跟大家说明一点,我们做 IT 类的外包开发,是非标品开发,所以很有可能在开发过程中会有这样那样的需求修改,而这种需求修改很容易造成扯皮,进而影响到费用支付,甚至出现做完了项目收不到钱的情况。 那么,怎么保证自己的薪酬安全呢? 我们在开工前,一定要做好一些证据方面的准备(也就是“讨薪”的理论依据),这其中最重要的就是需求文档和验收标准。一定要让需求方提供这两个文档资料作为开发的基础。之后开发...
网页实现一个简单的音乐播放器(大佬别看。(⊙﹏⊙))
今天闲着无事,就想写点东西。然后听了下歌,就打算写个播放器。 于是乎用h5 audio的加上js简单的播放器完工了。 演示地点演示 html代码如下` music 这个年纪 七月的风 音乐 ` 然后就是css`*{ margin: 0; padding: 0; text-decoration: none; list-...
Python十大装B语法
Python 是一种代表简单思想的语言,其语法相对简单,很容易上手。不过,如果就此小视 Python 语法的精妙和深邃,那就大错特错了。本文精心筛选了最能展现 Python 语法之精妙的十个知识点,并附上详细的实例代码。如能在实战中融会贯通、灵活使用,必将使代码更为精炼、高效,同时也会极大提升代码B格,使之看上去更老练,读起来更优雅。
数据库优化 - SQL优化
以实际SQL入手,带你一步一步走上SQL优化之路!
2019年11月中国大陆编程语言排行榜
2019年11月2日,我统计了某招聘网站,获得有效程序员招聘数据9万条。针对招聘信息,提取编程语言关键字,并统计如下: 编程语言比例 rank pl_ percentage 1 java 33.62% 2 cpp 16.42% 3 c_sharp 12.82% 4 javascript 12.31% 5 python 7.93% 6 go 7.25% 7 p...
通俗易懂地给女朋友讲:线程池的内部原理
餐盘在灯光的照耀下格外晶莹洁白,女朋友拿起红酒杯轻轻地抿了一小口,对我说:“经常听你说线程池,到底线程池到底是个什么原理?”
《奇巧淫技》系列-python!!每天早上八点自动发送天气预报邮件到QQ邮箱
将代码部署服务器,每日早上定时获取到天气数据,并发送到邮箱。 也可以说是一个小型人工智障。 知识可以运用在不同地方,不一定非是天气预报。
经典算法(5)杨辉三角
杨辉三角 是经典算法,这篇博客对它的算法思想进行了讲解,并有完整的代码实现。
Python实例大全(基于Python3.7.4)
博客说明: 这是自己写的有关python语言的一篇综合博客。 只作为知识广度和编程技巧学习,不过于追究学习深度,点到即止、会用即可。 主要是基础语句,如三大控制语句(顺序、分支、循环),随机数的生成,数据类型的区分和使用; 也会涉及常用的算法和数据结构,以及面试题相关经验; 主体部分是针对python的数据挖掘和数据分析,主要先攻爬虫方向:正则表达式匹配,常用数据清洗办法,scrapy及其他爬虫框架,数据存储方式及其实现; 最后还会粗略涉及人工智能领域,玩转大数据与云计算、进行相关的预测和分析。
腾讯算法面试题:64匹马8个跑道需要多少轮才能选出最快的四匹?
昨天,有网友私信我,说去阿里面试,彻底的被打击到了。问了为什么网上大量使用ThreadLocal的源码都会加上private static?他被难住了,因为他从来都没有考虑过这个问题。无独有偶,今天笔者又发现有网友吐槽了一道腾讯的面试题,我们一起来看看。 腾讯算法面试题:64匹马8个跑道需要多少轮才能选出最快的四匹? 在互联网职场论坛,一名程序员发帖求助到。二面腾讯,其中一个算法题:64匹...
面试官:你连RESTful都不知道我怎么敢要你?
干货,2019 RESTful最贱实践
刷了几千道算法题,这些我私藏的刷题网站都在这里了!
遥想当年,机缘巧合入了 ACM 的坑,周边巨擘林立,从此过上了"天天被虐似死狗"的生活… 然而我是谁,我可是死狗中的战斗鸡,智力不够那刷题来凑,开始了夜以继日哼哧哼哧刷题的日子,从此"读题与提交齐飞, AC 与 WA 一色 ",我惊喜的发现被题虐既刺激又有快感,那一刻我泪流满面。这么好的事儿作为一个正直的人绝不能自己独享,经过激烈的颅内斗争,我决定把我私藏的十几个 T 的,阿不,十几个刷题网...
为啥国人偏爱Mybatis,而老外喜欢Hibernate/JPA呢?
关于SQL和ORM的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行了一番讨论,感触还是有一些,于是就有了今天这篇文。 声明:本文不会下关于Mybatis和JPA两个持久层框架哪个更好这样的结论。只是摆事实,讲道理,所以,请各位看官勿喷。 一、事件起因 关于Mybatis和JPA孰优孰劣的问题,争论已经很多年了。一直也没有结论,毕竟每个人的喜好和习惯是大不相同的。我也看...
SQL-小白最佳入门sql查询一
不要偷偷的查询我的个人资料,即使你再喜欢我,也不要这样,真的不好;
JavaScript 为什么能活到现在?
作者 | 司徒正美 责编 |郭芮 出品 | CSDN(ID:CSDNnews) JavaScript能发展到现在的程度已经经历不少的坎坷,早产带来的某些缺陷是永久性的,因此浏览器才有禁用JavaScript的选项。甚至在jQuery时代有人问出这样的问题,jQuery与JavaScript哪个快?在Babel.js出来之前,发明一门全新的语言代码代替JavaScript...
项目中的if else太多了,该怎么重构?
介绍 最近跟着公司的大佬开发了一款IM系统,类似QQ和微信哈,就是聊天软件。我们有一部分业务逻辑是这样的 if (msgType = "文本") { // dosomething } else if(msgType = "图片") { // doshomething } else if(msgType = "视频") { // doshomething } else { // doshom...
Nginx 原理和架构
Nginx 是一个免费的,开源的,高性能的 HTTP 服务器和反向代理,以及 IMAP / POP3 代理服务器。Nginx 以其高性能,稳定性,丰富的功能,简单的配置和低资源消耗而闻名。 Nginx 的整体架构 Nginx 里有一个 master 进程和多个 worker 进程。master 进程并不处理网络请求,主要负责调度工作进程:加载配置、启动工作进程及非停升级。worker 进程负责处...
致 Python 初学者
欢迎来到“Python进阶”专栏!来到这里的每一位同学,应该大致上学习了很多 Python 的基础知识,正在努力成长的过程中。在此期间,一定遇到了很多的困惑,对未来的学习方向感到迷茫。我非常理解你们所面临的处境。我从2007年开始接触 python 这门编程语言,从2009年开始单一使用 python 应对所有的开发工作,直至今天。回顾自己的学习过程,也曾经遇到过无数的困难,也曾经迷茫过、困惑过。开办这个专栏,正是为了帮助像我当年一样困惑的 Python 初学者走出困境、快速成长。希望我的经验能真正帮到你
Python 编程开发 实用经验和技巧
Python是一门很灵活的语言,也有很多实用的方法,有时候实现一个功能可以用多种方法实现,我这里总结了一些常用的方法和技巧,包括小数保留指定位小数、判断变量的数据类型、类方法@classmethod、制表符中文对齐、遍历字典、datetime.timedelta的使用等,会持续更新......
吐血推荐珍藏的Visual Studio Code插件
作为一名Java工程师,由于工作需要,最近一个月一直在写NodeJS,这种经历可以说是一部辛酸史了。好在有神器Visual Studio Code陪伴,让我的这段经历没有更加困难。眼看这段经历要告一段落了,今天就来给大家分享一下我常用的一些VSC的插件。 VSC的插件安装方法很简单,只需要点击左侧最下方的插件栏选项,然后就可以搜索你想要的插件了。 下面我们进入正题 Material Theme ...
“狗屁不通文章生成器”登顶GitHub热榜,分分钟写出万字形式主义大作
一、垃圾文字生成器介绍 最近在浏览GitHub的时候,发现了这样一个骨骼清奇的雷人项目,而且热度还特别高。 项目中文名:狗屁不通文章生成器 项目英文名:BullshitGenerator 根据作者的介绍,他是偶尔需要一些中文文字用于GUI开发时测试文本渲染,因此开发了这个废话生成器。但由于生成的废话实在是太过富于哲理,所以最近已经被小伙伴们给玩坏了。 他的文风可能是这样的: 你发现,...
程序员:我终于知道post和get的区别
是一个老生常谈的话题,然而随着不断的学习,对于以前的认识有很多误区,所以还是需要不断地总结的,学而时习之,不亦说乎
《程序人生》系列-这个程序员只用了20行代码就拿了冠军
你知道的越多,你不知道的越多 点赞再看,养成习惯GitHub上已经开源https://github.com/JavaFamily,有一线大厂面试点脑图,欢迎Star和完善 前言 这一期不算《吊打面试官》系列的,所有没前言我直接开始。 絮叨 本来应该是没有这期的,看过我上期的小伙伴应该是知道的嘛,双十一比较忙嘛,要值班又要去帮忙拍摄年会的视频素材,还得搞个程序员一天的Vlog,还要写BU...
加快推动区块链技术和产业创新发展,2019可信区块链峰会在京召开
11月8日,由中国信息通信研究院、中国通信标准化协会、中国互联网协会、可信区块链推进计划联合主办,科技行者协办的2019可信区块链峰会将在北京悠唐皇冠假日酒店开幕。   区块链技术被认为是继蒸汽机、电力、互联网之后,下一代颠覆性的核心技术。如果说蒸汽机释放了人类的生产力,电力解决了人类基本的生活需求,互联网彻底改变了信息传递的方式,区块链作为构造信任的技术有重要的价值。   1...
Python 植物大战僵尸代码实现(2):植物卡片选择和种植
这篇文章要介绍的是: - 上方植物卡片栏的实现。 - 点击植物卡片,鼠标切换为植物图片。 - 鼠标移动时,判断当前在哪个方格中,并显示半透明的植物作为提示。
相关热词 c#委托 逆变与协变 c#新建一个项目 c#获取dll文件路径 c#子窗体调用主窗体事件 c# 拷贝目录 c# 调用cef 网页填表c#源代码 c#部署端口监听项目、 c#接口中的属性使用方法 c# 昨天
立即提问