当前位置: 首页 > news >正文

C/C++ 数据结构 - 链表

1.单链表

https://blog.csdn.net/qq_36806987/article/details/79858957

 1 #include<stdio.h>2 #include<stdlib.h>3 4 /*结构体部分*/5 typedef struct Node6 {7     int data;   //数值域8     struct Node *next;  //指针域9 }N;10 11 N *Init()    //初始化单链表12 {13     N *n;14     n = (N *)malloc(sizeof(N));15     n->next = NULL;16     return n;17 }18 19 N* Create(N* n)20 {21     /*通过输入n个数据,创建一个单链表*/22     int x;23     N *p,*r,*l;24     l = r = n;25     printf("输入-1结束\n");26     scanf("%d",&x);27     while(-1 != x )28     {29         p = (N *)malloc(sizeof(N));30         p -> data = x;31         p -> next = NULL;32         r->next = p;33         r = r->next;    //指针r始终指向链表中末数据元素所在位置34         scanf("%d",&x);35     }36     return l;37 }38 39 void output(N* n) //输出40 {41     N *p;42     p = n->next;43     while(p)44     {45         printf("%d ",p->data);46         p = p->next;47     }48     printf("\n");49 }50 51 int InsItem(N *L,int item,int x) /*给定的序号来插入*/52 {53     int i = 1;54     N *p,*t;55     p = L;56     t = (N *)malloc(sizeof(N));57     t ->data = item;58     if(L->next==NULL)59     {   /*若L为空表且要求将新结点插入到第0个位置*/60         if(x==1)61             {62                 L->next=t;63                 t->next=NULL;64                 return 1;65             }66     }67     while(p->next!=NULL&&i<x)/*查找第i个节点*/68     {69         p = p->next;70         i++;71     }72     if(p->next==NULL&&i<x)/*在表中不存在插入位置i ,找不到,则插入操作失败*/73     {74         return 0;75     }76     else77     {78         t->next = p->next;79         p->next = t;80         return 1;81     }82 }83 84 int DelItem(N *L,int x)//在单链表中删除数据元素85 {86     int i = 1;87     N *p,*q;88     p = L;89     if(L->next==NULL) /*L为空表,无结点可删除*/90     {91         return 0;92     }93     while(p->next!=NULL&&i<x)94     {95         p = p->next;96         i++;97     }98     if(p->next==NULL)/*若没有第i个结点,则删除操作失败*/99     {
100         return 0;
101     }
102     else
103     {
104         q = p->next;
105         p->next = p->next->next;
106         free(q);
107         return 1;
108     }
109 }
110 
111 int main()
112 {
113     N* n = Init();
114     n = Create(n);
115     output(n);
116     InsItem(n,5,5);
117     output(n);
118     DelItem(n,5);
119     output(n);
120 
121     return 0;
122 }

2.双链表

https://blog.csdn.net/qq_16933601/article/details/105351119

1 #include <stdio.h>2 #include <stdlib.h>3 4 typedef struct Node{5     struct Node *pre;6     int data;7     struct Node *next;8 }N;9 10 N *Init()11 {12     N *n;13     n=(N*)malloc(sizeof(N));//鍒涘缓閾捐〃绗竴涓粨鐐癸紙棣栧厓缁撶偣锛?14     n->next = n->pre=NULL;15     return n;16 }17 18 N* Create(N* n)19 {20    /*通过输入n个数据,创建一个单链表*/21     int x;22      N *p,*r,*l;23      l = r = n;24      printf("输入-1结束\n");25      scanf("%d",&x);26      while(-1 != x )27      {28          p = (N *)malloc(sizeof(N));29          p -> data = x;30          p->pre = p -> next = NULL;31          r->next = p;32          p->pre = r;33          r = r->next;    //指针r始终指向链表中末数据元素所在位置34          scanf("%d",&x);35     }36     return l;37 }38 39 void output(N* n) //输出40 {41      N *p;42      p = n->next;43      while(p)44      {45          printf("%d ",p->data);46          p = p->next;47      }48      printf("\n");49 }50 51 int InsItem(N *L,int item,int x) /*给定的序号来插入*/52 {53     int i = 1;54     N *p,*t;55     p = L;56     t = (N *)malloc(sizeof(N));57     t ->data = item;58     if(L->next==NULL)59     {   /*若L为空表且要求将新结点插入到第0个位置*/60         if(x==1)61         {62             L->next=t;63             t->pre = L;64             t->next=NULL;65             return 1;66         }67     }68     while(p->next!=NULL&&i<x)/*查找第i个节点*/69     {70         p = p->next;71         i++;72     }73     if(p->next==NULL&& i == x)/*在表中不存在插入位置i ,找不到,则插入操作失败*/74     {75         t->next = NULL;76         p->next = t;77         t->pre = p;78         return 1;79     }80     else81     {82         p->next->pre=t;83         t->next=p->next;84         p->next=t;85         t->pre=p;86         return 1;87     }88 }89 90 int DelItem(N *L,int x)//在单链表中删除数据元素91 {92     int i = 0;93     N *p,*q;94     p = L;95     if(L->next==NULL) /*L为空表,无结点可删除*/96     {97         return 0;98     }99     while(p->next!=NULL&&i<x)
100     {
101         p = p->next;
102         i++;
103     }
104     if(p->next==NULL && i == x)/*若没有第i个结点,则删除操作失败*/
105     {
106         p->pre->next = NULL;
107         free(p);
108         return 1;
109     }
110     else
111     {
112         p->pre->next=p->next;
113         p->next->pre=p->pre;
114         free(p);
115         return 1;
116     }
117 }
118 
119 int main()
120 {
121     N* n;
122     n = Init();
123     n = Create(n);
124     output(n);
125     InsItem(n,5,5);
126     output(n);
127     DelItem(n,5);
128     output(n);
129 
130     return 0;
131 }

3.单链表的反转

https://liang.blog.csdn.net/article/details/90116419 

1 #include<stdio.h>2 #include<stdlib.h>3  4 typedef int ElemType;5 6 typedef struct Node7 {8     ElemType data;   //数值域9     struct Node *next;  //指针域
10 }Linklist;
11  
12 Linklist *InitList(Linklist *L)    //初始化单链表
13 {
14     L = (Linklist *) malloc(sizeof(Linklist));
15     L->next = NULL;
16     return L;
17 }
18  
19 Linklist *CreateList(int n)
20 {
21     /*通过输入n个数据,创建一个单链表*/
22     int x,i;
23     Linklist *L,*r,*p;
24     L = InitList(L); //构造头结点
25     r = L;
26     printf("input %d value: ",n);
27     for(i=0;i<n;i++)
28     {
29         scanf("%d",&x);
30         p = (Linklist *)malloc(sizeof(Linklist));
31         p -> data = x;
32         p -> next = NULL;
33         r->next = p;
34         r = r->next;    //指针r始终指向链表中末数据元素所在位置
35  
36     }
37     return L;
38 }
39 
40 //头插法
41 int add_node_head(Linklist* head, Linklist* new_node)
42 {
43     if(NULL == head || NULL == new_node)
44         return -1;
45      new_node->next = head->next;
46     head->next = new_node;
47     return 0; 
48 } 
49 
50 //头插方式1-反转链表 
51 Linklist* revert_list(Linklist* head)
52 {
53     if(NULL == head)
54         return NULL;
55  
56     Linklist* p = head->next;
57     head->next= NULL;
58     Linklist* tmp = NULL;
59     while(p)
60     {
61         tmp = p->next;
62         add_node_head(head, p); 
63         p = tmp;    
64     }
65     return head;
66 }
67 
68 void output(Linklist *L) //输出
69 {
70     Linklist *p;
71     p = L->next;
72     printf("output element: \n");
73     for(;p!=NULL;p=p->next)
74     {
75         printf(" %d ",p->data);
76     }
77     printf("\n");
78 }
79 
80 int main()
81 {
82     Linklist *l = CreateList(6);
83     output(l);
84     l = revert_list(l);
85     output(l);
86     
87     return 0;
88 }

4.删除链表中的重复元素

https://blog.csdn.net/m0_59938453/article/details/123021127

1 #include<stdio.h>2 #include<stdlib.h>3  4 typedef int ElemType;5 6 typedef struct Node7 {8     ElemType data;   //数值域9     struct Node *next;  //指针域
10 }Linklist;
11  
12 Linklist *InitList(Linklist *L)    //初始化单链表
13 {
14     L = (Linklist *) malloc(sizeof(Linklist));
15     L->next = NULL;
16     return L;
17 }
18  
19 Linklist *CreateList(int n)
20 {
21     /*通过输入n个数据,创建一个单链表*/
22     int x,i;
23     Linklist *L,*r,*p;
24     L = InitList(L); //构造头结点
25     r = L;
26     printf("input %d value: ",n);
27     for(i=0;i<n;i++)
28     {
29         scanf("%d",&x);
30         p = (Linklist *)malloc(sizeof(Linklist));
31         p -> data = x;
32         p -> next = NULL;
33         r->next = p;
34         r = r->next;    //指针r始终指向链表中末数据元素所在位置
35  
36     }
37     return L;
38 }
39 
40 void output(Linklist *L) //输出
41 {
42     Linklist *p;
43     p = L->next;
44     printf("output element: \n");
45     for(;p!=NULL;p=p->next)
46     {
47         printf(" %d ",p->data);
48     }
49     printf("\n");
50 }
51 
52 Linklist* deleteDuplicates(Linklist* head)
53 {
54     //空链表就直接返回空指针
55     if(NULL == head)  // 注:在条件判断中,head == NULL 和 !head 所起的作用是一样的。
56         return NULL;
57 
58     Linklist* cur = head;
59     while(cur->next)  // 注意循环条件
60     {
61         Linklist* next = cur->next;
62         //若相等,则删掉下一个节点
63         if(cur->data == next->data)
64         {
65             cur->next = next->next;
66             free(next);
67         }
68         //若不等,则将下一个节点变为当前节点
69         else
70             cur = cur->next;
71     }
72     return head;  
73 }
74 
75 int main()
76 {
77     Linklist *l = CreateList(6);
78     output(l);
79     l = deleteDuplicates(l);
80     output(l);
81     
82     return 0;
83 }

c++实现删除链表的重复元素,把重复的元素全部删除(力扣82题):

1 #include <iostream>2 #include <vector>3 using namespace std;4 5 typedef struct Node6 {7    int data;   8     struct Node *next;  9 }Linklist;
10 
11 class node1{
12 public:
13     Linklist *InitList(Linklist *L){    //初始化单链表
14         L = new Linklist;
15         L->next = NULL;
16         return L;
17     }
18     
19     Linklist *CreateList(int n){
20      /*通过输入n个数据,创建一个单链表*/
21         int x,i;
22         Linklist *L,*r,*p;
23         L = InitList(L); //构造头结点
24         r = L;
25         for(i=0;i<n;i++){
26             cin >> x;
27             p = new Linklist;
28             p -> data = x;
29             p -> next = NULL;
30             r->next = p;
31             r = r->next;    //指针r始终指向链表中末数据元素所在位置
32         }
33          return L;
34      }
35     
36      void output(Linklist *L){ //输出
37         Linklist *p;
38         p = L->next;
39         for(;p!=NULL;p=p->next)
40             cout << p->data;
41         cout << endl;
42      }
43      
44     Linklist *deletedup(Linklist *L){
45         Linklist *dumy = new Linklist,*p = dumy;
46         dumy->next = L;
47         while(p->next){
48            Linklist* q = p->next;
49            while(q->next && q->next->data == q->data)  q = q->next;
50            if(q == p->next) p = p->next;
51            else p->next = q->next;
52         }
53         return dumy->next;
54     }
55 };
56 
57 int main()
58 {
59    node1 n;
60    Linklist *l,*p;
61    l = n.CreateList(5);
62    n.output(l);
63    p = n.deletedup(l);
64    n.output(p);
65     
66    return 0;
67 }

c++实现 删除链表重复元素,使得重复元素只出现一次(力扣83题)

1 #include <iostream>2 #include <vector>3 using namespace std;4 5 typedef struct Node6 {7    int data;   8     struct Node *next;  9 }Linklist;
10 
11 class node1{
12 public:
13     Linklist *InitList(Linklist *L){    //初始化单链表
14         L = new Linklist;
15         L->next = NULL;
16         return L;
17     }
18     
19     Linklist *CreateList(int n){
20      /*通过输入n个数据,创建一个单链表*/
21         int x,i;
22         Linklist *L,*r,*p;
23         L = InitList(L); //构造头结点
24         r = L;
25         for(i=0;i<n;i++){
26             cin >> x;
27             p = new Linklist;
28             p -> data = x;
29             p -> next = NULL;
30             r->next = p;
31             r = r->next;    //指针r始终指向链表中末数据元素所在位置
32         }
33          return L;
34      }
35     
36      void output(Linklist *L){ //输出
37         Linklist *p;
38         p = L->next;
39         for(;p!=NULL;p=p->next)
40             cout << p->data;
41         cout << endl;
42      }
43      
44     Linklist *deletedup(Linklist *L){
45         Linklist *p = L;
46         while(p && p->next){
47            Linklist *q = p->next;
48            while(q && q->data == p->data) q = q->next;
49            p->next = q;
50            p = p->next;
51         }
52         return L;
53     }
54 };
55 
56 int main()
57 {
58    node1 n;
59    Linklist *l,*p;
60    l = n.CreateList(5);
61    n.output(l);
62    p = n.deletedup(l);
63    n.output(p);
64     
65    return 0;
66 }

5.链表排序

https://blog.csdn.net/Vectory0213/article/details/79168475

 1 #include<stdio.h>2 #include<stdlib.h>3  4 typedef int ElemType;5 6 typedef struct Node7 {8     ElemType data;   //数值域9     struct Node *next;  //指针域
10 }Linklist;
11  
12 Linklist *InitList(Linklist *L)    //初始化单链表
13 {
14     L = (Linklist *) malloc(sizeof(Linklist));
15     L->next = NULL;
16     return L;
17 }
18  
19 Linklist *CreateList(int n)
20 {
21     /*通过输入n个数据,创建一个单链表*/
22     int x,i;
23     Linklist *L,*r,*p;
24     L = InitList(L); //构造头结点
25     r = L;
26     printf("input %d value: ",n);
27     for(i=0;i<n;i++)
28     {
29         scanf("%d",&x);
30         p = (Linklist *)malloc(sizeof(Linklist));
31         p -> data = x;
32         p -> next = NULL;
33         r->next = p;
34         r = r->next;    //指针r始终指向链表中末数据元素所在位置
35  
36     }
37     return L;
38 }
39 
40 void output(Linklist *L) //输出
41 {
42     Linklist *p;
43     p = L->next;
44     printf("output element: \n");
45     for(;p!=NULL;p=p->next)
46     {
47         printf(" %d ",p->data);
48     }
49     printf("\n");
50 }
51 
52 void BubbleSort(Linklist *head)
53 {
54     Linklist *cur,*tail;
55     cur=head;
56     tail=NULL; 
57     if(cur==NULL||cur->next==NULL){
58         return;
59     }
60     while(cur!=tail)
61     {
62         while(cur->next!=tail)
63         {
64             if(cur->data > cur->next->data)
65             {
66                 int temp=cur->data;
67                 cur->data=cur->next->data;
68                 cur->next->data=temp;
69             }
70             cur=cur->next;
71         }
72         tail=cur;
73         cur=head;
74     }
75 }
76 
77 int main()
78 {
79     Linklist *l = CreateList(6);
80     output(l);
81     BubbleSort(l);
82     output(l);
83     
84     return 0;
85 }

6.旋转链表(链表的移位) 力扣61题

1 #include<stdio.h>2 #include<stdlib.h>3 4 #include<stdio.h>5 #include<stdlib.h>6  7 typedef int ElemType;8 /*结构体部分*/9 typedef struct Node
10 {
11     ElemType data;   //数值域
12     struct Node *next;  //指针域
13 }Linklist;
14  
15 Linklist *InitList(Linklist *L)    //初始化单链表
16 {
17     int x;
18     scanf("%d",&x);
19     L = (Linklist *) malloc(sizeof(Linklist));
20     L->data = x;
21     L->next = NULL;
22     return L;
23 }
24  
25 Linklist *CreateList(int n)
26 {
27     /*通过输入n个数据,创建一个单链表*/
28     int x,i;
29     Linklist *L,*r,*p;
30     L = InitList(L); //构造头结点
31     r = L;
32     printf("input %d value: ",n);
33     for(i=0;i<n;i++)
34     {
35         scanf("%d",&x);
36         p = (Linklist *)malloc(sizeof(Linklist));
37         p -> data = x;
38         p -> next = NULL;
39         r->next = p;
40         r = r->next;    //指针r始终指向链表中末数据元素所在位置
41  
42     }
43     return L;
44 }
45 
46 Linklist *rotatRight(Linklist *head,int k)
47 {
48     if(NULL == head) return NULL;
49     Linklist *cur = head;
50     int n = 1;
51     while(cur->next) cur = cur->next;n++;
52     cur->next = head;
53     for(int i = 0;i<n-k%n;i++)
54     {
55         cur = cur->next;
56     }
57     head = cur->next;
58     cur->next = NULL;
59     return head;
60 }
61 
62 void output(Linklist *L) //输出
63 {
64     Linklist *p;
65     p = L;
66     printf("output element: \n");
67     for(;p!=NULL;p=p->next)
68     {
69         printf(" %d ",p->data);
70     }
71     printf("\n");
72 }
73 
74 int main()
75 {
76     Linklist *l = CreateList(4);
77     output(l);
78     l = rotatRight(l,5);
79     output(l);
80     
81     return 0;
82 }

7.两数之和(力扣第二题)

创建2个链表,对两个链表对应位进行相加。

1 #include<iostream>2 using namespace std;3 4 typedef struct Node5 {6     int data;   7     struct Node *next;  8 }Linklist;9 
10 class node{
11 public:
12     Linklist *InitList(Linklist *L)    //初始化单链表
13     {
14        L = new Linklist;
15        L->next = NULL;
16        return L;
17     }
18  
19     Linklist *CreateList(int n)
20     {
21     /*通过输入n个数据,创建一个单链表*/
22        int x,i;
23        Linklist *L,*r,*p;
24        L = InitList(L); //构造头结点
25        r = L;
26        for(i=0;i<n;i++)
27        {
28            cin >> x;
29            p = new Linklist;
30            p -> data = x;
31            p -> next = NULL;
32            r->next = p;
33            r = r->next;    //指针r始终指向链表中末数据元素所在位置
34        }
35         return L;
36     }
37     
38     void output(Linklist *L) //输出
39     {
40        Linklist *p;
41        p = L->next;
42        for(;p!=NULL;p=p->next)
43        {
44            cout << p->data;
45        }
46        cout << endl;
47     }
48     
49     Linklist *addtwonumbers(Linklist *l1,Linklist *l2)
50     {
51         Linklist *dumy = new Linklist,*cur = dumy;
52         int sum = 0;
53         while(l1 || l2 || sum){
54             if(l1) sum += l1->data,l1=l1->next;
55             if(l2) sum += l2->data,l2=l2->next;
56             cur->next = new Linklist;
57             cur->data = sum%10;
58             cur = cur->next;
59             sum /= 10;
60         }
61         return dumy->next;
62     }
63 };
64 
65 int main()
66 {
67     node n;
68     Linklist *l,*r,*p;
69     l = n.CreateList(3);
70     n.output(l);
71     r = n.CreateList(3);
72     n.output(r);
73     p = n.addtwonumbers(l,r);
74     n.output(p);
75     
76     return 0;
77 }

 8.合并两个有序链表(力扣21题)

1 #include<iostream>2 using namespace std;3  4  typedef struct Node5  {6      int data;   7       struct Node *next;  8  }Linklist;9  
10 class node{
11 public:
12     Linklist *InitList(Linklist *L)    //初始化单链表
13      {
14         L = new Linklist;
15         L->next = NULL;
16         return L;
17      }
18   
19      Linklist *CreateList(int n)
20      {
21      /*通过输入n个数据,创建一个单链表*/
22         int x,i;
23         Linklist *L,*r,*p;
24         L = InitList(L); //构造头结点
25         r = L;
26         for(i=0;i<n;i++)
27         {
28             cin >> x;
29             p = new Linklist;
30             p -> data = x;
31             p -> next = NULL;
32             r->next = p;
33             r = r->next;    //指针r始终指向链表中末数据元素所在位置
34         }
35          return L;
36      }
37      
38      void output(Linklist *L) //输出
39      {
40         Linklist *p;
41         p = L->next;
42         for(;p!=NULL;p=p->next)
43         {
44             cout << p->data;
45         }
46         cout << endl;
47      }
48      
49      Linklist *addtwonumbers(Linklist *l1,Linklist *l2)
50      {
51            Linklist* dumy = new Linklist,*cur = dumy;
52            while(l1 && l2){
53                if(l1->data <=l2->data){
54                   cur->next = new Linklist;
55                   cur->next->data = l1->data;
56                   l1 = l1->next;
57                }else{
58                   cur->next = new Linklist;
59                   cur->next->data = l2->data;
60                   l2 = l2->next;
61                }   
62                cur = cur->next;
63            }
64          cur->next = l1 ? l1 : l2;
65          return dumy->next->next;
66      }
67  };
68  
69  int main()
70  {
71      node n;
72      Linklist *l,*r,*p;
73      l = n.CreateList(3);
74      n.output(l);
75      r = n.CreateList(3);
76      n.output(r);
77      p = n.addtwonumbers(l,r);
78      n.output(p);
79      
80      return 0;
81  }

9.删除链表的倒数第N个元素(力扣第十九题)

#include <iostream>
using namespace std;typedef struct Node
{int data;   //数值域struct Node *next;  //指针域
}Linklist;class node{
public:Linklist *InitList(Linklist *L)    //初始化单链表{L = new Linklist;L->next = NULL;return L;}Linklist *CreateList(int n){/*通过输入n个数据,创建一个单链表*/int x,i;Linklist *L,*r,*p;L = InitList(L); //构造头结点r = L;for(i=0;i<n;i++){cin >> x;p = new Linklist;p -> data = x;p -> next = NULL;r->next = p;r = r->next;    //指针r始终指向链表中末数据元素所在位置}return L;}void output(Linklist *L) //输出{Linklist *p;p = L->next;for(;p!=NULL;p=p->next){cout << p->data << " ";}cout << endl;}Linklist* removee(Linklist* head,int n){Linklist *dumy = new Linklist;Linklist *slow = dumy,*fast = dumy;dumy->next = head;for(int i = 0;i<n;i++){fast = fast->next;}while(fast->next){slow = slow->next;fast = fast->next;}slow->next = slow->next->next;return dumy->next;}
};int main() 
{node n;Linklist *l = n.CreateList(5);n.output(l);l = n.removee(l,4);n.output(l);return 0;
}

http://www.lryc.cn/news/181762.html

相关文章:

  • 【算法基础】一文掌握十大排序算法,冒泡排序、插入排序、选择排序、归并排序、计数排序、基数排序、希尔排序和堆排序
  • javascript二维数组(3):指定数组元素的特定属性进行搜索
  • 使用Qt进行HTTP通信的方法
  • 第45节——页面中修改redux里的数据
  • 软考 系统架构设计师系列知识点之软件架构风格(2)
  • 【C++11】Lambda 表达式:基本使用 和 底层原理
  • 【网络安全---ICMP报文分析】Wireshark教程----Wireshark 分析ICMP报文数据试验
  • 【Docker】Docker的应用包含Sandbox、PaaS、Open Solution以及IT运维概念的详细讲解
  • Java Applet基础
  • 【记录】IDA|IDA怎么查看当前二进制文件自动分析出来的内存分布情况(内存范围和读写性)
  • LIMS实验室信息管理系统源码 基于计算机的数据处理技术、数据存储技术、网络传输技术、自动化仪器分析技术于一体
  • 有效括号相关
  • 浅谈泛型擦除
  • nodejs+vue校园跑腿系统elementui
  • Redis Cluster Cron调度
  • Redis Cluster Gossip Protocol: Message
  • 【JVM】第四篇 垃圾收集器ParNewCMS底层三色标记算法详解
  • STM32复习笔记(四):独立看门狗IWDG
  • SpringBoot中常用注解的含义
  • 学位论文的写作方法,较好的参考文章
  • 基于SpringBoot的科研工作量获奖项目管理平台设计与实现(源码+lw+部署文档+讲解等)
  • 嵌入式Linux应用开发-驱动大全-第一章同步与互斥④
  • 算法-数学-斜率-直线上最多的点数
  • 项目进展(五)-修复PCB电路板,学习32位ADC芯片ADS1285
  • (三) Markdown插入互联网或本地视频解决方案
  • HPA (Horizontal Pod Autoscaler) In K8s
  • Ubuntu安装samba服务器
  • [SpringBoot] 8. aop 获取 request response
  • 同学苹果ios的ipa文件应用企业代签选择签名商看看这篇文章你再去吧
  • 【PyCharm Community Edition】:excel操作