二叉排序树
头文件
#include<stdio.h>
#include<stdlib.h>
结构体
typedef int KeyType;
typedef struct BSTNode {
KeyType key;
struct BSTNode* lchild, * rchild;
}BSTNode,*BiTree;
功能函数
int BST_Insert(BiTree& T, KeyType k)
//创建二叉排序树
{
if (NULL == T)
{
//为新节点申请空间,第一个节点作为树根
T = (BiTree)malloc(sizeof(BSTNode));
T->key = k;
T->lchild = T->rchild = NULL;
return 1;//代表插入成功
}
else if (k == T->key)
return 0;//发现相同元素就不插入
else if (k < T->key)
return BST_Insert(T->lchild, k);//函数调用结束后左孩子和原来的父亲会自动关联起来,引用的机制
else
return BST_Insert(T->rchild, k);
}
void Creat_BST(BiTree& T, KeyType str[], int n)
{
T = NULL;
int i = 0;
while (i < n)
{
BST_Insert(T, str[i]);//把某一个节点放在二叉查找树当中
i++;
}
}
//递归算法简单,但执行效率较低,实现留给大家编写
BSTNode* BST_Search(BiTree T, KeyType key, BiTree& p)
{
p = NULL;//存储要找的节点的父亲
while (T != NULL && key != T->key)
{
p = T;
if (key < T->key) T = T->lchild;//比当前节点小,就左边找
else T = T->rchild;//比当前节点大,右边去
}
return T;
}
//书上没有二叉排序树的删除代码
void DeleteNode(BiTree& root, KeyType x)
{
if (root == NULL)
{
return;
}
if (root->key > x)
{
DeleteNode(root->lchild, x);
}
else if (root->key < x)
{
DeleteNode(root->rchild, x);
}
else {
//查找到了刪除节点
if (root->lchild == NULL)
{
//左子树为空
BiTree tempNode = root;//临时存着,一会free
root = root->rchild;
free(tempNode);
}
else if (root->rchild == NULL) {
//右子树为空
BiTree tempNode = root;//临时指针
root = root->lchild;//右子树直接顶上去
free(tempNode);
}
else {
//左右子树都不为空
//一般删除的策略是左子树的最大数据或右子树的最小数据
//代替要删除的节点(这里采用查找左子树最大数据来代替删除的节点)
BiTree tempNode = root->lchild;//保存删除的节点
if (tempNode->rchild != NULL)
{
tempNode = tempNode->rchild;
}
root->key = tempNode->key;
//递归
DeleteNode(root->lchild, tempNode->key);
}
}
}
//中序遍历
void InOrder(BiTree p)
{
if (p != NULL)
{
InOrder(p->lchild);
printf(" %d", p->key);//等价于visit函数
InOrder(p->rchild);
}
};
主函数
int main()
{
BiTree T=NULL;//树根
BiTree parent;//存储父亲节点的地址值
BiTree search;
KeyType str[] = { 54,20,66,40,28,79,58 };//将要进入二叉排序树的元素值
Creat_BST(T, str, 7);
InOrder(T);
printf("\n");
search = BST_Search(T, 40, parent);
if (search)
{
printf("找到对应节点,值=%d\n", search->key);
}
else {
printf("未找到对应节点\n");
};
DeleteNode(T, 54);//删除某个节点
InOrder(T);
printf("\n");
system("pause");
}
顺序查找和折半查找
头文件
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
存储结构
typedef int ElemType;
typedef struct {
ElemType* elem;//整型指针
int TableLen;//存储动态数组里面元素的个数
}SSTable;
主要函数
int Search_Seq(SSTable ST, ElemType key)
{
ST.elem[0] = key;
int i;
for (i = ST.TableLen - 1; ST.elem[i] != key; --i);
return i;
}
void ST_Init(SSTable& ST, int len)
{
ST.TableLen = len + 1;//多申请一个位置,为了哨兵
ST.elem = (ElemType*)malloc(sizeof(ElemType) * ST.TableLen);
int i;
srand(time(NULL));//随机数生成
for (int i = 0; i < ST.TableLen; i++) //为啥这里零号位置也随机了数据,为折半查找服务
{
ST.elem[i] = rand() % 100;
}
}
void ST_print(SSTable ST)
{
for (int i = 0; i < ST.TableLen; i++)
{
printf("%3d", ST.elem[i]);
}
printf("\n");
}
//时间复杂度 logn
int Binary_search(SSTable L, ElemType key)
{
int low = 0, high = L.TableLen - 1, mid;
while (low <= high)
{
mid = (low + high) / 2;
if (L.elem[mid] == key)
{
return mid;
}
else if(L.elem[mid]>key)
{
high = mid - 1;
}
else
low = mid + 1;
}
return -1;
}
int compare(const void* left, const void* right)
//left,right是任意两个元素的地址值
{
//转成整型指针在取值
//从小到大排序
return *(ElemType*)left - *(ElemType*)right;
}
主函数
//顺序查找与折半查找
int main()
{
SSTable ST;
ElemType key;
int pos;//存储查询元素的位置
ST_Init(ST, 10);
ST_print(ST);
printf("请输入要搜索的key的值:\n");
scanf("%d", &key);
pos = Search_Seq(ST, key);
if (pos)
{
printf("查找成功,位置为 %d\n", pos);
}
else {
printf("查找失败\n");
}
//compare:比较规则,需要我们传递一个函数名
qsort(ST.elem, ST.TableLen, sizeof(ElemType), compare);//qsort实现的是快排
ST_print(ST);
printf("二分查找,请输入要搜索的key的值:\n");
scanf("%d", &key);
//有序数组,必须是数组,链表不能随机访问
pos = Binary_search(ST, key);//二分查找,也叫折半查找
if (pos != 1)
{
printf("查找成功 位置为 %d\n", pos);
}
else {
printf("查找失败\n");
}
system("pause");
}