链表通常来说是用到封装了data与一个指针的类型的结构体
其实不使用指针也可以模拟链表。
这是啊哈,算法上面的描述。
大致意思就是声明两个数组,用right数组来代替指针。
right所储存的数据就是data下一个结点的位置。
贴一段代码:
//数组模拟链表
#include<stdio.h>
int main(){
int data[101],right[101];
int i,n,t,len;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&data[i]);
}
len=n;
//初始化right数组
for(i=1;i<=n;i++){
if(i!=n){
right[i]=i+1;
}
else{
right[i]=0;
}
}
//直接再data数组末尾增加一个数
len++;
scanf("%d",&data[len]);
//从链表头部开始遍历
t=1;
int tmp;
while(t!=0){
if(data[1]>data[len]){
tmp=data[1];
data[1]=data[len];
data[len]=tmp;
right[len]=right[1];
right[1]=len;
break;
}
else{
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];
}
printf("\n");
return 0;
}
这里默认的是原链表是按从小到大的顺序排列的!
这里我之前一直就用一个疑问:
这样不就默许data中第一位就是链表的开头了吗?
(链表的优点之一就是便于插入与删除)
那如果待插入的结点数据比data[1]还要小,需要添加在它的前面呢?
这就有一点麻烦,需要单独拎出来讨论了。
在添加的那段代码里讨论这种单独情况:
int tmp;
if(data[1]>data[len]){
tmp=data[1];
data[1]=data[len];
data[len]=tmp;
right[len]=right[1];
right[1]=len;
break;
}
//我想出来的办法是将待插入结点与第一个结点交换位置然后执行插入。
//等等好像可以写得更简单一点
//算了有很多种写法,殊途同归
//1.data[right[t]]这里是直接读取下一个结点(指针),如果写成data[t]呢??
//2.交换可以跟结点插入那里合并吗?
事实证明,上述代码都是将data[1]直接开指,有点类似没有带头指针的链表。
头插法的实现就有一定难度
我们如果引入头指针的说法在模拟链表这儿会怎么样呢??
那就直接利用起right[0]??
显然不行。t=0是判断链表结尾的标志?如果指向1那不直接成循环链表了??
没有没有,我们判断的时候是考虑t的数组而并不是考虑right[t]有没有值。
所以这个方法有效!
试一下吗?
我试了,就冲这里就不行
只能将链表再向后移动一格了。
突然就想到一句话,
编程心理:
写完代码,
不能运行。咦?为什么不能运行呢?
可以运行。咦?为什么可以运行呢?
笑死,说的就是我