2023.1.9 学习总结

本文介绍了二叉排序树的基本操作,包括创建、插入、查找和删除节点,并提供了相应的C++代码实现。同时,文章讨论了如何判断一个二叉树是否为完全二叉树以及使用层序遍历的方法。此外,还提到了C++中字符串查找的相关函数,如find、find_first_of、find_last_of和rfind。
摘要由CSDN通过智能技术生成

1.二叉排序树的相关操作

二叉排序树的相关操作可以分为这几种:

1.创建二叉排序树

2.插入值

3.查找值

4.删除值

首先给出二叉排序树的结点类型定义:(就是一个二叉树)

struct bis {
	int data;
	bis* left;
	bis* right;
};

因为创建二叉排序树需要用到插入值的操作,所以我们一起说:

创建二叉排序树

输入:

9
38 45 42 24 58 30 67 12 51

根据输入数据的方法不同,可以更改创建二叉排序树里面的写法,我写的这个就是按照上面的:输入第一行给出一个正整数N;第二行给出N个互不相同的正整数,其间以空格分隔。

每输入一个数,我们就要进行一次插入操作。 

bis* creat() {
	bis* root = NULL;

	int n;
	cin >> n;

	int temp;
	for (int i = 0; i < n; i++) {
		cin >> temp;

		root = insert(root, temp);//每输入一个数,我们就要进行一次插入操作
	}

	return root;
}

插入值

这个函数的第一个参数是二叉排序树的根节点,第二个参数是待插入的数据

now指针用于遍历,pre指针指向now的前驱

我这个二叉排序树是左大右小的,一般是左小右大。

当now指针为NULL时,说明pre指向了叶节点,这时候便可以插入了。

bis* insert(bis* t, int k) {
	bis* pre=NULL, *now;
	now = t;

	while (now) {
		if (k == now->data) {
			return t;
		}
		else {
			pre = now;

			if (k > now->data) {//这个二叉排序树是左大右小的,一般是左小右大
				now = now->left;
			}
			else {
				now = now->right;
			}
		}
	}

	bis* newnode = (bis*)malloc(sizeof(bis));
	newnode->data = k;
	newnode->left = NULL;
	newnode->right = NULL;

	if (!t) {
		t = newnode;
	}
	else {
		if (k > pre->data) {
			pre->left = newnode;
		}
		else {
			pre->right = newnode;
		}
	}

	return t;
}

查找值

查找值的过程和插入值的过程差不多

迭代法:

bis* search(bis* t, int k) {
	bis* temp = t;

	while (temp) {
		if (temp->data = k) {
			return temp;
		}
		else if (k<temp->data) {//这个二叉排序树是左大右小的
			temp = temp->right;
		}
		else {
			temp = temp->left;
		}
	}
	return NULL;
}

递归法:

bis* search2(bis* t, int k) {
	if (t == NULL || t->data == k) {
		return t;
	}
	else {
		if (k < t->data) {//这个二叉排序树是左大右小的
			return search2(t->right, k);
		}
		else {
			return search2(t->left, k);
		}
	}
}

删除值

删除值要注意的是待删除结点是否为根节点;

List* del(List* root, int data) {
    List* now = root, * pre = NULL;//now指向待查找的结点,pre指向now的前驱

    while (now&& now->data != data) {
        pre = now;
        if (data < now->data) {
            now = now->left;
        }
        else {
            now = now->right;
        }
    }

    //如果找到了结点,那么会通过break跳出循环,这时now不为空,
    //如果没找到,就只有当now为空时,才会退出循环。
    if (!now) {
        cout << "not find";
        return root;
    }

    //如果待删除结点有左右节点
    if (now->left && now->right) {
        //s用来找待删除结点的中序直接后继,pres保存的是s的前驱,
        //r保存的是待删除结点的中序直接后继结点的右孩子
        List* pres, * s, * r;
        pres = now;
        s = now->right;

        while (s->left) {//找出中序直接后继
            pres = s;
            s = s->left;
        }

        now->data = s->data;//中序直接后继结点替换待删除结点
        r = s->right;//保存的是待删除结点的中序直接后继结点的右孩子

        if (pres == now) {//如果待删除结点的右孩子没有左孩子
            now->right = r;
        }
        else {
            pres->left = r;
        }

        return root;
    }
    else {//待删除结点没有左右节点或者只有一个
        List* r;//用来保存待删除结点的孩子
        if (now->left) {
            r = now->left;
        }
        else {
            r = now->right;
        }

        if (pre == NULL) {//如果删除的是根节点
            return r;//返回待删除结点的孩子
        }
        else if (pre->left == now) {
            pre->left = r;
        }
        else {
            pre->right = r;
        }

        return root;
    }

}

2.判断是否为完全二叉树

判断是否为完全二叉树的方法和层序遍历差不多:

这是层序遍历:

void levelTraverse(List* root) {
    queue<List*> q;
    cout << root->data;
    q.push(root);

    List* temp;
    while (!q.empty()) {
        temp = q.front();
        q.pop();

        if (temp->left != NULL) {
            cout << " " << temp->left->data;
            q.push(temp->left);
        }

        if (temp->right != NULL) {
            cout << " " << temp->right->data;
            q.push(temp->right);
        }
    }

}

这是层序遍历的同时判断是否为完全二叉树: 

bool levelTraverse(List* root) {
    int flag = 1;
    bool result = true;
    queue<List*> q;
    cout << root->data;
    q.push(root);

    List* temp;
    while (!q.empty()) {
        temp = q.front();
        q.pop();

        if (temp->left != NULL) {
            cout << " " << temp->left->data;
            q.push(temp->left);

            if (flag == 0) {
                result = false;
            }
        }
        else {
            flag = 0;
        }

        if (temp->right != NULL) {
            cout << " " << temp->right->data;
            q.push(temp->right);

            if (flag == 0) {
                result = false;
            }
        }
        else {
            flag = 0;
        }
    }

    return result;
}

3.字符串find函数

1.find函数

语法

find(str,position)
  • str:待查找的字符串

  • position:字符串中的某个位置,表示从从这个位置开始的字符串中找指定元素(不填第二个参数,默认从字符串的开头进行查找)

返回值为目标字符的位置(第一个字符位置为0),当没有找到目标字符时返回-1

举例

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;

int main()
{
    string message = "666acbd";
    string s = "chi1 huo3 guo1";
    string s2 = "ac";

    int flag = message.find(s);
    int flag2 = message.find(s2);

    cout << flag << endl;
    cout << flag2 << endl;

    return 0;
}

2.find_first_of()

查找第一次出现的位置

find_last_of()

查找最后一次出现的位置

举例:

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;

int main()
{
    string message = "string666,int m=466,34566";
    string s = "66";

    int first = message.find_first_of(s);
    int last = message.find_last_of(s);

    cout << first << endl;
    cout << last << endl;
    

    return 0;
}

3.rfind() 

 反向查找第一次出现的位置

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;

int main()
{
    string message = "string666,int m=466,34566";
    string s = "66";

    int k = message.rfind(s);

    cout << k << endl;

    return 0;
}

查找所有子串在母串中出现的位置 

//查找s 中flag 出现的所有位置。
	string s("hello world!");
    string flag="l";
    int position=0;
    int i=1;
    while((position=s.find(flag,position))!=string::npos)
    {
        cout<<"position  "<<i<<" : "<<position<<endl;
        position++;
        i++;
    }
  position  1 : 2
  position  2 : 3
  position  3 : 9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值