009.day07

day07笔记

一、数组排序

1. 冒泡排序

每两个元素比较,按照从小到大顺序时,两两找出较大值,可能会发生交换,将较大值放在右侧,按照从大到小顺序时,两两比较找出较小值,可能会发生交换,将较小值放在右侧

  • 代码实现(由小到大)

    • 第一种写法

      // TODO 冒泡排序
              int[] a = { 34, 23, 77, 66, 3, 145 };
              // 排序的次数:数组元素的个数减一(当最后一个数的时候就不用排了)
              for (int i = 0; i < a.length - 1; i++) {
                   // 当第一层循环到达i次时,第二层循环就可以减去第一次循环已经排好的次数,所以for循            // 环跳出的条件为a.length - 1 - i
                  for (int j = 0; j < a.length - 1 - i; j++) {
                      // 两个数字的比较,从左至右,从小到大
                      if (a[j] > a[j + 1]) {
                       //亦或交换位置格式为三行
                       // a = a ^ b
                       // b = a ^ b
                       // a = a ^ b
                          a[j] = a[j] ^ a[j + 1];
                          a[j + 1] = a[j] ^ a[j + 1];
                          a[j] = a[j] ^ a[j + 1];
                      }
                  }
              }
              for (int temp : a) {
                  System.out.println(temp);
              }
    • 第二种写法

// TODO 冒泡排序
        int[] a = { 34, 23, 77, 66, 3, 145 };
        // 排序的次数:数组元素的个数减一
        for (int i = 0; i < a.length - 1; i++) {
            // j的取值为当前数组能够取到的下标减去已经排好的数(已经执行排序的次数)
            for (int j = a.length - 1; j > i; j--) {
                // 两个数字的比较,是否交换
                // 从左至右,从小到大
                if (a[j - 1] > a[j]) {
                    a[j] = a[j] ^ a[j - 1];
                    a[j - 1] = a[j] ^ a[j - 1];
                    a[j] = a[j] ^ a[j - 1];
                }
            }
        }
        for (int temp : a) {
            System.out.println(temp);
        }
小练习

需求:将学生对象按照ID大小排序

//这是一个学生对象
public Student(Integer id, String name) {
        this.id = id;
        this.name = name;
    }
    private Integer id;
    private String name;
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
// 测试
public static void main(String[] args) {
        Student[] students = new Student[3];
        students[0] = new Student(2,"sand");
        students[1] = new Student(1,"yokii");
        students[2] = new Student(0,"Agiao");
        // 经过排序后,数组中的对象按照学号正序
        for (int i = 0; i < students.length; i++) {
            for (int j = 0; j < students.length - 1 - i; j++) {
                if (students[j].getId() > students[j + 1].getId()) {
                    Student temp = null;
                    temp = students[j];
                    students[j] = students[j + 1];
                    students[j + 1] = temp;
                }
            }
        }
        for (Student student : students) {
            System.out.println(student.getId());
        }
    }

1422552-20180721100453384-1833185697.png

2. 选择排序

冒泡算法的改进,每次从当前比较的一组数中选出最值,排好一个数,只进行一次交换

1422552-20180721100518996-350888657.png

  • 代码实现
// TODO 选择排序
        int[] a = { 34, 23, 77, 66, 3, 145 };
        // 排序的次数:数组元素的个数减一
        for (int i = 0; i < a.length - 1; i++) {
            // 每次指向a[0]
            int max = 0;
            // 这一层循环的目的是找到这一次循环中最大数的下标为max
            // (优化)第二层循环可以减去第一层循环已经排好的数
            for (int j = 1; j < a.length - i; j++) {
                if (a[j] > a[max]) {
                    max = j;
                }
            }
            // 判断找到的最大数是否为第一层循环的当前最后一个
            // 如果不是,则将当前获取到的最大的数与第一层循环的当前最后一个交换位置
            // a ^ a = 0(亦或运算->相同为0,不同为1)
            if (max != a.length - i - 1) {
                /*int temp = a[max];
                a[max] = a[a.length - i - 1];
                a[a.length - i - 1] = temp;*/
                a[max] = a[max] ^ a[a.length - i - 1];
                a[a.length - i - 1] = a[max] ^ a[a.length - i - 1];
                a[max] = a[max] ^ a[a.length - i - 1];
            }
        }
        for (int i : a) {
            System.out.println(i);
        }

3. Arrays工具类

  • Arrays所在包:java.util
  • sort方法:将数组的元素按照自然序列排序(基本数据类型),也可以自定义排序规则
  • 使用规则:无返回值类型,直接传入数组变量作为参数
int a[] = {25,66,7,8,43,200}
Arrays.sort(a);

二、数组查找

1. 二分法查找

在一个有序数组中查找一个数,返回其所在位置

1422552-20180721100622014-210818656.png

  • 代码实现
        // TODO 有序数组的二分查找
        int[] a = {3,20,10,5,67,103};
        Arrays.sort(a);
        for (int i : a) {
            System.out.print(i + "  ");
        }
        System.out.println();
        System.out.println("请输入要查找的数:");
        Scanner scanner = new Scanner(System.in);
        // n为要查找的数
        int n = scanner.nextInt();
        // 初始化用于标记区间的变量
        int left = 0;
        int right = a.length - 1;
        // 初始化每次用于比较的变量的下标
        int middle = (left + right) / 2;
        // 标记是否已经找到相应的数字
        int location = -1;
        // 当要查找的数不存在于数组中时,left>right,跳出循环
        while(left <= right) {
            if (a[middle] == n) {
                // 找到时,标记下标位置,并且跳出
                location = middle;
                break;
            }else if (n > a[middle]) {
                // 在右侧区间中,将left指标右移
                left = middle + 1;
                middle = (left + right) / 2; 
            }else {
                // 在左侧区间中,将right指标左移
                right = middle - 1;
                middle = (left + right) / 2; 
            }
        }
        // 当找到这个数时,location改变为这个数的下标
        if (location != -1) {
            System.out.println("位置为" + (location + 1));
        }else {
         // 找不到这个数时,location的值没有改变为-1
            System.out.println("数组中没有该元素");
        }
        scanner.close();

三、数组扩容

数组定义后长度固定,可以新建一个数组,迁移原数组数据,并提供更多的空间放入新数据

ArrayList的add方法(用于向集合中添加新的元素):ArrayList底层通过数组结构实现,过程与数组扩容步骤类似

需求:用户从控制台不断的录入数据,当数据录入的个数已经超过数组容量时可以自动扩容,继续接受元素

步骤:

​ 定义一个数组(a),例如长度为5
定义一个变量,记录用户输入了几个数据,即数组(a)中已经添加了几个元素
每次用户输入数据时,使用变量判断是否超出了当前数组(a)的长度
如果超出,定义一个新的数组(b),复制原来数组中的数据到新数组(b)
将新输入的元素添加到数组(b)中,并将新数组赋值给原数组(a)

  • 代码实现
// 定义全局变量数组a
static int[] a = new int[3];        
public static void main(String[] args) {
        // TODO 数组扩容
         // 实例化扫描器
        Scanner scanner = new Scanner(System.in);
        //控制是否继续输入数据  
        boolean flag = true;
        // 标记数组当前存储元素的个数
        int index = 0;
        while(flag) {
            System.out.println("请输入一个数");
            int number = scanner.nextInt();
            if (index == a.length) {
                //当index自增到与a数组的长度相等时调用扩容方法
                extend();
            }
         // 先把输入的输赋给a[index],然后index再自增
            a[index ++] = number;
            scanner.nextLine();
            System.out.println("是否继续输入y/n");
            String input = scanner.nextLine();
            if ("y".equals(input)) {
                flag = true;
            }else {
                flag = false;
            }
        }
        for (int number : a) {
            System.out.println(number);
        }
        scanner.close();
    }
    
    /**
     * 将原数组数据保留下来,并扩充空间
     */
    public static void extend() {
        // new一个新数组,长度为原来数组的长度+1
        int[] b = new int[a.length + 1];
        for (int i = 0; i < a.length; i++) {
            // 保留原数据
            b[i] = a[i];
        }
        // 把保存了原数据并扩容后的新数组b赋给原数组a
        // 也就是把a指向b的地址
        a = b;
    }

四、数组结构(与链表比较)

  • 数组适合数据的查找,不适合元素的更新,原因:连续的空间
  • 链表不适合数据的查找,适合元素的更新,原因:拆下或插入新节点容易

1422552-20180721100557503-69821484.png

转载于:https://www.cnblogs.com/yokii/p/9345679.html

#include <c8051f360.h> #include <stdio.h> #include <absacc.h> #include <intrins.h> #define WDATADDR XBYTE[0XC009] #define RDATADDR XBYTE[0XC00B] #define WCOMADDR XBYTE[0XC008] #define RCOMADDR XBYTE[0XC00A] #define KEYCS XBYTE[0XC00C] sbit LCD_RST = P3^0; sbit BUZZER = P1^0; struct Time { unsigned char year; unsigned char month; unsigned char day; unsigned char week; unsigned char hour; unsigned char min; unsigned char sec; } currentTime; struct Alarm { unsigned char hour; unsigned char min; unsigned char enable; } alarmTime; unsigned char key_num = 0xff; bit timeUpdateFlag = 0; bit alarmTriggered = 0; unsigned char settingMode = 0; unsigned char settingField = 0; unsigned char blinkState = 0; unsigned int tickCount = 0; unsigned char blinkCount = 0; unsigned char alarmCount = 0; // 星期字符串 (GB2312编码) unsigned char code WEEKDAYS[][3] = { {0xD6, 0xDC, 0x00}, // 日 {0xD2, 0xBB, 0x00}, // 一 {0xB6, 0xFE, 0x00}, // 二 {0xC8, 0xFD, 0x00}, // 三 {0xCB, 0xC4, 0x00}, // 四 {0xCE, 0xE5, 0x00}, // 五 {0xC1, 0xF9, 0x00} // 六 }; void OSC_INIT(void) { SFRPAGE = 0X0F; OSCICL = OSCICL + 4; OSCICN = 0XC2; CLKSEL = 0X30; SFRPAGE = 0; } void IO_INIT(void) { SFRPAGE = 0X0F; P0MDIN = 0Xe7; P0MDOUT = 0X83; P0SKIP = 0XF9; P1MDIN = 0XFF; P1MDOUT = 0XFF; P1SKIP = 0XFF; P2MDIN = 0XFE; P2MDOUT = 0XFF; P2SKIP = 0XFF; P3MDIN = 0XFF; P3MDOUT = 0XFF; P3SKIP = 0XFD; P4MDOUT = 0XFF; XBR0 = 0X09; XBR1 = 0XC0; SFRPAGE = 0X0; } void XRAM_INIT(void) { SFRPAGE = 0X0F; EMI0CF = 0X07; SFRPAGE = 0; } void SMB_INIT(void) { SMB0CF = 0XC1; } void UART_INIT(void) { SCON0 = 0X0; } void DAC_INIT(void) { IDA0CN = 0XF2; } void ADC_INIT(void) { REF0CN = 0; AMX0P = 0X08; AMX0N = 0X1F; ADC0CF = 0X2C; ADC0CN = 0X80; } void INT0_INIT(void) { IT01CF = 0X05; IT0 = 1; } void TIMER_INIT(void) { TMOD = 0x11; CKCON = 0; TL0 = 0X78; TH0 = 0XEC; TL1 = 0X0C; TH1 = 0XFE; TMR2CN = 0X04; TMR2RLL = 0XF0; TMR2RLH = 0XD8; TMR3CN = 0X0C; TMR3RLL = 0XE0; TMR3RLH = 0XFF; TR0 = 1; ET0 = 1; TR1 = 1; } void PCA_INIT(void) { PCA0CN = 0X40; PCA0MD = 0; } void INT_INIT(void) { EX0 = 1; PX0 = 0; ET0 = 1; ET1 = 0; ET2 = 0; EIE1 = 0X0; ES0 = 0; EA = 1; } void Init_device(void) { OSC_INIT(); IO_INIT(); XRAM_INIT(); SMB_INIT(); UART_INIT(); DAC_INIT(); ADC_INIT(); INT0_INIT(); TIMER_INIT(); PCA_INIT(); INT_INIT(); } void LCD_REST(void) { unsigned int i; LCD_RST = 0; for(i=0;i<255;i++); LCD_RST = 1; } void LCD_WC(unsigned char command) { unsigned char a; while(a = RCOMADDR & 0X80); WCOMADDR = command; } void LCD_INIT(void) { LCD_WC(0X30); LCD_WC(0X01); LCD_WC(0X02); LCD_WC(0X0C); } void LCD_WD(unsigned char d) { while(RCOMADDR & 0X80); WDATADDR = d; } void LCD_HZ(unsigned char x, unsigned char *temp) { unsigned int i = 0; LCD_WC(x); while(temp[i] != 0) { LCD_WD(temp[i]); i++; } } void LCD_BYTE(unsigned char x, unsigned char temp) { LCD_WC(x); LCD_WD(temp); } void LCD_CLR(void) { LCD_WC(0X01); } void LCD_TwoDigit(unsigned char pos, unsigned char num) { LCD_BYTE(pos, (num / 10) + '0'); LCD_BYTE(pos + 1, (num % 10) + '0'); } void KEY_INIT0(void) interrupt 0 { key_num = KEYCS & 0x0f; } void Timer0_ISR(void) interrupt 1 { unsigned char daysInMonth; TL0 = 0x78; TH0 = 0xEC; tickCount++; if(tickCount >= 100) { tickCount = 0; timeUpdateFlag = 1; currentTime.sec++; if(currentTime.sec >= 60) { currentTime.sec = 0; currentTime.min++; if(currentTime.min >= 60) { currentTime.min = 0; currentTime.hour++; if(currentTime.hour >= 24) { currentTime.hour = 0; currentTime.day++; currentTime.week = (currentTime.week + 1) % 7; switch(currentTime.month) { case 2: daysInMonth = 28; break; case 4: case 6: case 9: case 11: daysInMonth = 30; break; default: daysInMonth = 31; } if(currentTime.day > daysInMonth) { currentTime.day = 1; currentTime.month++; if(currentTime.month > 12) { currentTime.month = 1; currentTime.year = (currentTime.year + 1) % 100; } } } } } if(alarmTime.enable && !alarmTriggered) { if(currentTime.hour == alarmTime.hour && currentTime.min == alarmTime.min && currentTime.sec == 0) { alarmTriggered = 1; } } } blinkCount++; if(blinkCount >= 50) { blinkCount = 0; blinkState = !blinkState; } if(alarmTriggered) { alarmCount++; BUZZER = !BUZZER; if(alarmCount >= 300) { alarmCount = 0; alarmTriggered = 0; BUZZER = 0; } } } void Init_Time(void) { currentTime.year = 25; currentTime.month = 6; currentTime.day = 16; currentTime.week = 1; currentTime.hour = 10; currentTime.min = 30; currentTime.sec = 0; alarmTime.hour = 8; alarmTime.min = 0; alarmTime.enable = 1; } void Display_Time(void) { // 第一行: 年月日 LCD_WC(0x80); LCD_WD('2'); LCD_WD('0'); LCD_TwoDigit(0x82, currentTime.year); LCD_WD('-'); LCD_TwoDigit(0x85, currentTime.month); LCD_WD('-'); LCD_TwoDigit(0x88, currentTime.day); // 第一行右侧: 星期 LCD_WC(0x8C); LCD_WD(0xD6); // 周 LCD_WD(0xDC); LCD_HZ(0x8E, WEEKDAYS[currentTime.week]); // 第二行: 时间 LCD_WC(0x90); LCD_TwoDigit(0x90, currentTime.hour); LCD_WD(':'); LCD_TwoDigit(0x93, currentTime.min); LCD_WD(':'); LCD_TwoDigit(0x96, currentTime.sec); // 第三行: 闹铃状态 LCD_WC(0x88); LCD_WD(0xC4); // 闹 LCD_WD(0xD0); // 铃 LCD_WD(':'); LCD_TwoDigit(0x8D, alarmTime.hour); LCD_WD(':'); LCD_TwoDigit(0x90, alarmTime.min); LCD_WC(0x92); LCD_WD('['); LCD_WD(alarmTime.enable ? 'O' : 'X'); LCD_WD(']'); } void Display_Setting(void) { LCD_CLR(); if(settingMode == 1) { // 设置时间 LCD_WC(0x80); LCD_WD(0xC9); // 设 LCD_WD(0xE3); // 置 LCD_WD(0xCA); // 时 LCD_WD(0xB1); // 间 LCD_WD(':'); } else { // 设置闹铃 LCD_WC(0x80); LCD_WD(0xC9); // 设 LCD_WD(0xE3); // 置 LCD_WD(0xC4); // 闹 LCD_WD(0xD0); // 铃 LCD_WD(':'); } switch(settingField) { case 0: // 年 LCD_WC(0x90); LCD_WD(0xC4); // 年 LCD_WD(':'); LCD_WD('2'); LCD_WD('0'); if(!blinkState) LCD_TwoDigit(0x95, currentTime.year); break; case 1: // 月 LCD_WC(0x90); LCD_WD(0xD4); // 月 LCD_WD(':'); if(!blinkState) LCD_TwoDigit(0x93, currentTime.month); break; case 2: // 日 LCD_WC(0x90); LCD_WD(0xC8); // 日 LCD_WD(':'); if(!blinkState) LCD_TwoDigit(0x93, currentTime.day); break; case 3: // 时 LCD_WC(0x90); LCD_WD(0xCA); // 时 LCD_WD(':'); if(!blinkState) LCD_TwoDigit(0x93, currentTime.hour); break; case 4: // 分 LCD_WC(0x90); LCD_WD(0xB7); // 分 LCD_WD(':'); if(!blinkState) LCD_TwoDigit(0x93, currentTime.min); break; case 5: // 星期 LCD_WC(0x90); LCD_WD(0xD0); // 星 LCD_WD(0xC6); // 期 LCD_WD(':'); if(!blinkState) LCD_HZ(0x96, WEEKDAYS[currentTime.week]); break; } } void Process_Key(void) { if(key_num == 0xff) return; switch(key_num) { case 10: // SET键 if(settingMode == 0) { settingMode = 1; settingField = 0; Display_Setting(); } else if(settingMode == 1) { settingMode = 2; settingField = 0; Display_Setting(); } else { settingMode = 0; Display_Time(); } break; case 11: // MODE键 if(settingMode == 1) { settingField = (settingField + 1) % 6; Display_Setting(); } else if(settingMode == 2) { settingField = (settingField + 1) % 2; Display_Setting(); } break; case 12: // ENTER键 if(settingMode == 1 && settingField < 5) { settingField++; Display_Setting(); } break; case 13: // ALARM键 alarmTime.enable = !alarmTime.enable; if(settingMode == 0) Display_Time(); break; case 14: // UP键 if(settingMode == 1) { switch(settingField) { case 0: currentTime.year = (currentTime.year + 1) % 100; break; case 1: currentTime.month = (currentTime.month % 12) + 1; break; case 2: currentTime.day = (currentTime.day % 31) + 1; break; case 3: currentTime.hour = (currentTime.hour + 1) % 24; break; case 4: currentTime.min = (currentTime.min + 1) % 60; break; case 5: currentTime.week = (currentTime.week + 1) % 7; break; } } else if(settingMode == 2) { switch(settingField) { case 0: alarmTime.hour = (alarmTime.hour + 1) % 24; break; case 1: alarmTime.min = (alarmTime.min + 1) % 60; break; } } Display_Setting(); break; case 15: // DOWN键 if(settingMode == 1) { switch(settingField) { case 0: currentTime.year = (currentTime.year + 99) % 100; break; case 1: currentTime.month = (currentTime.month + 10) % 12 + 1; break; case 2: currentTime.day = (currentTime.day + 30) % 31 + 1; break; case 3: currentTime.hour = (currentTime.hour + 23) % 24; break; case 4: currentTime.min = (currentTime.min + 59) % 60; break; case 5: currentTime.week = (currentTime.week + 6) % 7; break; } } else if(settingMode == 2) { switch(settingField) { case 0: alarmTime.hour = (alarmTime.hour + 23) % 24; break; case 1: alarmTime.min = (alarmTime.min + 59) % 60; break; } } Display_Setting(); break; } key_num = 0xff; } void main() { unsigned int i; Init_device(); LCD_REST(); LCD_INIT(); Init_Time(); // 初始显示测试 LCD_WC(0x80); LCD_HZ(0x80, "数字钟测试"); for(i=0; i<30000; i++); // 延时 Display_Time(); while(1) { if(timeUpdateFlag && settingMode == 0) { timeUpdateFlag = 0; Display_Time(); } Process_Key(); // 简单延时 for(i = 0; i < 1000; i++) { _nop_(); } } }
06-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值