c语言单向链表
一、链表概述
链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。它可以根据需要开辟内存单元。链表有一个“头指针”变量,以head表示,它存放一个地址。该地址指向一个元素。链表中每一个元素称为“结点”,每个结点都应包括两个部分:一为用户需要用的实际数据,二为下一个结点的地址。因此,head指向第一个元素:第一个元素又指向第二个元素;……,直到最后一个元素,该元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。
链表的各类操作包括:学习单向链表的创建、删除、 插入(无序、有序)、输出、 排序(选择、插入、冒泡)、反序等等。
二、链表创建、删除、插入等如下,将函数与声明定义进行分离为.h和.c:
2.1 linklist.h
1 #pragma once 2 typedef struct list 3 { 4 int data;//数据域 5 struct list *next;//指针域 6 }LinkList; 7 LinkList *crate_list(); //建立一个节点 8 void traverse(LinkList*ls);//循环遍历链表 9 LinkList* insert_list(LinkList* ls, int n, int data);//在指定位置插入元素 10 int delete_list(LinkList* ls, int n);//删除指定位置元素 11 int count_list(LinkList* ls);//返回链表元素的个数 12 void clear_list(LinkList *ls);//清空链表,只保留首节点 13 int empty_list(LinkList *ls);//返回链表是否为空 14 LinkList *local_list(LinkList*ls, int n);//返回链表指定的位置节点 15 LinkList * elem_list(LinkList* ls, int data);//返回指定位置data 16 int elem_pos(LinkList *ls, int data);//返回数据域等于DATA的位置 17 LinkList *last_list(LinkList *ls);//得到链表的最后一个节点 18 void merge_list(LinkList * s1,LinkList* s2);//合并两个链表 19 void reverse_lsit(LinkList *ls);//链表反转
2.2 linklist.c
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include "linlist.h" 4 //建立一个节点 5 LinkList * crate_list() 6 { 7 return (LinkList*)calloc(sizeof(LinkList),1); 8 } 9 //循环遍历链表 10 void traverse(LinkList * ls) 11 { 12 LinkList *p = ls; 13 while (p) 14 { 15 printf("%d\n",p->data); 16 p = p->next; 17 } 18 19 } 20 //插入元素 21 LinkList * insert_list(LinkList * ls, int n, int data) 22 { 23 LinkList *p = ls; 24 while (p&&n--) 25 { 26 p = p->next; 27 } 28 if (p==NULL) 29 { 30 return NULL;//n的位置大于链表节点数 31 } 32 LinkList *node = crate_list();//新建一个节点 33 node->data = data; 34 node->next = p->next; 35 p->next = node; 36 return node; 37 } 38 //删除节点 39 int delete_list(LinkList * ls, int n) 40 { 41 LinkList *p = ls; 42 while (p&&n--) 43 { 44 p = p->next; 45 } 46 if (p==NULL) 47 { 48 return -1; 49 } 50 LinkList *tmp = p->next; 51 p->next = p->next->next; 52 free(tmp); 53 return 0; 54 } 55 //返回链表元素的个数 56 int count_list(LinkList * ls) 57 { 58 LinkList *p = ls; 59 int count = 0; 60 while (p) 61 { 62 count++; 63 p = p->next; 64 } 65 return count; 66 } 67 //清空链表,只保留首节点 68 void clear_list(LinkList * ls) 69 { 70 LinkList* p = ls->next; 71 while (p) 72 { 73 LinkList * tmp = p->next; 74 free(p); 75 p = tmp; 76 } 77 ls->next = NULL;//只有首节点,则首节点next实则为NULL 78 } 79 //返回聊表是否为空 80 int empty_list(LinkList * ls) 81 { 82 if (ls->next) 83 return 0; 84 else 85 return -1; 86 return 0; 87 } 88 //返回链表指定位置的节点数据域 89 LinkList * local_list(LinkList * ls, int n) 90 { 91 LinkList* p = ls; 92 while (p&&n--) 93 { 94 p=p->next; 95 } 96 if (p == NULL) 97 return NULL; 98 return p; 99 } 100 //返回指定位置数据域对应的节点 101 LinkList * elem_list(LinkList * ls, int data) 102 { 103 LinkList*p = ls; 104 while (p) 105 { 106 if (p->data = data) 107 return p; 108 p = p->next; 109 } 110 return NULL;//没有找到 111 } 112 //返回数据域等于data的节点位置 113 int elem_pos(LinkList * ls, int data) 114 { 115 LinkList * p = ls; 116 int index = 0; 117 while (p) 118 { 119 index++; 120 if (p->data = data) 121 return index; 122 p = p->next; 123 } 124 return -1;//没有找到索引 125 } 126 127 LinkList * last_list(LinkList * ls) 128 { 129 LinkList * p = ls; 130 while (p->next) 131 { 132 p = p->next; 133 } 134 return p; 135 } 136 //合并两个链表,将结构放在第一个链表中 137 void merge_list(LinkList * s1, LinkList * s2) 138 { 139 //合并连标点节点,不合并链表头 140 last_list(s1)->next = s2->next; 141 free(s2); 142 } 143 144 void reverse_lsit(LinkList * ls) 145 { 146 if (ls->next == NULL) 147 return;//只有只有一个头节点 148 if (ls->next->next == NULL) 149 return; 150 LinkList * last = ls->next;//ls->next为最后一个节点 151 LinkList * pre = ls;//上一个节点的指针 152 LinkList *cur = ls->next;//当前节点 153 LinkList*next = NULL;//下一个节指针 154 while (cur) 155 { 156 next = cur->next; 157 cur->next = pre; 158 pre = cur; 159 cur = next; 160 } 161 ls->next = pre; 162 last->next = NULL; 163 }
2.3 测试主函数
1 #include<stdlib.h> 2 #include<stdio.h> 3 #include"linlist.h" 4 #define Len 10 5 int main() 6 { 7 LinkList *first = crate_list();//创建第一个节点 8 LinkList *second = crate_list();//创建第二个节点 9 LinkList *third = crate_list();//创建第三个节点 10 first->next = second;//指针域第一个节点的指针指向下一节点 11 second->next = third;//指针域第二个节点的指针指向下一节点 12 third->next = NULL;//指针域第三个节点的指针指向下一节点,只有三个元素,所以下一节点为NULL 13 first->data = 1;//数据域第一个元素 14 second->data = 2;//数据域第二个元素 15 third->data = 3;//数据域第二个元素 16 //遍历链表 17 printf("插入前:\n"); 18 traverse(first);//遍历头即可打印整个链表,因为链表是靠指针连接在一起 19 insert_list(first,0,100); 20 printf("插入后:\n"); 21 traverse(first); 22 printf("删除后\n"); 23 delete_list(first,2); 24 traverse(first); 25 printf("--------------------------------------\n"); 26 printf("链表的个数cout=%d\n", count_list(first)); 27 //printf("清空链表,直保留首节点\n"); 28 //clear_list(first); 29 printf("链表的个数cout=%d\n", count_list(first)); 30 printf("%d\n",local_list(first,2)->data); 31 printf("data=%d\n",last_list(first)->data); 32 printf("-----------------------------------------\n"); 33 34 LinkList * pp = crate_list(); 35 for (int i = 0; i < Len; i++) 36 { 37 insert_list(pp,0,i); 38 } 39 merge_list(first,pp); 40 traverse(first); 41 printf("xxxxxxxxxxxxxxxxxxxx"); 42 reverse_lsit(first); 43 traverse(first); 44 return 0; 45 }
2.4 结果显示: