一、链表
1.简介
链表是物理存储单元上非连续的、非顺序的存储结构,数据元素的逻辑顺序是通过链表的指针地址实现,有一系列结点(地址)组成,结点可动态的生成。
2.与数组的区别
(1)数组
使用一块连续的内存空间地址去存放数据。
(2)链表
使用多个不连续的内存空间去存储数据, 可以 节省内存资源(只有需要存储数据时,才去划分新的空间),对数据的增删比较方便。
代码:
#include <stdio.h>
struct Test
{
int data;
struct Test *next;
};
int main()
{
int arr[3]={1,2,3};
int i;
for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
printf("%d ",arr[i]);
}
printf("\n");
struct Test t1 = {1,NULL};
struct Test t2 = {2,NULL};
struct Test t3 = {3,NULL};
t1.next = &t2;
t2.next = &t3;
printf("use t1 to print three num \n");
printf("%d %d %d\n",t1.data,t1.next -> data,t1.next->next -> data);
return 0;
}
运行结果:
3.链表的静态添加和动态遍历
如果需要加一项内容,数组需要重新进行合适的数组,而链表可以直接进行链接即可
代码:
#include <stdio.h>
struct Test
{
int data;
struct Test *next;
};
void printlink(struct Test *head)
{
while(head != NULL)
{
printf("%d ",head->data);
head = head->next;
}
putchar('\n');
}
int main()
{
int arr[3]={1,2,3};
int i;
for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
printf("%d ",arr[i]);
}
printf("\n");
struct Test t1 = {1,NULL};
struct Test t2 = {2,NULL};
struct Test t3 = {3,NULL};
struct Test t4 = {4,NULL};
struct Test t5 = {5,NULL};
struct Test t6 = {6,NULL};
t1.next = &t2;
t2.next = &t3;
t3.next = &t4;
t4.next = &t5;
t5.next = &t6;
printf("use t1 to print three num \n");
printlink(&t1);
//printf("%d %d %d\n",t1.data,t1.next -> data,t1.next->next -> data);
return 0;
}
运行结果:
4.链表的节点个数与查找
代码:
#include <stdio.h>
struct Test
{
int data;
struct Test *next;
};
void printlink(struct Test *head)
{
while(head != NULL)
{
printf("%d ",head->data);
head = head->next;
}
putchar('\n');
}
int getlinkcount(struct Test *head)
{
int cnt = 0;
while(head != NULL)
{
cnt++;
head = head->next;
}
return cnt;
}
int searchlink(struct Test *head,int data)
{
while(head != NULL)
{
if(head->data = data)
{
return 1;
}
head = head->next;
}
return 0;
}
int main()
{
int arr[3]={1,2,3};
int i;
for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
printf("%d ",arr[i]);
}
printf("\n");
struct Test t1 = {1,NULL};
struct Test t2 = {2,NULL};
struct Test t3 = {3,NULL};
struct Test t4 = {4,NULL};
struct Test t5 = {5,NULL};
struct Test t6 = {6,NULL};
t1.next = &t2;
t2.next = &t3;
t3.next = &t4;
t4.next = &t5;
t5.next = &t6;
printf("use t1 to print three num \n");
printlink(&t1);
int ret = getlinkcount(&t1);
printf("total number is:%d\n",ret);
ret = searchlink(&t1,1);
if(ret == 1)
{
printf("have 1\n");
}else{
printf("no 1\n");
}
//printf("%d %d %d\n",t1.data,t1.next -> data,t1.next->next -> data);
return 0;
}
运行结果:
5.链表从指定节点后方插入
通过将插入值(new)插入到前一个(3)的后端,让前一个(3)的下一个节点(4)赋给插入值(new),再将插入值(new)的节点赋给前一个(3)
代码:
#include <stdio.h>
struct Test
{
int data;
struct Test *next;
};
void printlink(struct Test *head)
{
struct Test *p = head;
while(p != NULL)
{
printf("%d ",p->data);
p = p->next;
}
putchar('\n');
}
int getlinkcount(struct Test *head)
{
struct Test *p = head;
int cnt = 0;
while(p != NULL)
{
cnt++;
p = p->next;
}
return cnt;
}
int searchlink(struct Test *head,int data)
{
struct Test *p = head;
while(p != NULL)
{
if(p->data = data)
{
return 1;
}
p = p->next;
}
return 0;
}
int insertlink(struct Test *head,int data,struct Test *new)
{
struct Test *p = head;
while(p != NULL)
{
if(p->data == data ){
new->next = p->next;
p->next = new;
return 1;
}
p = p->next;
}
return 0;
}
int main()
{
int arr[3]={1,2,3};
int i;
for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
printf("%d ",arr[i]);
}
printf("\n");
struct Test t1 = {1,NULL};
struct Test t2 = {2,NULL};
struct Test t3 = {3,NULL};
struct Test t4 = {4,NULL};
struct Test t5 = {5,NULL};
struct Test t6 = {6,NULL};
t1.next = &t2;
t2.next = &t3;
t3.next = &t4;
t4.next = &t5;
t5.next = &t6;
printf("use t1 to print three num \n");
printlink(&t1);
int ret = getlinkcount(&t1);
printf("total number is:%d\n",ret);
ret = searchlink(&t1,1);
if(ret == 1)
{
printf("have 1\n");
}else{
printf("no 1\n");
}
struct Test new={100,NULL};
insertlink(&t1,6,&new);
puts("after insert is:");
printlink(&t1);
//printf("%d %d %d\n",t1.data,t1.next -> data,t1.next->next -> data);
return 0;
}
运行结果:
6.链表删除节点
删除链表节点两种类型:
(1)删除头
换头,直接指向下一个节点,以下一个节点作为头
(2)删除其他
直接越过需要删除的这个链表节点,例如1,2,3;直接1,3
代码:
#include <stdio.h>
struct Test
{
int data;
struct Test *next;
};
void printlink(struct Test *head)
{
struct Test *p = head;
while(p != NULL)
{
printf("%d ",p->data);
p = p->next;
}
putchar('\n');
}
int getlinkcount(struct Test *head)
{
struct Test *p = head;
int cnt = 0;
while(p != NULL)
{
cnt++;
p = p->next;
}
return cnt;
}
int searchlink(struct Test *head,int data)
{
struct Test *p = head;
while(p != NULL)
{
if(p->data = data)
{
return 1;
}
p = p->next;
}
return 0;
}
int insertlink(struct Test *head,int data,struct Test *new)
{
struct Test *p = head;
while(p != NULL)
{
if(p->data == data ){
new->next = p->next;
p->next = new;
return 1;
}
p = p->next;
}
return 0;
}
struct Test* deletNode(struct Test *head,int data)
{
struct Test *p = head;
if(p->data == data){
head = head->next;
//free()p;
return head;
}
while(p->next != NULL)
{
if(p->next->data == data)
{
//strct Test *tmp = p;
p->next = p->next->next;
//free(tmp);
return head;
}
p = p->next;
}
return head;
}
int main()
{
struct Test *head = NULL;
struct Test t1 = {1,NULL};
struct Test t2 = {2,NULL};
struct Test t3 = {3,NULL};
struct Test t4 = {4,NULL};
struct Test t5 = {5,NULL};
struct Test t6 = {6,NULL};
t1.next = &t2;
t2.next = &t3;
t3.next = &t4;
t4.next = &t5;
t5.next = &t6;
head = &t1;
printlink(head);
head = deletNode(head,6);
printlink(head);
return 0;
}
运行结果:
7.动态创建
(1)头插法
代码:
#include <stdio.h>
#include <stdlib.h>
struct Test
{
int data;
struct Test *next;
};
void printlink(struct Test *head)
{
struct Test *p = head;
while(p != NULL)
{
printf("%d ",p->data);
p = p->next;
}
putchar('\n');
}
int getlinkcount(struct Test *head)
{
struct Test *p = head;
int cnt = 0;
while(p != NULL)
{
cnt++;
p = p->next;
}
return cnt;
}
int searchlink(struct Test *head,int data)
{
struct Test *p = head;
while(p != NULL)
{
if(p->data = data)
{
return 1;
}
p = p->next;
}
return 0;
}
struct Test* deletNode(struct Test *head,int data)
{
struct Test *p = head;
if(p->data == data){
head = head->next;
//free()p;
return head;
}
while(p->next != NULL)
{
if(p->next->data == data)
{
//strct Test *tmp = p;
p->next = p->next->next;
//free(tmp);
return head;
}
p = p->next;
}
return head;
}
struct Test* insertFromHead(struct Test *head,struct Test *new)
{
if(head == NULL)
{
head = new;
}else{
new->next = head;
head = new;
}
return head;
}
struct Test *creatLink(struct Test *head)
{
struct Test *new;
while(1){
new = (struct Test *)malloc(sizeof(struct Test));
printf("input your new node data:\n");
scanf("%d",&(new->data));
if(new->data == 0)
{
printf("0 quit\n");
free(new);
return head;
}
head = insertFromHead(head,new);
}
}
int main()
{
struct Test *head = NULL;
head = creatLink(head);
printlink(head);
struct Test t1 = {100,NULL};
head = insertFromHead(head,&t1);
printlink(head);
return 0;
}
运行结果:
(2)尾插法
通过尾部链表节点的特性 t5 = NULL就可以从尾部进行插入
代码:
#include <stdio.h>
#include <stdlib.h>
struct Test
{
int data;
struct Test *next;
};
void printlink(struct Test *head)
{
struct Test *p = head;
while(p != NULL)
{
printf("%d ",p->data);
p = p->next;
}
putchar('\n');
}
int getlinkcount(struct Test *head)
{
struct Test *p = head;
int cnt = 0;
while(p != NULL)
{
cnt++;
p = p->next;
}
return cnt;
}
int searchlink(struct Test *head,int data)
{
struct Test *p = head;
while(p != NULL)
{
if(p->data = data)
{
return 1;
}
p = p->next;
}
return 0;
}
int insertlink(struct Test *head,int data,struct Test *new)
{
struct Test *p = head;
while(p != NULL)
{
if(p->data == data ){
new->next = p->next;
p->next = new;
return 1;
}
p = p->next;
}
return 0;
}
struct Test* deletNode(struct Test *head,int data)
{
struct Test *p = head;
if(p->data == data){
head = head->next;
//free()p;
return head;
}
while(p->next != NULL)
{
if(p->next->data == data)
{
//strct Test *tmp = p;
p->next = p->next->next;
//free(tmp);
return head;
}
p = p->next;
}
return head;
}
struct Test* insertFromHead(struct Test *head,struct Test *new)
{
if(head == NULL)
{
head = new;
}else{
new->next = head;
head = new;
}
return head;
}
struct Test *creatLink(struct Test *head)
{
struct Test *new;
while(1){
new = (struct Test *)malloc(sizeof(struct Test));
printf("input your new node data:\n");
scanf("%d",&(new->data));
if(new->data == 0)
{
printf("0 quit\n");
free(new);
return head;
}
head = insertFromHead(head,new);
}
}
struct Test* insertFromBehind(struct Test *head,struct Test *new)
{
struct Test *p = head;
if(p == NULL)
{
head = new;
return head;
}
while(p->next != NULL){
p = p->next;
}
p->next = new;
return head;
}
struct Test *creatLink2(struct Test *head)
{
struct Test *new;
while(1){
new = (struct Test *)malloc(sizeof(struct Test));
printf("input your new node data:\n");
scanf("%d",&(new->data));
if(new->data == 0)
{
printf("0 quit\n");
free(new);
return head;
}
head = insertFromBehind(head,new);
}
}
int main()
{
struct Test *head = NULL;
head = creatLink(head);
printlink(head);
struct Test t1 = {100,NULL};
head = insertFromHead(head,&t1);
printlink(head);
struct Test t2 = {200,NULL};
head = insertFromBehind(head,&t2);
printlink(head);
return 0;
}
运行结果:
1为第一种创建链表方式
2为第二种创建链表方式