笔记2- 数据结构之 线性结构

线性表

顺序存储结构

顺序表:内存地址是连续的
a1,a2,a3,a4.... ai,ai+1,an
a1是a2的前驱,ai+1 是ai的后继,a1没有前驱,an没有后继
n为线性表的长度 ,若n==0时,线性表为空表

优点:
尾插效率高,支持随机访问。
缺点:
中间插入或者删除效率低。
应用:
数组
ArrayList

蛮力法排序:
蛮力法(brute force method,也称为穷举法或枚举法)
是一种简单直接地解决问题的方法,
常常直接基于问题的描述,
所以,蛮力法也是最容易应用的方法。(数据比较少的时候)
但是,用蛮力法设计的算法时间特性往往也是最低的,(数据过多的时候)
典型的指数时间算法一般都是通过蛮力搜索而得到的 。(即输入资料的数量依线性成长,所花的时间将会以指数成长)

冒泡排序     适用于3-5个数据
    /**
     * 冒泡排序  
     * 相邻的左边比右边大的就互相交换位置,一轮过后最大的数就到了顺序表的末尾
     * @param array
     */
    public static void sort_bubble(int[] array){
        if(array == null || array.length == 0){
            return;
        }
        for(int i = array.length -1 ; i > 0 ; i--){
            boolean flag = true;
            for(int j = 0; j < i ; j++){
                if(array[j] > array[j+1]){
                    array[j] = array[j]^array[j+1];
                    array[j+1] = array[j]^array[j+1];
                    array[j] = array[j]^array[j+1];
                    flag = false;
                }
            }
            if(flag){
                break;
            }
        }
    }

选择排序  适用于3-5个数据
    /**
     * 选择排序  快速排序的基础
     * 
     * @param array
     */
    public static void sort_select(int[] array){
        if(array == null || array.length == 0){
            return;
        }
        for(int i = 0 ; i < array.length - 1; i++){
            int index = i;
            for(int j = i + 1; j < array.length;j++){
                if(array[j] < array[index]){
                    index = j;
                }
            }
            if(index != i){
                array[index] = array[i]^array[index];
                array[i] = array[i]^array[index];
                array[index] = array[i]^array[index];
            }
        }
    }

链式存储结构

线性表的链式存储结构:特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的
优点:
插入或者删除效率高。
缺点:
不支持随机访问。

分为:
1.单链表
2.单循环链表
3.双链表
4.双向循环链表

单链表

单链表的每一个数据可以看做是一个节点。
节点由 数据域+指针域组成

单循环链表

单链表的最后一个节点的指针域指向第一个数据

双链表

前指针域+数据域+后 指针域组成。单链表查询只能从前往后进行查找,双链表可以支持从后往前查找,所以优化了查询效率。

双向循环链表

参照 单循环链表

下面附上我自己写的自定义的双向链表代码,仅供大家参考:

package com.xx.lists;
/**
 * 练习  
 * 自定义的双向链表
 * @author Lixin
 *
 * @param <E>
 */
public class MyLinkedList<E> {
    
    private Node<E> first;
    private Node<E> last;
    public int size;
    
    
    // 添加
    public void add(E item){
        addLast(item);
    }
    // 在最后添加一个数据
    public void addLast(E item){
        Node<E> node = new Node(last,item,null);
        Node<E> l = last;
        last=node;
        if(l == null){
            // 此前链表为空
            first = node;
        }else{
            l.next = node;
        }
        size++;
    }
    
    // 在具体位置添加
    public void add(int index, E item){
        if(index < 0 || index > size){
            return;
        }
        if(index == size){
            addLast(item);
        }else{
            Node<E> oldNode = node(index);
            if(oldNode == null){
                throw new NullPointerException();
            }
            Node<E> preNode = oldNode.pre;
            Node<E> newNode = new Node<E>(preNode,item,oldNode);
            
            // old
            oldNode.pre = newNode;
            // pre
            if(preNode != null){
                preNode.next = newNode;
            }else{
                first = newNode;
            }
            size++;
            
        }
    }
    // 根据下标位置找到节点数据  可以看到链表的查找是比较麻烦的
    public E get(int index){
        Node<E> node = node(index);
        if(node!=null){
            return node.item;
        }
        return null;
    }
    
    // 删除
    public void remove(int index){
        Node<E> node = node(index);
        if(node == null){
            return;
        }
        Node<E> nodePre = node.pre;
        Node<E> nodeNext = node.next;
        if(nodePre == null){
            first = nodeNext;
        }else{
            nodePre.next = nodeNext;
        }
        node.pre = null;
        if(nodeNext != null){
            nodeNext.pre = nodePre;
        }else{
            last = nodePre;
        }
        node.next = null;
        size--;
    }
    
    private Node<E> node(int index){
        if(index<0 || index>(size - 1)){
            throw new IndexOutOfBoundsException();
        }
        Node<E> node ;
        // size >> 1  ==  size/2
        if(index < (size>>1)){
            node = first;
            for(int i = 0;i<index;i++){
                node = node.next;
            }
        }else{
            node = last;
            for(int i = size - 1;i > index;i--){
                node = node.pre;
            }
        }
        return node;
         //如果index在整个链表的前半部分
//        if(index<(size>>1)){   //1000 100   10
//            Node<E> node=first;
//            for (int i = 0; i < index; i++) {
//                node=node.next;
//            }
//            return node;
//        }else{
//            Node<E> node=last;
//            for (int i = size-1; i > index; i--) {
//                node=node.pre;
//            }
//            return node;
//        }
    }
    
    

    // 节点
    private class Node<E>{
        public E item;
        // 前一个节点
        public Node<E> pre;
        // 下一个节点
        public Node<E> next;
        
        public Node(Node<E> pre,E item,Node<E> next){
            this.item = item;
            this.pre = pre;
            this.next = next;
        }
    }
}

栈和递归

栈是限定仅在表尾进行插入和删除操作的线性表。
允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。
栈又称为后进先出的线性表

栈的实现方式:
顺序方式:Stack.java类

链式方式:last = 栈顶
入栈方式


image.png

出栈方式


image.png

逆波兰表达式: 高级语言中的运算方法原理,比较麻烦,有时间再开个专题讲解吧,有兴趣的同学也可以百度去查一下相关资料。
大概逻辑是:中缀表达式(如 1+1) (依照数字输出,运算符优先级低出栈,运算符高入栈的原则)转成后缀表达式(1 1 + )
计算时,数字入栈,遇到运算符号就取栈内的两个数字进行计算。

递归

程序调用自身的编程技巧称为递归(recursion)。
递归做为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,
它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,
递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
递归的能力在于用有限的语句来定义对象的无限集合。
一般来说,递归需要有边界条件递归前进段递归返回段
当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
执行特点:每次递归调用的方法会放入方法栈中,然后从栈顶依次调用。

调用自己一次的情况:调用位置前面的代码是正循环,调用位置后面的代码是反循环
调用自己两次的情况:一个二叉树的中序遍历过程

下面为大家介绍一个用递归算法实现的一个程序:
汉诺塔算法:有三根相邻的柱子,标号为A,B,C,A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘,要把所有盘子一个一个移动到柱子B上,并且每次移动同一根柱子上都不能出现大盘子在小盘子上方,请问至少需要多少次移动


image.png
public class RecursionTest {

    public static void main(String[] arg0){
        hanoi(3,1,2,3);
    }
    
    
     /**
     * @param n      盘子的个数
     * @param start   开始的柱子
     * @param middle   中介柱子
     * @param end      结果柱子
     */
    public static void hanoi(int n,int start,int middle,int end){
        if(n<=1){
            System.out.println(start+"----->"+end);
        }else{
            hanoi(n-1,start,end,middle);
            System.out.println(start+"----->"+end);
            hanoi(n-1,middle,start,end);
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容