C语言基本数据结构之四(线性,对分,二叉树查找及二叉树删除)

一、线性查找

基本思想:对给定的一关键字K,从线性表的一端开始,逐个进行记录的关键字和 K 的比较,直到找到关键字等于 K 的记录(成功)或到达表的另一端(失败),其时间复杂度为O(n)。

查找成功时的平均查找次数为:

ASL=(1+2+3+4+……+n)/n=(n+1)/2

查找不成功时的比较次数为:n+1

优点:算法简单,无需排序,采用顺序和链式存储均可。

缺点:平均查找长度较大。

二、对分查找

基本思想:对有序文件,进行查找,先找“中间记录”,进行比较,根据不同情况,逐步缩小范围,直到找到或确认找不到该记录为止。 适用条件:必须在具有顺序存储结构的有序表中进行。其时间复杂度为O(log2 (n)) 优点:相对线性查找方式,对分查找次数要少,查找速度快。 缺点:要求表中的记录是按关键字排序,并且只适用于线性存储结构,当n较小的时候,其效果不十分显著

三、二叉排序树

3.1二叉排序树或者是一棵空树;或者是具有如下特性的二叉树:

(1)若它的左子树不空,则左子树上所有结点的值均小于根结点的值; (2)若它的右子树不空,则右子树上所有结点的值均大于根结点的值; (3)它的左、右子树也都分别是二叉排序树。

3.2删除二叉树节点

1. 如果被删除的是叶子结点,则删除后不影响整个树的结构;

2. 若被删结点只有左子树或右子树,只要将其左子树或右子树直接成为其双亲结点的左或右子树即可;

3. 若被删结点P的左右子树都非空,这时要循着P的左子树的根结点C向右一直找到结点S,要求S的右子树为空,然后将S的左子树改为结点Q的右子树,将S结点的数据域取代P结点的数据域值。

四、代码解析

直接贴上~~~

#include<stdio.h>
#include<malloc.h>
#define MAX 10
typedef struct STable stable;
typedef struct BTNode Node;
struct STable{
	int key;
	int other;
};
/*二叉树的节点类型*/
struct BTNode{
	int data;
	Node *Lchild;
	Node *Rchild;
};

stable table[MAX];
/*
线性查找
*/
int search(stable s[],int key,int size){
	int i = size;
	s[0].key = key;/*设置监视哨,以控制比较次数 ,在size 很大的情况下可以节省几乎一半的时间*/
	while(s[i].key !=key)
		i--;    /* 由表尾向前查找*/
	return (i);
}
/*对分查找,按升序排列
*/
int HalfSearch(stable s[],int key,int size){
	int low ,hight ,mid;
	low = 1;
	hight = size;
	while(low <= hight){
		mid = (low + hight)/2;
		if(s[mid].key == key){
			return (mid);
		}
		else if(s[mid].key > key)
			hight = mid - 1;
		else
			low = mid + 1;
	}
	return (0) ;
}
/*二叉排序树的插入*/
Node *insertBT(Node *t,int key){
	if(NULL==t){
		t = (Node * )malloc(sizeof(Node));
		t->Lchild = NULL;
		t->Rchild = NULL;
		t->data = key;
	}
	else if(key < t->data){
		t->Lchild = insertBT(t->Lchild,key);
	}
	else{
		t->Rchild = insertBT(t->Rchild,key);
	}
	
	return (t);
}
/* 二叉排序树的查询,返回该点的Node*/
Node *BTSearch(Node *t,int key){
	Node *p = NULL;
	if(NULL!=t){
		if(t->data ==key)
			p = t;
		else if(key < t->data)
			p = BTSearch(t->Lchild,key);		
		else
			p = BTSearch(t->Rchild,key);
	}
	return (p);
}
/*删除key节点*/
int DeleteNode(Node *t,int key){
	int flag = 0;
	Node *s,*q,*p,*f;/* f 是p 的父节点,s 是指向比key节点稍小的节点*/
	p = t;
	f = NULL;
	/*查找到该Key所在的节点*/
	while(p){
		if(key != p->data){
			f = p;
			if(key < p->data)
				p = p->Lchild;
			else
				p = p->Rchild;
		}
		else if(key == p->data)
			break;
	}
	/*如果不存在*/
	if(NULL==p){
		printf(" 无此点");
		return flag;
	}
	if(NULL==p->Lchild)
		s = p->Rchild;
	else if(NULL==p->Rchild)
		s = p->Lchild;
	else
	{
		/* p节点有两个子节点的情况*/
		q = p;
		s = p->Lchild;
		/*找到比p节点稍小的节点,以便于替换p*/
		while(NULL !=s->Rchild){
			s = s->Rchild;
		}
		/* 如果p的左孩子的右孩子为null*/
		if (q == p)
			q->Lchild = s->Lchild;
		else q->Rchild = s->Lchild;
		p->data = s->data; /*将s节点替换掉p*/
		free(s);
		flag = 1;  
	}
	/*p 点只有一个孩子节点*/
	if ( flag == 0) {
		if  ( f == NULL) //p节点的父节点为NULL 即P为树的根节点
			t = s;
		else if  (f->Lchild == p) 
			f->Lchild = s; 
        else f->Rchild = s;
		   free(p);
	} 
	return (flag);
} 
/*
判断该点是否为null
*/
void showNode(Node *q){
	if(NULL!=q)
		printf("\nYes the  data is %d \n",q->data);
	else
		printf("\n fail to search \n");
}
void main(){
	int i,n;
	Node *t=NULL,*q;
	/*初始化数据*/
	for(i = 1;i<=MAX;i++){
	  table[i].key = i + 10 ;
	}
	/*线性查找*/
	n = search(table,13,MAX);
	printf("\n search position is %d \n",n);
	n = 0;
	/*对分查找*/
	n = HalfSearch(table,17,MAX);
	printf("\n HalfSearch position is %d \n",n);
	i = 1;
	/*初始化二叉排序树*/
	while(i<=MAX){
		t = insertBT(t,table[i].key);
		i++;
	}
	/*二叉排序树查找*/
	q = BTSearch(t,12);
	showNode(q);
	/*删除该数*/
	DeleteNode(t,12);
	printf("\n still exist 12 ? \n");
	q = BTSearch(t,12);
	showNode(q);
}

持续更新中~~

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/to_perfect/article/details/53860927
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞