顺序表
1.顺序表的插入
①
public int insert(int i, T x) {
if (x == null)
throw new NullPointerException("x==null"); // 抛出空对象异常
if (i < 0)
i = 0; // 插入位置i容错,插入在最前
if (i > this.n)
i = this.n; // 插入在最后
Object[] source = this.element; // 数组变量引用赋值,source也引用element数组
if (this.n == element.length) { // 若数组满,则扩充顺序表的数组容量
this.element = new Object[source.length * 2]; // 重新申请一个容量更大的数组
for (int j = 0; j < i; j++) // 复制当前数组前i-1个元素
this.element[j] = source[j];
}
for (int j = this.n - 1; j >= i; j--) // 从i开始至表尾的元素向后移动,次序从后向前 this.element[j + 1] = source[j];
this.element[i] = x;
this.n++;
return i; // 返回x序号
}
// 顺序表尾插入x元素,返回x序号。成员方法重载
public int insert(T x) {
return this.insert(this.n, x); // 插入操作中,this.n加1
}
②练习题:
已知顺序表递减有序,将元素x插入到顺序表中,保持其有序性
public void insert1(T x){
if(x= =null) throw new NullPointerException(“x==null”);
int t=0;
for(int i=0;i<=n-1;i++) // n:顺序表的长度 element[0]~element[n-1]
if(x>element[i]){
t=i;
break;
}
if(i= =n) t=n;
insert(t,x);
}
2.顺序表的删除
public T remove(int i) {// 删除第i个元素,0<=i<n,返回被删除元素。若i越界,则返回null
if (this.n > 0 && i >= 0 && i < this.n) {
T old = (T) this.element[i]; // old中存储被删除元素
for (int j = i; j < this.n - 1; j++)
this.element[j] = this.element[j + 1]; // 元素前移一个位置 this.element[this.n - 1] = null; //
// 设置数组元素对象为空,释放原引用实例 this.n--;
return old; // 返回old局部变量引用的对象,传递对象引用
}
return null;
}
②练习题:
从顺序表中第i个元素开始连续删除k个元素的算法
public void remove_k(int i,int k){
if(i>0&&i+k<this.n&&this.n>0){
for(int j=i+k;j<this.n-1;j++)
this.element[j-k]=this.element[j];
}
if(i+k>n) n=i;
else this.n=this.n-k;
}
单链表
1.单链表的插入
public Node<T> insert(int i, T x) {
if (x == null)
throw new NullPointerException("x==null"); // 抛出空对象异常
Node<T> front = this.head; // front指向头结点
for (int j = 0; front.next != null && j < i; j++) // 寻找第i-1个或最后一个结点(front指向)
front = front.next;
front.next = new Node<T>(x, front.next);
// 在front之后插入值为x结点,包括头插入、中间/尾插入
return front.next; // 返回插入结点
}
2.单链表的删除
public T remove(int i) {
Node<T> front = this.head; // front指向头结点
for (int j = 0; front.next != null && j < i; j++) // 遍历寻找第i-1结点(front指向)
front = front.next;
if (i >= 0 && front.next != null) {// 若front的后继结点存在,则删除之 T old = front.next.data; // 获得待删除结点引用的对象 front.next =
// front.next.next; // 删除front的后继结点,包括头删除、中间/尾删除
// 由Java虚拟机稍后释放结点占用存储单元
return old;
}
return null; // 若i<0或i>表长
}
3.单链表的遍历
Node<T>p=head;while(p!=null)
{
System.out.print(p.data.toString() + "");
p = p.next;
}
二叉树
1.二叉树的先序遍历(递归)
public void preorder() {// 输出先根次序遍历序列
System.out.print("先根次序遍历二叉树: ");
preorder(this.root); // 调用先根次序遍历二叉树的递归方法 System.out.println();
}
private void preorder(BinaryNode<T> p) {// 先根次序遍历以p结点为根的子树,递归方法
if (p != null) { // 若二叉树不空
System.out.print(p.data.toString() + " ");
// 先访问当前结点元素 preorder(p.left); //
// 按先根次序遍历p的左子树,递归调用,参数为左孩子preorder(p.right); //
// 按先根次序遍历p的右子树,递归调用,参数为右孩子
}
}
2.二叉树的中序遍历(递归)
public void inorder() {// 输出中根次序遍历序列
System.out.print("中根次序遍历二叉树: ");
inorder(this.root);
System.out.println();
}
private void inorder(BinaryNode<T> p) // 中根次序遍历以p结点为根的子树,递归方法 {
if (p != null) {
inorder(p.left); // 中根次序遍历p的左子树,递归调用 System.out.print(p.data.toString() + " ");
inorder(p.right); // 中根次序遍历p的右子树,递归调用
}
}
3.二叉树的后序遍历(递归)
public void postorder() { // 输出后根次序遍历序
System.out.print("后根次序遍历二叉树: ");
postorder(this.root);
System.out.println();
}
private void postorder(BinaryNode<T> p) { // 后根次序遍历以p结点为根的子树,递归方法
if (p != null) {
postorder(p.left);
postorder(p.right);
System.out.print(p.data.toString() + " "); // 后访问当前结点元素
}
}
4.二叉树的先序遍历(非递归)
public void preorderTraverse(){
System.out.print("先根次序遍历(非递归)");
LinkedStack<BinaryNode<T>>stack=new LinkedStack<BinaryNode<T>>();
BinaryNode<T>p=this.root;
while(p!=null‖!stack.isEmpty())//p非空或栈非空
if(p!=null){
System.out.print(p.data+" ");//访问结点
stack.push(p);//p结点入栈
p=p.left;
}
else{ //p为空且且栈非空时
System.out.print("# ");
p=stack.pop();
p=p.right;
}
System.out.println();
}
5.二叉树的中序遍历(非递归)
public void inorderTraverse(){ // 中根次序遍历二叉树的非递归算法 System.out.print("中根次序遍历(非递归): "); SeqStack<BinaryNode<T>> stack = new SeqStack<BinaryNode<T>>(64); // 创建一个空栈
BinaryNode<T> p = this.root;
while (p != null || !stack.isEmpty()) // p非空或栈非空时
if (p != null) {
stack.push(p); // p结点入栈
p = p.left; // 进入左子树
}
else {// p为空且栈非空时
p = stack.pop(); // p指向出栈结点
System.out.print(p.data + " "); // 访问结点
p = p.right; // 进入右子树
}
System.out.println();
}
}
6.×二叉树的后序遍历(非递归)
7.构造一颗二叉树的算法
public BinaryTree(T[] 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!="∧",因为T不一定是String p = new BinaryNode<T>(elem); // 创建叶子结点
p.left = create(prelist); // 创建p的左子树,递归调用,实际参数与形式参数相同
p.right = create(prelist); // 创建p的右子树,递归调用,实际参数与形式参数相同
}
}
return p;
}
8.×二叉树层次遍历
查找
1.顺序查找
public int search(T key) {
for (int i = 0; i < this.n; i++) {
System.out.print("查找次数:" + i + " ");
if (key.equals(this.element[i])) {
return i;
}
}
return -1;
}
2.二分法查找
public class SortedArray {
public static int count = 0;
// 统计比较次数,计算ASL成功 //
// 已知value数组元素按升序排序,在begin~end范围内,二分法查找关键字为key元素,若查找成功返回下标,否则返回-1;
// 若begin、end越界,返回-1。若key==null,Java抛出空对象异常。
public static <T extends Comparable<? super T>> int binarySearch(T[] value, int begin, int end, T key) {
count = 0; // 统计比较次数,计算ASL成功
while (begin <= end) // 边界有效 {
int mid = (begin + end) / 2;
// 取中间位置,当前比较元素位置
System.out.print("[" + mid + "]=" + value[mid] + "?");
// 显示比较中间结果,可省略
count++;
if (key.compareTo(value[mid]) == 0) // 两对象相等
return mid; // 查找成功
if (key.compareTo(value[mid]) < 0) // key对象较小
end = mid - 1; // 查找范围缩小到前半段
else
begin = mid + 1; // 查找范围缩小到后半段
}return-1; // 查找不成功
}
// 已知value数组元素按升序排序,二分法查找关键字为key元素,若查找成功返回下标,否则返回-1
public static <T extends Comparable<? super T>> int binarySearch(T[] value, T key) {
return binarySearch(value, 0, value.length - 1, key);
}
}
3.×分块查找
4.×在一颗二叉排序树中查找
排序
1.直接插入排序
public void insertSort() {
for (int i = 1; i < element.length; i++) {
int temp = (int) element[i];
int j;
for (j = i - 1; j >= 0 && temp < (int) element[j]; j--) {
element[j + 1] = element[j];
}
element[j + 1] = temp;
System.out.print("第" + i + "趟 temp=" + temp + "\t");
print();
System.out.println();
}
}
2.希尔排序
public static void shellSort(int []keys){//希尔排序(升序)
for(int delta=keys.length/2;delta>0;delta/=2){//若干趟,控制增量每趟减半
for(int i=delta;i<keys.length;i++){//一趟分若干组,每组直接插入排序
int temp=keys[i],j;
for(j=i-delta;j>=0&&temp<keys[j];j-=delta)
keys[j+delta]=keys[j];//组内直接插入排序,寻找插入位置
keys[j+delta]=temp;
}
System.out.print("delta="+delta+" ");
print(keys);
}
}
3.冒泡排序
private static void swap(int[] keys, int i, int j) {// 交换keys[i]和keys[j]的值
int temp = keys[j];
keys[j] = keys[i];
keys[i] = temp;
}
public static void bubbleSort(int[] keys) {// 升序
bubbleSort(keys, true);
}
public static void ubbleSort(int[]keys,boolean asc){
System.out.println("冒泡排序("+(asc?"升":"降")+"序)");
boolean=true;//是否交换的标记
for(int i=1;i<keys.length&&exchange;i++){//有交换时再进行下一趟,最多n-1趟
exchange=false;//假定元素未交换
for(int j=0;j<keys.length;j++)//一趟比较,交换
if(asc?keys[j]>keys[j+1]:keys[j]<keys[j+1]){
swap(keys,j,j+1);
exchange=true;//有交换
}
System.out.print("第"+i+"趟 ");print(keys);
}
}
4.快速排序
public static void quickSort(int[] keys){ // 快速排序(升序)
System.out.println("快速排序(升序)");
quickSort(keys, 0, keys.length - 1);
}
// 对存于keys数组begin~end之间的子序列进行一趟快速排序,递归算法
private static void quickSort(int[] keys, int begin, int end) {
if(begin>=0&&begin<keys.length&&end>=0&&end<keys.length&&begin<end){// 序列有效
int i = begin, j = end; // i、j下标分别从子序列的前后两端开始
int vot = keys[i]; // 子序列第一个值作为基准值
while (i != j) {
while (i < j && keys[j] >= vot) // (升序)从后向前寻找较小值,不移动与基准值相等元素
j--;
if (i < j)
keys[i++] = keys[j]; // 子序列后端较小元素向前移动
while (i < j && keys[i] <= vot) // (升序)从前向后寻找较大值,不移动与基准值相等元素
i++;
if (i < j)
keys[j--] = keys[i]; // 子序列前端较大元素向后移动
}
keys[i] = vot; // 基准值到达最终位置
System.out.print("下标" + begin + "~" + end + ", vot=" + vot + ", ");
print(keys);
quickSort(keys, begin, j - 1);
// 前端子序列再排序,递归调用 quickSort(keys, i + 1, end); // 后端子序列再排序,递归调用
System.out.println();
}
}
5.×堆排序
6.简单(直接)选择排序
public static void selectSort(int[] keys) { // 直接选择排序(升序)
System.out.println("直接选择排序(升序)");
for (int i = 0; i < keys.length - 1; i++) { // n-1趟排序
int min = i;
for (int j = i + 1; j < keys.length; j++) // 每趟在从keys[i]开始的子序列中寻找最小元素
if (keys[j] < keys[min]) // (升序// if (keys[j]>keys[min]) //(降序) min = j; // min记住本趟最小元素下标
System.out.print("第" + (i + 1) + "趟,下标" + i + "~" + (keys.length - 1) + ",min=" + min + ",");
if (min != i) // 将本趟最小元素交换到前边
swap(keys, i, min);
print(keys);
System.out.println();
}
}
private static void swap(int[] keys, int i, int j) { // 交换keys[i]与keys[j]元素,i、j范围由调用者控制
int temp = keys[j];
keys[j] = keys[i];
keys[i] = temp;
}
7.×归并排序