单链表不带头标准c语言实现
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。
下面给出不带头的单链表标准实现:
#include <stdio.h>#include <stdlib.h>typedef struct node{int data;struct node *next;} Node;void pushBackList(Node *list, int data) //尾插{Node *head = list;Node *newNode = (Node *)malloc(sizeof(Node)); //申请空间newNode->data = data;newNode->next = NULL;if (list == NULL) //为空list = newNode;else //非空{while (head->next != NULL)head = head->next;head->next = newNode;}}/* 初始条件:链式线性表L已存在。操作结果:返回L中数据元素个数 */int sizeList(Node *list){int i = 0;Node *p = list->next; /* p指向第一个结点 */while (p){i++;p = p->next;}return i;}int insertList(Node *list, int index, int data) //插入{int n;int size = sizeList(list); //获取链表长度Node *head = list;Node *newNode, *temp;if (index < 0 || index > size)return 0; //非法,要插入的位置小于0,大于链表长度newNode = (Node *)malloc(sizeof(Node)); //创建新节点newNode->data = data;newNode->next = NULL;if (index == 0) //头插{newNode->next = head;list = newNode;return 1;}for (n = 1; n < index; n++) //非头插head = head->next;if (index != size)newNode->next = head->next;//链表尾部next不需指定head->next = newNode;return 1;}void deleteList(Node *list, int data) //按值删除{Node *head = list;Node *temp;while (head->next != NULL){if (head->next->data != data){head = head->next;continue;}temp = head->next;if (head->next->next == NULL) //尾节点删除head->next = NULL;elsehead->next = temp->next;free(temp);}head = list;if (head->data == data) //头结点删除{temp = head;list = head->next;head = head->next;free(temp);}}int printList(Node *list) //打印{if (list->next == NULL){printf("打印 \n");return 0;}Node *temp = list->next;for (; temp != NULL; temp = temp->next)printf("%d ", temp->data);printf("\n");return 1;}int freeList(Node *list) //清空{/*暂时未知*/// Node *head = list;// Node *temp = NULL;// printf("666");// while (head != NULL) //依次释放// {// temp = head;// head = head->next;// free(temp);// }list->next = NULL; //置空printf("清空\n");return 0;}int main(void) //测试{Node *head;for (int i = 0; i < 10; i++){pushBackList(head, i);}insertList(head, 10, 10);insertList(head, 5, 10);printList(head);deleteList(head,10);printList(head);int a = freeList(head);printf("%d \n", a);printList(head);}
运行结果
0 1 2 3 10 4 5 6 7 8 100 1 2 3 4 5 6 7 8清空0打印
别的也没啥了,都是基本操作 有些代码要分情况,很麻烦,可读性较强吧
单链表不带头压缩c语言实现
注:单追求代码简洁,所以写法可能有点不标准。
//第一次拿c开始写数据结构,因为自己写的,追求代码量少,和学院ppt不太一样。有错请指出#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct node//定义节点{int data;struct node * next;}Node;//函数介绍void printlist(Node * head);//打印链表int lenlist(Node * head);//返回链表长度void insertlist(Node ** list,int data,int index);//插入元素void pushback(Node ** head,int data);//尾部插入void freelist(Node ** head);//清空链表void deletelist(Node ** list,int data);//删除元素Node * findnode(Node ** list,int data);//查找void change(Node ** list,int data,int temp);//改变值void printlist(Node * head)//打印链表{for(;head!=NULL;head=head->next) printf("%d ",head->data);printf("\n");//为了其他函数打印,最后换行}int lenlist(Node * head)//返回链表长度{int len;Node * temp = head;for(len=0; temp!=NULL; len++) temp=temp->next;return len;}void insertlist(Node ** list,int data,int index)//插入元素,用*list将head指针和next统一表示{if(index<0 || index>lenlist(*list))return;//判断非法输入Node * newnode=(Node *)malloc(sizeof(Node));//创建newnode->data=data;newnode->next=NULL;while(index--)list=&((*list)->next);//插入newnode->next=*list;*list=newnode;}void pushback(Node ** head,int data)//尾插,同上{Node * newnode=(Node *)malloc(sizeof(Node));//创建newnode->data=data;newnode->next=NULL;while(*head!=NULL)head=&((*head)->next);//插入*head=newnode;}void freelist(Node ** head)//清空链表{Node * temp=*head;Node * ttemp;*head=NULL;//指针设为空while(temp!=NULL)//释放{ttemp=temp;temp=temp->next;free(ttemp);}}void deletelist(Node ** list,int data)//删除链表节点{Node * temp;//作用只是方便freewhile((*list)->data!=data && (*list)->next!=NULL)list=&((*list)->next);if((*list)->data==data){temp=*list;*list=(*list)->next;free(temp);}}Node * findnode(Node ** list,int data)//查找,返回指向节点的指针,若无返回空{while((*list)->data!=data && (*list)!=NULL) list=&((*list)->next);return *list;}void change(Node ** list,int data,int temp)//改变{while((*list)->data!=data && (*list)->next!=NULL)list=&((*list)->next);if((*list)->data==data)(*list)->data=temp;}int main(void)//测试{Node * head=NULL;Node ** gg=&head;int i;for(i=0;i<10;i++)pushback(gg,i);printf("链表元素依次为: ");printlist(head);printf("长度为%d\n",lenlist(head));freelist(gg);printf("释放后长度为%d\n",lenlist(head));for(i=0;i<10;i++)pushback(gg,i);deletelist(gg,0);//头deletelist(gg,9);//尾deletelist(gg,5);deletelist(gg,100);//不存在printf("再次创建链表,删除节点后\n");printlist(head);freelist(gg);for(i=0;i<5;i++)pushback(gg,i);insertlist(gg,5,0);//头insertlist(gg,5,5);insertlist(gg,5,7);//尾insertlist(gg,5,10);//不存在printlist(head);printf("找到%d\n把3变为100",*findnode(gg,5));change(gg,3,100);change(gg,11111,1);//不存在printlist(head);}
运行结果
链表元素依次为: 0 1 2 3 4 5 6 7 8 9长度为10释放后长度为0再次创建链表,删除节点后1 2 3 4 6 7 85 0 1 2 3 5 4 5找到6422000把3变为1005 0 1 2 100 5 4 5
