实习复习纲要-数据结构

数据结构
1.链表
(1)单链表
c语言实现:

typedef struct Lnode {
	Elemtype e;
	struct Lnode *next
}Lnode, *Linklist;

JAVA语言实现:

public class Node{
	public Object data;
	public Node next;

	public Node(Object e){
	this.data = e;
	}
}

2.栈

typedef struct {
SElemtype *top;
SElemtype *base;
int stacksize;
}SqStack;

JAVA语言实现:

//节点
public class LinkNode<T> {
	private T data;
	private LinkNode<T> next;
	public LinkNode(T data, LinkNode<T> next){
	this.data = data;
	this.next = next;
	}
}
//实现栈
public class LinkStack<T>{
	private LinkNode base;
	private LinkNode top;
	private  Integer size;
	public void InitStack(){
	top = base = new LinkNode();
	size = 0;
	}
}

3.队列
C语言实现:

typedef struct {
QElemtype *base;
int front;
int rear;
}SqQueue;

JAVA语言实现:

//节点
public class LinkNode<T> {
	private T data;
	private LinkNode<T> next;
	public LinkNode(T data, LinkNode<T> next){
	this.data = data;
	this.next = next;
	}
}
//实现队列
public class LinkQueue<T>{
	private LinkNode rear;
	private LinkNode front;
	private  Integer size;
	public void InitStack(){
	front = rear = new LinkNode();
	size = 0;
	}
}

4.二叉树
(1)满二叉树和完全二叉树
满二叉树:深度为k,且有2^k-1个节点。
完全二叉树:深度为k,不需有2^k-1个节点,但是每个节点需按照层次遍历排列。
(2)遍历二叉树
先序遍历
中序遍历
后序遍历
三种遍历都有使用二叉链表进行递归和非递归实现方法。

C语言二叉树:

typedef struct BiTNode{
TElemtype data;
struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

递归实现先序遍历:

Status PreOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){
	//Visit函数:
	//Status PrintElement(TElemType e){
	//	printf(e);
	//	return OK;
	//}
	if(T){
		if(Visit(T->data))
			if(PreOrderTraverse(T->lchild,Visit))
				if(PreOrderTraverse(T->rchild,Visit)) return OK;
		return ERROR;
	}else return OK;
}

非递归实现中序遍历:

Status InOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){
	InitStack(S); 
	p = T;
	while(p||!StackEmpty(S)){
		if(p){
			Push(S,p);
			p = p->lchild;
		}
		else{
		Pop(S,p);
		P=P->rchild;
		}
	}
	return OK;
}

JAVA实现二叉树:

//节点
public class BiNode{
	public BiNode left;
	public BiNode right;
	private Object data;

	public BiNode(Object data){
		this.data = data;
}
//二叉树的建立
	public List<BiNode> createTree(){
		int[] array = {1,2,3,4,5,6,7,8,9};
		List<BiNode> nodeList = new ArrayList<>();
		for(int Index = 0; Index < array.length; Index++){
		nodeList.add(new BiNode(array[nodeIndex]));
		}
		for(Index = 0; Index < array.length/2-1;Index++){
		nodeList.get(Index).left = nodeList.get(Index*2 + 1);
		nodeList.get(Index).right = nodeList.get(Index*2 + 2);
		}
		//最后一个父节点,可能存在没有右孩子的情况,所以拿出来单独处理
        int lastParentIndex = array.length/2-1;
        //左孩子
        nodeList.get(lastParentIndex).left =  nodeList.get(lastParentIndex * 2 + 1);
        //右孩子,如果长度为奇数则建立右孩子
        if(array.length % 2 == 1){
            nodeList.get(lastParentIndex).right = nodeList.get(lastParentIndex * 2 + 2);
        }
        return nodeList;
}

JAVA二叉树前序遍历(递归):

public static void PreOrderTraverse(BiNode node){
	if(node == null)
	return;
	System.out.print(node.key + " ");
	PreOrderTraverse(node.left);
	PreOrderTraverse(node.right);
}

JAVA二叉树中序遍历(非递归):

public void InOrderTraverse(BiNode node){
	Stack<BiNode> s = new Stack<BiNode>();
	BiNode a = node;
	while(a != null || !s.empty()){
		while(a != null){
			s.push(a);
			a = a.left;
		}
		BiNode a = s.pop();
		System.out.print(a.data + " ");
		if(a.right != null){
			a = a.right;
		}
		else
		a = null;
	}
}

(3)赫夫曼树
又称最优二叉树,一类带权路径长度最短的树。
如何构造赫夫曼树:
首先,选取权值最小的两个节点作为左右子树构造一棵新的二叉树。置新的二叉树的根节点的权值,为左右节点权值之和。
将新二叉树放回集合,重复进行选取,直到整个赫夫曼树形成。

(4)深度优先遍历(DFS)和广度优先遍历(BFS)
可参考http://www.blogjava.net/fancydeepin/archive/2013/02/03/CPP_BinaryTreeSearch.html

深度优先遍历:可等价于先序遍历。
运用栈的先进后出原理。

广度优先遍历:
运用队列的先进先出原理。

C++实现广度优先遍历:

void breadthFirstSearch(Tree root){
	queue<Node *> nodeQueue;
	nodeQueue.push(root);
	Node *node;
	while(!nodeQueue.empty()){
		node = nodeQueue.front;
		nodeQueue.pop();
		printf(format,node->data);
		if(node->lchild){
			nodeQueue.push(node->lchild);
		}
		if(node->rchild){
			nodeQueue.push(node->rchild);
		}
	}

}

JAVA实现广度优先遍历:

public static void LevelTraverse(BiNode root){
	Queue<BiNode> queue = new LinkedList<>();
	queue.add(root);
	while(queue.size()>0){
		BiNode a = queue.get(0);
		queue.remove();
		Syetem.out.print(a.data + " ");
		if(a.left != null)
			queue.add(a.left);
		if(a.right != null)
			queue.add(a.right);
		
	}
}

5.查找
(1)静态查找表
有序表,折半查找(logn)
(2)动态查找表
二叉排序树(最好logn,最坏n/2)
为使二叉排序树维持在logn,需使用平衡二叉树,即左子树和右子树深度之差不超过1。
B-树和B+树
(3)哈希表
哈希表如何建立
直接定址法:均匀的哈希函数。
数字分析法:取关键字的若干位
平方取中法:平方后的中间几位
折叠法:分隔为相同位数的几部分,再求叠加和
除留余数法:求mod n 的余数
随机数法:关键字长度不等长时用此方法
如何解决冲突:
开放定址法:存入后面的地址中
再哈希法:再计算一个不同的哈希函数
链地址法:地址为i的记录都存在Hash[i]链表中

6.排序
(1)插入排序
直接插入排序:看i位在已经排好的序列里在哪个位置。
时间复杂度:O(n^2)
折半插入排序:折半查找插入位置,仅减少关键字比较次数
时间复杂度:O(n^2)
(2)快速排序
冒泡排序
时间复杂度:O(n^2)
快速排序:第一个数值为轴,所有比他小的放左边,所有比他大的放右边,设两个指针low和high,low在头,high在末尾。首先把轴取出(第一位空了),high开始往前查找,第一个比轴小的,放入轴所在的位置(此时high位置空了)。然后low往后查找,第一个比轴大的,放入high的位置(low的位置又空了)。直至i和j相同,将轴放入这个位置。递归将轴两边也进行快排。
时间复杂度:O(nlogn) ,最坏情况O(n^2)
快排在所有相同时间复杂度算法中平均性能最好。
(3)选择排序
简单选择排序:每趟选最小的放入i位
时间复杂度:O(n^2)
堆排序:构建堆,使得堆顶是最小,所有非终端节点的值都不大于左右孩子节点的值,每次堆顶和堆底对换,拿掉堆底的最小值,然后重新构建堆。
先把无序序列看成完全二叉树,最后一个非终端节点是[n/2]个元素。从[n/2]往前倒,每次使得根节点最小。
时间复杂度:O(nlogn)
最坏的情况也是O(nlogn) ,这是相对快排来说最大优点。

7.平衡二叉树
性质:左右子树都平衡,平衡意味着左右深度差的绝对值不超过1。(我没孩子你可以有,但你的孩子不可能有孩子)

8.B树,B+树
转载自:https://www.cnblogs.com/xueqiuqiu/articles/8779029.html
B树和B+树应用在数据库索引,可以认为是m叉的多路平衡查找树。理论上二叉树查找速度和比较次数都是最小的,不用二叉树的原因是,当数据量大时,整个索引不会全加载到内存,而是会逐一加载每一个硬盘页。这样会涉及到磁盘IO的时间,磁盘IO相对于内存是很慢的。所以我们要用m叉树减少IO次数。

(1)B树,可以认为是m叉的多路平衡查找树,每个节点最多包涵m个孩子,m成为B树的阶。m的大小取决于磁盘页的大小。(有多大房子生多少孩子)

在这里插入图片描述

(2)B+树,是B树的变体,查询性能更好。
关键字不再保存数据,只用来索引。所有叶子节点用来保存数据,因此B+树会更矮胖。
同一个节点会在不同节点中重复出现。
因此B+树相对B树的优势就是,B+树只需遍历叶子结点链表,B树需要重复的中序遍历。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值