链表
有一串已经从小到大排好序的数 2 3 5 8 9 10 18 26 32。现需要往这串数中插入 6 使其得到的新序列仍符合从小到大排列。
先回顾下指针:(主要是我不太了解…)
int *p;
指针有什么作用呢?
答案是:存储一个地址。确切地说是存储一个内存空间的地址。严格地说这里的指针 p 也只能存储“一个存放整数的内存空间”的地址,因为在定义的时候我们已经限制了这一点(即定义的时候*p 的前面是 int)。
当然你也可以定义一个只能用来存储“一个存放浮点数的内存空间”的地址,如:
double *p;
整型指针 p 如何才能存储整型变量 a 的地址呢?
p=&a;//&取地址符
有什么用呢?用处就是我们可以用指针 p 来操作变量 a 了。比如我们可以通过操作指针 p 来输出变量 a 的值:
#include <stdio.h>
int main()
{
int a=10;
int *p; //定义个指针p
p=&a; //指针p获取变量a的地址
printf("%d",*p); //输出指针p所指向的内存中的值
return 0;
}
MALLOC函数:
malloc 函数的返回类型是 void * 类型。 void * 表示未确定类型的指针。在 C和 C++中, void * 类型可以强制转换为任何其他类型的指针。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *p; //定义一个指针p
p=(int *)malloc(sizeof(int)); //指针p获取动态分配的内存空间地址
*p=10; //向指针p所指向的内存空间中存入10
printf("%d",*p); //输出指针p所指向的内存中的值
return 0;
}
链表每一个结点都由两个部分组成。
左边的部分用来存放具体的数值,那么用一个整型变量就可以;
右边的部分需要存储下一个结点的地址,可以用指针来实现
#include <stdio.h>
#include <stdlib.h>
//创建一个结构体来表示链表的结点类型
typedef struct node
{
int data;
struct node *next;
};
int main(int argc, char const *argv[])
{
struct node *head,*p,*q,*t;
int n,a;
printf("Input the num of data:
");
scanf("%d",&n);
head=NULL;//头指针指向空
printf("Input the data:
");
for (int i = 0; i < n; i++)
{
scanf("%d",&a);
//动态申请一个内存,用来存放一个结点,并用临时指针指向这个结点
p=(struct node *)malloc(sizeof(struct node));
/*->叫做结构体指针运算符,也是用来访问结构体内部成员的。
因为此处 p 是一个指针,所以不能使用.号访问内部成员,而要使用->*/
p->data=a;//将数据存储到当前结点的数据域中
p->next=NULL;//设置当前结点的后继指针为空,也就是当前结点的下一个结点为空
if (head==NULL)//
{
head=p;//如果这是第一个创建的结点,则将头指针指向这个结点
}
else
{
q->next=p;//如果不是第一个创建的结点,则将上一个结点的后继指针指向当前结点
}
q=p;//指针q也指向当前结点
}
/*插入新的结点*/
printf("Input the num of insert:
");
scanf("%d",&a);
t=head;//
while (t!=NULL)//遍历链表
{
if(t->next->data > a)//如果下一个结点的数据大于插入的数
{
p=(struct node *)malloc(sizeof(struct node));//动态申请
p->data=a;//存入数据
p->next=t->next;//新增指针的后继指针指向当前结点的后继指针所指向的结点。。。晕
t->next=p;//当前结点的后继指针指向新增结点
break;//插入完毕,退出
}
t=t->next;
}
//输出链表中的所有数
t=head;
while (t!=NULL)
{
printf(" %d",t->data);
t=t->next;
}
free(p);
return 0;
}
**
模拟链表:
**
如果你觉得上一节的代码简直是天书,或者你压根就很讨厌指针这些东西,没关系!链表还有另外一种使用数组来实现的方式,叫做模拟链表,我们一起来看看
链表中的每一个结点只有两个部分。我们可以用一个数组 data 来存储每序列中的每一个数。那每一个数右边的数是谁,这一点该怎么解决呢?上一节中是使用指针来解决的,这里我们只需再用一个数组 right 来存放序列中每一个数右边的数是谁就可以了,具体怎么做呢?
上图的两个数组中,第一个整型数组 data 是用来存放序列中具体数字的,另外一个整型数组 right 是用来存放当前序列中每一个元素右边的元素在数组 data 中位置的。例如 right[1]的值为 2,就表示当前序列中 1 号元素右边的元素存放在 data[2]中;如果是 0,例如right[9]的值为 0,就表示当前序列中 9 号元素的右边没有元素。
看完就晕了,说说我自己的理解:
简单来说就是把上面链表的地址用数组下标来表示,用另一个数组来存放数据数组中的数对应的下标,也即链表中的后继指针,有理解错的地方,希望有心人能给我指正下。
#include <stdio.h>
int main(int argc, char const *argv[])
{
int data[101],right[101];
int n,t,len;
printf("Input the num of data:
");
scanf("%d",&n);
printf("Input the data:
");
for (int i = 1; i <= n; i++)
{
scanf("%d",&data[i]);
}
len=n;
//初始化right数组
for (int i = 1; i <= n; i++)
{
if(i!=n)
right[i]=i+1;
else
right[i]=0;
}
//在data末尾加上一个数据
len++;
printf("Input the num of insert:
");
scanf("%d",&data[len]);
//从链表的头部开始遍历
t=1;
while (t!=0)
{
if (data[right[t]]>data[len])//如果当前结点的下一个结点的数大于待插入的数据,将数插入到中间
{
right[len]=right[t];//新插入数的下一个结点标号等于当前结点的下一个编号
right[t]=len;//当前结点的下一个节点编号就是新插入书的结点编号
break;
}
t=right[t];
}
//打印
t=1;
while (t!=0)
{
printf(" %d",data[t]);
t=right[t];
}
return 0;
}