学习目标:
1.链表和数组的区别,链表的动态遍历
2.链表数据计数和查询链表数据
3.链表指定节点插入新节点(链表是顺序数据)
(对数据的操作,增删改查)
4.链表头插法(及其优化)
5.尾插法
学习内容:
①.数组书记地址紧连,没有链表便利。链表可以自己从链表头开始地址串起来。
通过自定义struct lian*next 结构体型指针的方式,来进行数据的串联输出
struct lian{ //结构体声明
int date;
struct lian*next;//用来串
}
void Linprin(struct lian*point){
while(point!=NULL){
printf("%d",point.date);
point = point->next;//重点
}
putchar('\n');
}
int main(){
struct lian T1 = {1,NULL};
struct lian T2 = {2,NULL};
struct lian T3 = {3,NULL};
T1.next=&T2;//T2的地址 送到 T1指针的地址
T2.next=&T3;
printf("This is 链表动态输出\n");
linprin(&T1);//将T1地址传过去
return 0;
}
②链表计数与查询都是利用,自定义指针的地址实现
1..链表计数与查找
int conum(struct lian *p){//利用串好的指针,是否等于NULL来计数
int cnt =0;
while(p !=NuLL){
cnt ++;
p = p->next; //struct lian*自定义全局变量,next可直接用
}
return cnt;
}
int search(struct lian * q,int a){
whlie(q != NULL){
if(a = 1){
return 1;
}else{
q = q->next;
}
}
return 0;
}
int main(){
int set = searchdate(&T1,1);
if(set == 1){
printf("find you~1");
}else{
printf("where are you1?\n");
}
putchar('\n');
}
③链表指定节点插入新节点(链表是顺序数据)
看懂这核心代码:
new->next = p->next;//此时利用链表查找,找到p的地址及指向
p->next= new;
一、从指定节点后插入
new->next = p->next;//此时利用链表查找,找到p的地址及指向
p->next= new;
二、指定节点前插入
分为两种情况:1、首节点位置,新节点址项首地址就行
2、目标节点的前一个date
新建struct text* insertforword(struct text* head,1,struct text* new){}
实际上是 改 头,返回的值取代main 函数里的 原先的head
struct test* insertforword(struct test* head,1,struct test* new){
struct test*p = head;
if(p->date == 1){
new->next=p;
return new;// 返回的地址,在主函数里是头,head= insertforword(head,1,&new);
}while(p->next!=NULL){
if(p->next->date==date){
new->next=p->next;
p->next=new;
printf("insert sucess \n");//插入成功,不往下走※
return head;
}
p=p->next;
}
printf("on find where can insert\n");
return head;//能走到这一步,头没变
}
三、链表指定节点的删除
1、改头指针(删除头指针或之前)
2、next->next
struct text* deletNode(struct text* head,int date){
struct text* p = head;//首先判断删除的 是否为 首位置
if(p->date == date){
p = p->next;
free(p);
return head;
}
while(p->next != NULL){ //利用从前插入的思想,确定指针下个位置
if(p->next->date = date){
p->next = p->next->next;
return head;
}
}
p = p->next;
}
四、头插法
1、单独节点,头插法(目的就是 将串好的head返回给main,输出)
struct text *insertfronhead(struct text *head){
struct text *new;
whlie(1){
new =(struct text *) malloc(sizeof(struct text));
printf("please put your will insert date\n");
scanf("%d",&(new->date));
if(new->date == 0){
return head;
}
if(new == NULL){
head = new;
}else{
new->next = head;
head = new;
}
}
return head;
}
void printfronhead(struct text *head){
whlie(1){
if(head!=NULL){
printf("%d",head->date);
head = head->next;
}
}
}
int main(){
struct text *head=NULL;
insertfronhead(head);
printfronhead(head);
}
2.头插法优化
与1 比较,将 循环创建输入 和 头插 分开创建,好处便于 新数值随时头插
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct text insertfromhead(struct text*head,struct text*new){
\\注意此函数包含干creaklink循环中,因此不写while循环
if(head == NULL){
head = new;
}else{
new->date = head;
head = new;
}
}
return head;
}
struct text creatlink(struct text *head){
struct text *new;
while(1){
new = (struct text*)malloc(sizeof(struct text));//不断创建新空间
printf("please write your date");
scanf("%d",&(new->date));//不断提示用户输入
if(new->date == 0){
free(new);
return head;
}
head = insertfromhead(head,new);\\head的返回在下个函数里※
}
}
void printflink(struct text *head){
while(1){
if(new != NULL){
printf("%d",new->date);
new = new->next;
}
}
}
int main(){
struct text *head = NULL;
creatlink(head);
head = insertfromhead(head);
printflink(head); //将船建与 头插连接 分开写好处是可以随时插入新数
struct text t1 = (666,NULL);
head = insertfromhead(head,&t1);即可随时插入新值※
return 0;
}
五、尾插法
核心 判断head里的date 是否为空,下个next为空 则令此节点head->next = new;核心
struct text insertbihand(struct text *head,struct text *new){
if(head->next == NULL){
head = new;
return head;
}
while(head->next!=NULL){
head = head->next;
}else{
head->next = new;
}
return head;
}