2、链表
1、创建链表-无头结点
#include<stdio.h> #include<malloc.h> #include<assert.h> typedef int ElemType; //定义链表 typedef struct ListNode{ ElemType data; struct ListNode* next; }ListNode; typedef ListNode* PList; //初始化链表,让链表一开始指向为空 void initList(PList* head){//此处相当于ListNode** plist [二级指针存储一级指针的地址] *head = NULL; } //创建链表 尾插法[无虚拟头结点] void createListByPushBack(PList* head){ *head = (ListNode*)malloc(sizeof(ListNode)); // if(*head == NULL){ // printf("内存空间不足.\n"); // return; // } assert(*head != NULL); //处理第一个结点 (*head)->data = 1; (*head)->next = NULL; ListNode* temp = *head; int i = 2; for(i;i <= 3;i++){ ListNode *p = (ListNode*)malloc(sizeof(ListNode)); assert(p != NULL); p->data = i; p->next = NULL; temp->next = p; temp = p; } } //创建链表 头插法[无虚拟头结点] void createListByPushFront(PList* head){ *head = (ListNode*)malloc(sizeof(ListNode)); assert(*head != NULL); //处理第一个结点 (*head)->data = 1; (*head)->next = NULL; int i = 2; for(i;i <= 3;i++){ ListNode *p = (ListNode*)malloc(sizeof(ListNode)); assert(p != NULL); p->data = i; p->next = *head; *head = p; } } //打印链表 void showList(ListNode* list){ while(list != NULL){ printf("%d ",list->data); list = list->next; } } int main(){ PList myList; initList(&myList); createListByPushFront(&myList); showList(myList); // printf("\n%d",myList->data); return 0; }
2、创建链表-有头结点
//初始化链表,让链表一开始指向为空 void initList(PList* head){//此处相当于ListNode** plist [二级指针存储一级指针的地址] *head = (ListNode*)malloc(sizeof(ListNode));//创建虚拟头结点,该节点不储存数据 assert(*head != NULL); (*head)->next = NULL; } //创建链表 尾插法[有虚拟头结点] void createListByPushBack(PList* head){ ListNode* p = *head; int i = 1; for(i;i <= 3;i++){ p = p->next = (ListNode*)malloc(sizeof(ListNode)); assert(p != NULL); p->data = i; p->next = NULL; } } //创建链表 头插法[无虚拟头结点] void createListByPushFront(PList* head){ ListNode* temp = *head; int i = 1; for(i;i <= 10;i++){ ListNode *p = (ListNode*)malloc(sizeof(ListNode)); assert(p != NULL); p->data = i; p->next = temp->next; temp->next = p; } } //展示链表 void showList(ListNode* list){ ListNode* temp = list->next; while(temp != NULL){ printf("%d--> ",temp->data); temp = temp->next; } }
3、单链表
#include<stdio.h> #include<malloc.h> #include<assert.h> typedef int ElemType; //单链表节点定义 typedef struct Node{ ElemType data; struct Node* next; }Node,*PNode; //单链表定义 typedef struct SingleList{ PNode first; PNode last; int size; }List; //初始化单链表 void initList(List* list){ Node* node = (Node*)malloc(sizeof(Node)); node->next = NULL;//此处最好是置为空 list->first = list->last = node;; list->size = 0; } //尾插法[带有虚拟头结点] void push_back(List* list,ElemType data){ Node* pNode = (Node*)malloc(sizeof(Node)); assert(pNode != NULL); pNode->data = data; pNode->next = NULL; list->last->next = pNode; list->last = pNode; list->size++; } //头插法[带有虚拟头结点] void push_front(List* list,ElemType data){ Node* pNode = (Node*)malloc(sizeof(Node)); assert(pNode != NULL); pNode->data = data; //指向第一个节点 pNode->next = list->first->next; list->first->next = pNode; list->size++; } //打印链表数据 void show_list(List* list){ PNode p = list->first->next; while(p != NULL){ printf("%d",p->data); if(p->next != NULL){ printf("->"); } p = p->next; } } //尾部删除 void pop_back(List* list){ if(list->size == 0){ printf("链表长度为0,不可进行删除操作.\n"); return; } PNode p = list->first; //p指向最后一个节点的上一个节点 while(p->next != list->last){ p = p->next; } //释放空间 free(list->last); //改变单链表的尾指针指向 list->last = p; list->last->next = NULL; list->size--; } //头部删除 void pop_front(List* list){ if(list->size == 0){ printf("链表长度为0,不可进行删除操作.\n"); return; } PNode p = list->first->next; list->first->next = p->next; free(p); //注意:如果链表只有一个元素,删除该节点后要修改尾指针! if(list->size == 1){ list->last = list->first; } list->size--; } //插入值[默认链表已经从小到大排序好] void insert_val(List* list,ElemType e){ Node* pNode = (Node*)malloc(sizeof(Node)); pNode->data = e; PNode p = list->first; while(p->next != NULL && p->next->data < e){ p = p->next; } //说明当前插入的位置是最后一个 if(p->next == NULL){ //修改尾指针 list->last = p; } //插入节点 pNode->next = p->next; p->next = pNode; list->size++; } //查找值 Node* find(List list,ElemType e){ PNode p = list.first->next; while(p != NULL){ if(e == p->data){ return p; } p = p->next; } return NULL; } //单链表长度 int length(List list){ return list.size; } //按值删除 void delete_val(List* list,ElemType data){ Node* node = find(*list,data); if(node == NULL){ printf("删除值不存在链表中.\n"); return; } /* 注意 这里找到要删除的节点,按之前的思路是要 用删除节点的前驱去指向删除节点的后继 但这里前驱不好寻找,因此更换思路, 直接用 删除节点的后继 覆盖 要删除节点 然后在清楚掉后继节点即可 */ if(node = list->last){ //删除最后一个节点 pop_back(list); }else{ Node* p = node->next; node->data = p->data; node->next = p->next; free(p); } list->size--; } //排序 void sort(List* list){ if(list->size <= 1){ return; } //指向第一个节点 Node* p = list->first->next; //指向第二个节点 Node* q = p->next; //断开链表,形成两个链表,后续遍历第二个链表, //然后参照按值插入的方式插入数据 list->last = p; p->next = NULL; while(q != NULL){ p = q; q = q->next; Node* temp = list->first; while(temp->next != NULL && temp->next->data < p->data){ temp = temp->next; } if(temp->next == NULL){ list->last = p; } p->next = temp->next; temp->next = p; } } //逆置链表 void reverse(List* list){ /* 逆置思路跟上面差不多 将链表一分为二,然后将第二个链表元素依次头插到第一个链表即可 */ if(list->size <= 0){ return; } //指向第一个元素 Node* p = list->first->next; //指向第二个元素 Node* q = p->next; //链表一分为二 list->last = p; p->next = NULL; while(q != NULL){ p = q; q = q->next; p->next = list->first->next; list->first->next = p; } } //清空链表 void clear(List* list){ if(list->size == 0){ return; } Node* p = list->first->next; while(p != NULL){ list->first->next = p->next; free(p); p = list->first->next; } list->last = list->first; list->size = 0; } //销毁链表 void destroy(List* list){ clear(list); free(list->first); list->first = list->last = NULL; } int main(){ List list; initList(&list); int select = 1; ElemType item = 0; while(select){ printf("\n"); printf("***********************************\n"); printf("* [1] push_back [2] push_front *\n"); printf("* [3] show_list [4] pop_back *\n"); printf("* [5] pop_front [6] insert_val *\n"); printf("* [7] find [8] length *\n"); printf("* [9] delete_val [10] sort *\n"); printf("* [11] reverse [12] clear *\n"); printf("* [13] destroy [0] exit_system *\n"); printf("***********************************\n"); printf("请选择> "); scanf("%d",&select); if(!select){ break; } PNode p = NULL; switch(select){ case 1: printf("请输入要输入的数据(-1结束):>"); while(scanf("%d",&item),item != -1){ push_back(&list,item); } break; case 2: printf("请输入要输入的数据(-1结束):>"); while(scanf("%d",&item),item != -1){ push_front(&list,item); } break; case 3: show_list(&list); break; case 4: pop_back(&list); break; case 5: pop_front(&list); break; case 6: printf("请输入要插入的数据:>"); scanf("%d",&item); insert_val(&list,item); break; case 7: printf("请输入要查找的数据:>"); scanf("%d",&item); p = find(list,item); if(p == NULL){ printf("查找的数据不存在.\n"); } break; case 8: printf("该链表长度为: %d.\n",length(list)); break; case 9: printf("请输入要删除的数据:>"); scanf("%d",&item); delete_val(&list,item); break; case 10: sort(&list); break; case 11: reverse(&list); break; case 12: clear(&list); break; case 13: destroy(&list); break; } } destroy(&list); return 0; }
4、单链表-代码优化
//---头插尾插优化start-------- //创建节点 Node* create_node(ElemType e){ Node* pNode = (Node*)malloc(sizeof(Node)); assert(pNode != NULL); pNode->data = e; pNode->next = NULL; return pNode; } //返回第一个节点 Node* begin(List* list){ return list->first->next; } //返回最后一个 Node* end(List* list){ return list->last->next; } //针对pos 的前驱进行插入 void insert(List* list,Node* pos,ElemType e){ Node* p = list->first; while(p->next != pos){ p = p->next; } Node* node = create_node(e); node->next = p->next; p->next = node; if(pos == NULL){ //插入到链表最后的位置 list->last = node; } list->size++; } //尾插法[优化] void push_back_plus(List* list,ElemType data){ insert(list,end(list),data); } //头插法优化 void push_front_plus(List* list,ElemType data){ insert(list,begin(list),data); } //-------------end-------------

浙公网安备 33010602011771号