目录
c语言暂时更新完毕
链表实现
![](https://i-blog.csdnimg.cn/blog_migrate/374c0fc7d424ba61ccdac1f70dec844f.png)
#include <stdio.h>
#include "node.h"
#include <stdlib.h>
//node头文件内容:
//typedef struct _node{
// int value;
// struct _node *next;
//}Node;
typedef struct test{
int a;
}Test;
void add(Node*head,int number);
int main(int argc,char const *argv[]) {
int number;
Node * head=NULL;
do {
scanf("%d",&number);
if ((number!=-1)){
//如果输入的不是-1则申请一个结点空间
add(head,number);//将添加过程抽取成一个函数add
}
}while (number!=-1);
return 0;
}
void add(Node *head,int number){
//这里复习一下malloc,它返回的是一个指针,是指向一块内存的指针,指针p能够p->value就不难理解了
Node *p=(Node*)malloc(sizeof(Node));
//给value赋值
p->value=number;
//因为这是新节点,新结点的的下一个结点肯定是NULL
p->next=NULL;
//定义一个尾指针,从头开始遍历找到最后一个结点
Node *last=head;
if (last){//因为在链表最初始化时,last=head=null
while (last->next){//向后搜索找到尾,这里可以用一个一直指向尾的指针tail代替这里不展开了
last=last->next;
}
//找到后,把新建立的结点p给尾指针,也就是放到链表尾
last->next=p;
} else{
head = p;//注意了这里需要修改head,但是这个head是局部变量,与外面的head无关
/*
* 几种解决办法
* 1、将head声明为全局变量,有害不推荐
* 2、函数返回一个Node *head 但是对之后用这个函数的人有要求,必须用head来接收
* 3、我们传入head的指针进去,形参当然也是head指针的指针Node** pHead,函数里面的head全部写为*pHead
* 4、建立一个结构:List,里面有Node *head,所有的head都被List list代替当然初始化也是list.head=NULL,add函数传入&list
* 这里使用方案4进行改进,这样做的好处是我们定义了一个可以扩展的类型
* */
}
}
链表改进及其函数
#include <stdio.h>
#include "node.h"
#include <stdlib.h>
//node头文件内容:
//typedef struct _node{
// int value;
// struct _node *next;
//}Node;
typedef struct list{
Node *head;
//Node *tail 这里尾指针不展开
}List;
void add(List *pList,int number);
void print(List *list);
void search(List *list,int number);
void delete(List *list,int number);
void clearList(List *list);
int main(int argc,char const *argv[]) {
int number;
// Node * head=NULL;
//改进
List list;
list.head=NULL;
do {
scanf("%d",&number);
if ((number!=-1)){
//如果输入的不是-1则申请一个结点空间
add(&list,number);//将添加过程抽取成一个函数add
}
}while (number!=-1);
//链表遍历
print(&list);
//搜索链表
scanf("%d",&number);
search(&list,number);
//删除
scanf("%d",&number);
delete(&list,number);
print(&list);
//链表的清除
clearList(&list);
print(&list);
return 0;
}
void add(List *pList,int number){
//这里复习一下malloc,它返回的是一个指针,是指向一块内存的指针,指针p能够p->value就不难理解了
Node *p=(Node*)malloc(sizeof(Node));
//给value赋值
p->value=number;
//因为这是新节点,新结点的的下一个结点肯定是NULL
p->next=NULL;
//定义一个尾指针,从头开始遍历找到最后一个结点
Node *last=pList->head;
if (last){//因为在链表最初始化时,last=head=null
while (last->next){//向后搜索找到尾,这里可以用一个一直指向尾的指针tail代替这里不展开了
last=last->next;
}
//找到后,把新建立的结点p给尾指针,也就是放到链表尾
last->next=p;
} else{
pList->head = p;//注意了这里需要修改head,但是这个head是局部变量,与外面的head无关
/*
* 几种解决办法
* 1、将head声明为全局变量,有害不推荐
* 2、函数返回一个Node *head 但是对之后用这个函数的人有要求,必须用head来接收
* 3、我们传入head的指针进去,形参当然也是head指针的指针Node** pHead,函数里面的head全部写为*pHead
* 4、建立一个结构:List,里面有Node *head,所有的head都被List list代替当然初始化也是list.head=NULL,add函数传入&list
* 这里使用方案4进行改进
* */
}
}
void print(List *list){
Node *p;
//for也可以写为这样:for (list->head;list->head; list->head=list->head->next),从而去掉Node *p
for (p = list->head;p; p=p->next) {
printf("%d\t",p->value);
}
}
void search(List *list,int number){
Node *p;
int isFound=0;
for (p=list->head;p; p=p->next) {
if (p->value==number) {
printf("找到了!\n");
isFound = 1;
break;
}
}
if (!isFound){
printf("没找到!\n");
}
}
void delete(List *list,int number){
Node *p;
Node *q;//现在光有一个p不行了得有一个q等于p前面一个结点
for (q = NULL,p = list->head;p; q=p,p=p->next) {
if (p->value == number){
if (q){
q->next=p->next;//注意这里q可能出现可以出现null,需要边界检测
//在->左边的指针都得做边界检测
} else{
list->head=p->next;
}
free(p);
break;
}
}
}
void clearList(List *list){
Node *p;
Node *q;//用q来指向当前结点的下一个结点
for (p=list->head;p;p=q) {
q=p->next;
free(p);
}
printf("清楚成功!\n");
}
补充知识volatile关键字
volatile关键字用来修饰变量时,就告诉编译器该变量是随时变化的,让编译器不做寄存器缓冲优化,直接从存储器读取。
原因:当一个变量频繁变化且有寄存器存储被读写,如果有其他程序修改这个变量就会出现不一致现象