顺序表
这个是动态顺序表,我觉得功能已经十分的齐全了,要是有缺少的功能大家可以私信或者在评论区告诉我,我会修改的。
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<assert.h> #include<stdlib.h> typedef int SLDatatype; typedef struct SeqList { SLDatatype* a; int size;//储存的有效数据个数 int capacity;//容量 }SL; void SLInit(SL* psl) { assert(psl); psl->a = (SLDatatype*)malloc(sizeof(SLDatatype)*4); if (psl->a == NULL) { perror("malloc fail"); return; } psl->size = 0; psl->capacity = 4; } void SLCheckCapacity(SL* psl) { assert(psl); if (psl->size == psl->capacity) { SLDatatype* tmp = (SLDatatype*)realloc(psl->a,sizeof(SLDatatype) * psl->capacity * 2); if (tmp == NULL) { perror("realloc fail"); return; } psl->a = tmp; psl->capacity *= 2; } } void SLDestroy(SL* psl) { assert(psl); free(psl->a); psl->a = NULL; psl->size = 0; psl ->capacity = 0; } void SLPrint(SL* psl) { assert(psl); for (int i = 0; i < psl->size; i++) { printf("%d ", psl->a[i]); } printf("\n"); } //STL命名风格 void SLPushBack(SL* psl, SLDatatype x) { assert(psl); SLCheckCapacity(psl); psl->a[psl->size++] = x; } void SLPushFront(SL* psl, SLDatatype x) { assert(psl); SLCheckCapacity(psl); int end = psl->size-1; while (end >= 0) { psl->a[end + 1] = psl->a[end]; --end; } psl->a[0] = x; psl->size++; } void SLPopBack(SL* psl) { assert(psl); if (psl->size <= 0) { return; } psl->size--; } void SLPopFront(SL* psl) { assert(psl); if (psl->size <= 0) { return; } for (int i = 0; i < psl->size-1; i++) { psl->a[i] = psl->a[i + 1]; } psl->size--; } void SLInsert(SL* psl, int pos, SLDatatype x) { assert(psl); SLCheckCapacity(psl);; for (int i = pos; i < psl->size; i++) { psl->a[i+1] = psl->a[i]; } psl->a[pos] = x; psl->size++; } void SLErase(SL* psl, int pos) { assert(psl); if (psl->size <= 0) { return; } for (int i = pos; i < psl->size-1; i++) { psl->a[i] = psl->a[i + 1]; } psl->size--; } // 找到返回下标,没有找到返回-1 int SLFind(SL* psl, SLDatatype x) { assert(psl); for (int i = 0; i < psl->size; i++) { if (psl->a[i] == x) { return i; } } return -1; } void SLModify(SL* psl, int pos, SLDatatype x) { assert(psl); psl->a[pos] = x; } void menu() { printf("***************************************\n"); printf("1、尾插数据 2、尾删数据\n"); printf("3、头插数据 4、头删数据\n"); printf("5、打印数据 6.修改数据\n"); printf("-1.退出程序\n"); printf("***************************************\n"); } int main() { int option = 0; SL s; SLInit(&s); while (option != -1) { menu(); printf("请输入你的操作:>"); scanf("%d", &option); if (option == 1) { /*printf("请输入要尾插的数据,以-1结束:"); int x = 0; scanf("%d", &x); while (x != -1) { SLPushBack(&s, x); scanf("%d", &x); }*/ int n = 0; printf("请输入要尾插的数据个数,再依次输入要插入的数据:"); scanf("%d", &n); int x = 0; while (n > 0) { scanf("%d", &x); SLPushBack(&s, x); n--; } } else if (option == 5) { SLPrint(&s); } else if (option == 2) { int n = 0; printf("请输入要尾删的数据个数"); scanf("%d", &n); int x = 0; while (n > 0) { SLPopBack(&s); n--; } } else if (option == 3) { int n = 0; printf("请输入要头插的数据个数,再依次输入要插入的数据:"); scanf("%d", &n); int x = 0; while (n > 0) { scanf("%d", &x); SLPushFront(&s, x); n--; } } else if (option == 4) { int x; int n; printf("请输入需要头删的个数"); scanf("%d", &n); while (n) { SLPopFront(&s); n--; } } else if (option == 6) { printf("请输入要修改的数的下标\n"); int x; scanf("%d", &x); printf("请输入修改后的数字\n"); int n; scanf("%d", &n); SLModify(&s, x, n); } else if (option == -1) { break; } else { printf("无此选项,请重新输入\n"); } } SLDestroy(&s); return 0; }
单链表
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<assert.h> typedef int SLTDataType; typedef struct SListNode { SLTDataType data; struct SListNode* next; }SLTNode; void SLTPrint(SLTNode* phead) { SLTNode* cur = phead; while (cur != NULL) { printf("%d=>", cur->data); cur = cur->next; } printf("NULL"); printf("\n"); } SLTNode* BuyLTNode(SLTDataType x) { SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode)); if (newnode == NULL) { perror("malloc fail"); return NULL; } newnode->data = x; newnode->next = NULL; return newnode; } void SLPushFront(SLTNode** pphead, SLTDataType x) { SLTNode* newnode = BuyLTNode(x); if (*pphead == NULL) { *pphead = newnode; } else { newnode->next = *pphead; *pphead = newnode; } } void SLPushBack(SLTNode** pphead, SLTDataType x) { SLTNode* cur = *pphead; SLTNode* newnode = BuyLTNode(x); if (*pphead == NULL) { *pphead = newnode; newnode = *pphead; } else { while (cur->next!= NULL) { cur = cur->next; } cur->next = newnode; } } void SLPopFront(SLTNode** pphead) { assert(*pphead); SLTNode* del = *pphead; *pphead = (*pphead)->next; free(del); } void SLPopBack(SLTNode** pphead) { assert(*pphead); if ((*pphead)->next == NULL) { free(*pphead); *pphead = NULL; } else { SLTNode* tail = *pphead; // 找到尾结点 while (tail->next->next) { tail = tail->next; } free(tail->next); tail->next = NULL; } } void TestSList2() { SLTNode* plist = NULL; SLPushBack(&plist, 1); SLPushBack(&plist, 2); SLPushBack(&plist, 3); SLPushBack(&plist, 4); SLPopFront(&plist); SLPushFront(&plist, 1); SLPopBack(&plist); SLPushBack(&plist, 4); SLTPrint(plist); } int main() { TestSList2(); return 0; }
双向链表
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<assert.h> #include<stdbool.h> typedef int LTDataType; typedef struct ListNode { struct ListNode* prev; struct ListNode* next; LTDataType data; }LTNode; LTNode* BuyLTNode(LTDataType x) { LTNode* newnode = (LTNode*)malloc(sizeof(LTNode)); if (newnode == NULL) { perror("malloc fail"); return NULL; } newnode->data = x; newnode->next = NULL; newnode->prev = NULL; return newnode; } LTNode* LTInit() { LTNode* phead = BuyLTNode(-1); phead->next = phead; phead->prev = phead; return phead; } void LTPrint(LTNode* phead) { assert(phead); printf("GUard<==>"); LTNode* cur = phead->next; while (cur != phead) { printf("%d<==>", cur->data); cur = cur->next; } printf("\n"); } bool LTEmpty(LTNode* phead) { assert(phead); return phead->next == phead; } void LTPushBack(LTNode* phead, LTDataType x) { assert(phead); LTNode* tail = phead->prev; LTNode* newnode = BuyLTNode(x); newnode->next = phead; phead->prev = newnode; newnode->prev = tail; tail->next = newnode; } void LTPushFront(LTNode* phead, LTDataType x) { assert(phead); LTNode* head = phead->next; LTNode* newnode = BuyLTNode(x); phead->next = newnode; newnode->prev = phead; newnode->next = head; head->prev = newnode; } void LTPopBack(LTNode* phead) { assert(phead); assert(!LTEmpty(phead)); LTNode* tail = phead->prev; LTNode* tailprev = tail->prev; free(tail); phead->prev = tailprev; tailprev->next = phead; } void LTPopFront(LTNode* phead) { LTNode* head = phead->next; LTNode* headnext = head->next; phead->next = headnext; headnext->prev = phead; free(head); } LTNode* LTFind(LTNode* phead, LTDataType x) { LTNode* cur = phead->next; while (cur!=phead) { if (cur->data == x) { return cur; } cur = cur->next; } return NULL; } // 在pos之前插入 void LTInsert(LTNode* pos, LTDataType x) { assert(pos); LTNode* prev = pos->prev; LTNode* newnode = BuyLTNode(x); newnode->next = pos; pos->prev = newnode; prev->next = newnode; newnode->prev = prev; } // 删除pos位置的值 void LTErase(LTNode* pos) { assert(pos); LTNode* posPrev = pos->prev; LTNode* posNext = pos->next; posPrev->next = posNext; posNext->prev = posPrev; } void LTDestroy(LTNode* phead) { assert(phead); LTNode* cur = phead->next; while (cur!=phead) { LTNode* next = cur->next; free(cur); cur = next; } free(phead); } void TestList3() { LTNode* plist = LTInit(); LTPushFront(plist, 1); LTPushFront(plist, 2); LTPushFront(plist, 3); LTPushFront(plist, 4); LTPrint(plist); LTNode* pos = LTFind(plist, 3); if (pos) { LTInsert(pos, 30); } LTPopFront(plist); LTPopBack(plist); LTPushBack(plist, 9); LTPrint(plist); LTDestroy(plist); plist = NULL; } int main() { TestList3(); return 0; }
像头插,尾删这样的功能,我们可以直接通过复用 LTInsert和LTErase来实现,这样写可以大幅度简化代码,让代码精简。代码如下:
#include<stdio.h> #include<stdlib.h> #include<assert.h> typedef struct Node { int data; struct Node* next; struct Node* prev; }Node; Node* BuyListNode(int x); Node* SLInit(); void LTPopFront(Node* phead); void LTPushFront(Node* phead, int x); void LTPopBack(Node* phead); void LTDestroy(Node* phead); void LTPushBack(Node* phead, int x); void LTErase(Node* phead); void LTInsert(Node* pos, int x); int LTEmpty(Node* phead); void Print(Node* phead); Node* BuyListNode(int x) { Node* newnode = (Node*)malloc(sizeof(Node)); newnode->data = x; newnode->next = NULL; newnode->prev = NULL; return newnode; } Node* SLInit() { Node* phead = BuyListNode(-1); phead->next = phead; phead->prev = phead; return phead; } void LTInsert(Node* pos, int x) { assert(pos); Node* newnode = BuyListNode(x); Node* prev = pos->prev; newnode->next = prev->next; newnode->prev = prev; prev->next = newnode; pos->prev = newnode; } void LTPushFront(Node* phead, int x) { assert(phead); LTInsert(phead->next, x); } void LTPushBack(Node* phead, int x) { assert(phead); LTInsert(phead, x); } void LTPopFront(Node* phead) { assert(phead); assert(!LTEmpty(phead)); LTErase(phead->prev); } void LTErase(Node* pos) { assert(pos); Node* prev = pos->prev; Node* next = pos->next; prev->next = next; next->prev = prev; } void LTPopBack(Node* phead) { assert(phead); assert(!LTEmpty(phead)); LTErase(phead->prev); } void LTDestroy(Node* phead) { assert(phead); Node* cur = phead->next; while (phead != cur) { Node* next = cur->next; free(cur); cur = next; } free(phead); } int LTEmpty(Node* phead) { assert(phead); return phead == phead->next; } void Print(Node* phead) { Node* cur = phead->next; while (cur != phead) { Node* next = cur->next; printf("%d<==>", cur->data); cur = next; } printf("\n"); }
循环双向链表
typedef int DLLData; typedef struct DLLNode { DLLData data; struct ListNode* next; struct ListNode* prev; }ListNode; // 创建返回链表的头结点. ListNode* ListCreate() { ListNode* guard = (ListNode*)malloc(sizeof(ListNode)); guard->next = guard->prev = guard; return guard; } // 创建一个新的结点 ListNode* BuyNewnode(LTDataType x) { ListNode* new_node = (ListNode*)malloc(sizeof(ListNode)); new_node->data = x; return new_node; } // 双向链表销毁 void ListDestroy(ListNode* phead) { assert(phead); ListNode* tmp = phead->next, *node = phead->next; phead->next = NULL; while (tmp) { node = tmp->next; free(tmp); tmp = node; } } // 双向链表打印 void ListPrint(ListNode* phead) { assert(phead); ListNode* tmp = phead->next; printf("phead<=>"); while (tmp != phead) { printf("%d<=>", tmp->data); tmp = tmp->next; } printf("phead\n"); } // 双向链表尾插 void ListPushBack(ListNode* phead, LTDataType x) { assert(phead); ListInsert(phead, x); } // 双向链表尾删 void ListPopBack(ListNode* phead) { assert(phead); assert(!CheckVoid(phead)); ListErase(phead->prev); } // 双向链表头插 void ListPushFront(ListNode* phead, LTDataType x) { assert(phead); ListInsert(phead->next, x); } // 双向链表头删 void ListPopFront(ListNode* phead) { assert(phead); assert(!CheckVoid(phead)); ListErase(phead->next); } // 双向链表查找 ListNode* ListFind(ListNode* phead, LTDataType x) { assert(phead); ListNode* tmp = phead->next; while (tmp != phead) { if (tmp->data == x) return tmp; tmp = tmp->next; } return NULL; } // 双向链表在pos的前面进行插入 void ListInsert(ListNode* pos, LTDataType x) { ListNode* front = pos->prev; ListNode* new_node = BuyNewnode(x); front->next = new_node; new_node->next = pos; pos->prev = new_node; new_node->prev = front; } // 双向链表删除pos位置的节点 void ListErase(ListNode* pos) { pos->prev->next = pos->next; pos->next->prev = pos->prev; free(pos); } // 检查链表为空 bool CheckVoid(ListNode* rhs) { assert(rhs); return rhs->next == rhs; }
栈
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<assert.h> #include<stdbool.h> typedef int STDataType; typedef struct Stack { STDataType* a; int top; int capacity; }ST; void STInit(ST* pst) { assert(pst); pst->a = NULL; pst->top = 0;//这里要注意,如果设置top为-1,则为指向数据位置,如果设置top=0,则指向数据的下一个位置。 pst->capacity = 0; } bool STEmpty(ST* pst) { assert(pst); return pst->top == 0; } void STDestroy(ST* pst) { assert(pst); free(pst->a); pst->a = NULL; pst->top = pst->capacity = 0; } void STPush(ST* pst, STDataType x) { if (pst->top == pst->capacity) { int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2; STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity); if (tmp == NULL) { perror("realloc fail"); return; } pst->a = tmp; pst->capacity = newcapacity; } pst->a[pst->top] = x; pst->top++; } void STPop(ST* pst) { assert(pst); assert(!STEmpty(pst)); pst->top--; } STDataType STTop(ST* pst) { assert(pst); assert(!STEmpty(pst)); return pst->a[pst->top - 1]; } int STSize(ST* pst) { assert(pst); return pst->top; } void TestStack1() { ST st; STInit(&st); STPush(&st, 1); STPush(&st, 2); printf("%d ", STTop(&st)); STPop(&st); STPush(&st, 3); STPush(&st, 4); while (!STEmpty(&st)) { printf("%d ", STTop(&st)); STPop(&st); } STDestroy(&st); } int main() { TestStack1(); return 0; }
队列
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<assert.h> #include<stdbool.h> typedef int QDataType; typedef struct QueueNode { QDataType data; struct QueueNode* next; }QNode; typedef struct Queue { QNode* phead; QNode* ptail; int size; }Queue; void QueueInit(Queue* pq) { assert(pq); pq->phead = NULL; pq->ptail = NULL; pq->size = 0; } bool QueueEmpty(Queue* pq) { assert(pq); return pq->size == 0; } void QueueDestroy(Queue* pq) { assert(pq); QNode* cur = pq->phead; while (cur) { QNode* next = cur->next; free(cur); cur = next; } pq->ptail = pq->phead = NULL; pq->size = 0; } void QueuePush(Queue* pq, QDataType x) { assert(pq); QNode* newnode = (QNode*)malloc(sizeof(QNode)); if (newnode == NULL) { perror("malloc fail"); return; } newnode->data = x; newnode->next = NULL; if (pq->ptail == NULL) { assert(pq->phead == NULL); pq->ptail = pq->phead = newnode; } else { pq->ptail->next = newnode; pq->ptail = newnode; } pq->size++; } void QueuePop(Queue* pq) { assert(pq); assert(!QueueEmpty(pq)); if (pq->phead->next == NULL) { free(pq->phead); pq->phead = pq->ptail = NULL; } else { //头删 QNode* next = pq->phead->next; free(pq->phead); pq->phead = next; } pq->size--; } QDataType QueueFront(Queue* pq) { assert(pq); assert(!QueueEmpty(pq)); return pq->phead->data; } QDataType QueueBack(Queue* pq) { assert(pq); assert(!QueueEmpty(pq)); return pq->ptail->data; } int QueueSize(Queue* pq) { assert(pq); return pq->size; } int main() { Queue* pq = (Queue*)malloc(sizeof(Queue));; QueueInit(pq); QueuePush(pq, 1); QueuePush(pq, 2); QueuePush(pq, 3); QueuePush(pq, 4); QueuePush(pq, 5); printf("%d\n", QueueSize(pq)); printf("%d\n", QueueFront(pq)); printf("%d\n", QueueBack(pq)); return 0; }
循环队列
# include<stdio.h> # include<malloc.h> # define TRUE 1 # define FALSE 0 /*链队列*/ /*链队列的存储结构*/ typedef struct Node { int data; //队列数据域 struct Node* next; //队列指针域 }LinkQueueNode; typedef struct { LinkQueueNode* front;//头指针 LinkQueueNode* rear;//尾指针 }LinkQueue; /*链队列的初始化*/ int InitQueue(LinkQueue* Q) { Q->front = (LinkQueueNode*)malloc(sizeof(LinkQueueNode)); if (Q->front != NULL) { Q->rear = Q->front; Q->front->next = NULL; return TRUE; } else return FALSE; //溢出 } /*链队列的创建*/ void CreateQueue(LinkQueue* Q) { LinkQueueNode* NewNode; int c, flag = 1; while (flag) { scanf("%d", &c); if (c != 0) { NewNode = (LinkQueueNode*)malloc(sizeof(LinkQueueNode)); NewNode->data = c; Q->rear->next = NewNode; //新结点插入到队尾 Q->rear = NewNode; //修改队尾指针 } else { flag = 0; NewNode->next = NULL; } } } /*链队列入队*/ int EnterQueue(LinkQueue* Q, int x) { /*将数据元素x插入到队列Q中*/ LinkQueueNode* NewNode; NewNode = (LinkQueueNode*)malloc(sizeof(LinkQueueNode)); if (NewNode != NULL) { NewNode->data = x; NewNode->next = NULL; Q->rear->next = NewNode; //新结点插入到队尾 Q->rear = NewNode; //修改队尾指针 return TRUE; } return FALSE; } /*链队列出队*/ int DeleteQueue(LinkQueue* Q, int* x) { /*将队列Q的队头元素出队,并保存到x中*/ LinkQueueNode* p; if (Q->front == Q->rear) //空队列 return FALSE; p = Q->front->next; //p指向队头元素 Q->front->next = p->next; //队头元素p出队 if (Q->rear == p) //若队中只有一个元素p,则p出队后成为空队 Q->rear = Q->front; *x = p->data; free(p); return TRUE; } /*队列输出*/ void Display(LinkQueue* Q) { if (Q->front == Q->rear) //空队列 printf("空队列!\n"); else { LinkQueueNode* p; p = Q->front->next; //p指向队头元素 while (p != NULL) { printf("%d ", p->data); p = p->next; } printf("\n"); } } int main() { int x; LinkQueue Q; InitQueue(&Q); //初始化队列 printf("创建队列(以0结束):"); //创建 CreateQueue(&Q); printf("创建的队列元素为:"); Display(&Q); EnterQueue(&Q, 5); //入队 printf("入队后队中元素为:"); Display(&Q); DeleteQueue(&Q, &x); //出队 printf("出队元素为:%d\n", x); printf("出队后队中元素为:"); Display(&Q); return 0; }
二叉树
二叉树的层序遍历需要用到队列的知识,大家看代码可能不理解是什么意思,不过没关系。
只要你画个图,一切就会豁然开朗!
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<assert.h> #include<stdbool.h> typedef int BTDataType; typedef struct BinaryTreeNode { BTDataType data; struct BinaryTreeNode* left; struct BinaryTreeNode* right; }BTNode; typedef BTNode* QDataType; typedef struct QueueNode { struct QueueNode* next; QDataType data; }QNode; typedef struct Queue { QNode* phead; QNode* ptail; int size; }Queue; void QueueInit(Queue* pq); void QueueDestroy(Queue* pq); void QueuePush(Queue* pq, QDataType x); void QueuePop(Queue* pq); QDataType QueueFront(Queue* pq); QDataType QueueBack(Queue* pq); int QueueSize(Queue* pq); bool QueueEmpty(Queue* pq); BTNode* BuyNode(BTDataType x) { BTNode* newnode = (BTNode*)malloc(sizeof(BTNode)); if (newnode == NULL) { perror("malloc fail"); return NULL; } newnode->data = x; newnode->left = NULL; newnode->right = NULL; return newnode; } void PrevOrder(BTNode* root) { if (root == NULL) { printf("NULL "); return; } printf("%d ", root->data); PrevOrder(root->left); PrevOrder(root->right); } void InOrder(BTNode* root) { if (root == NULL) { printf("NULL"); return; } InOrder(root->left); printf("%d ", root->data); InOrder(root->right); } void PostOrder(BTNode* root) { if (root == NULL) { printf("NULL "); return; } PostOrder(root->left); PostOrder(root->right); printf("%d ", root->data); } int BTNodeSize(BTNode* root) { return root == NULL ? 0 : BTNodeSize(root->left) + BTNodeSize(root->right) + 1; } int BTreeLeafSize(BTNode* root) { if (root == NULL) { return 0; } if (root->left == NULL && root->right == NULL) { return 1; } return BTreeLeafSize(root->left) + BTreeLeafSize(root->right); } int BTreeHeight(BTNode* root) { if (root == NULL) { return 0; } int LeftHeight = BTreeHeight(root->left); int RightHeight = BTreeHeight(root->right); return LeftHeight > RightHeight ? LeftHeight + 1 : RightHeight + 1; } int BTreeLevelKSize(BTNode* root, int k) { assert(k > 0); if (root == NULL) { return 0; } if (k == 1) { return 1; } return BTreeLevelKSize(root->left, k - 1) + BTreeLevelKSize(root->right, k - 1); } BTNode* BTFind(BTNode* root, BTDataType x) { if (root == NULL) { return NULL; } if (root->data == x) { return root; } BTNode* ret1 = BTFind(root->left, x); if (ret1) { return ret1; } BTNode* ret2 = BTFind(root->right, x); if (ret2) { return ret2; } return NULL; } void BTreeNodeDestroy(BTNode* root) { if (root == NULL) { return; } BTreeNodeDestroy(root->left); BTreeNodeDestroy(root->right); free(root); } // 判断二叉树是否是完全二叉树 bool BTreeComplete(BTNode* root) { Queue q; QueueInit(&q); if (root) QueuePush(&q, root); while (!QueueEmpty(&q)) { BTNode* front = QueueFront(&q); QueuePop(&q); // 遇到空就跳出 if (front == NULL) break; QueuePush(&q, front->left); QueuePush(&q, front->right); } // 检查后面的节点有没有非空 // 有非空,不是完全二叉树 while (!QueueEmpty(&q)) { BTNode* front = QueueFront(&q); QueuePop(&q); if (front) { QueueDestroy(&q); return false; } } QueueDestroy(&q); return true; } void InsertSort(int* a, int n) { for (int i = 1; i < n; ++i) { // [0, end] 有序,插入tmp依旧有序 int end = i - 1; int tmp = a[i]; while (end >= 0) { if (a[end] > tmp) { a[end + 1] = a[end]; --end; } else { break; } } a[end + 1] = tmp; } }
图的知识太多了,我在这里就不列举了。
大家期末加油。。。祝大家拿满绩。。。