链表中每个结点只有两个部分:值域和指针域;
值域存放的是自身的值,指针域放的就是下一个结点的地址,如果指针域用数组表示的话,也就是下一个结点的值的下标。
所以用两个数组来模拟单链表,一个data数组表示值域(存的是结点的值),一个next数组表示指针域(存的是下一个结点在data数组里的下标)。
如图:
next数组的下标是当前结点的下标,next的元素对应着是当前结点的下一个结点的下标。
比如:
next[0]表示data[0]的下一个结点的下标是1,即a的下一个结点b在data数组里的下标是1;
next[1]表示data[1]的下一个结点的下标是2,即b的下一个结点c在data数组里的下标是2;
……
next[i]表示data[i]的下一个结点的下标是next[i],即data[next[i]]=data[i+1];
next[7]表示data[7]的下一个结点的下标是-1,但下标没有-1,所以表示没有下一个结点了。
总之 next[i] 就是下标, data[i] 是结点值。next数组的下标对应着data数组的下标,next数组的元素还是对应着data数组的下标,只不过一个是当前结点一个是下一个结点。所以如果要遍历链表的话,就是遍历data数组,只不过数组下标是通过next数组来改变的。
现在需要在这个链表里面插入一个值,要求这个值插在比他大的值的前面:
首先直接把这个值(num)放在data数组里面,直接放在data数组最后一个值的后面(data[N]),然后遍历链表,找到比num大的结点(data[next[i]]),然后先把当前位置的下一个位置存到num的指针域(next[N]=next[i]),再把当前位置改成num位置(next[i]=N);
如果链表中没有比num大的值,那说明插入位置在链表的末尾,还是先将num存到data的最后一个位置,因为原来的末尾结点指针域(next[i])是-1,现在新插入一个结点,所以要把原来的末尾指针域改成 i+1(next[i]=i+1),然后把新的末尾指针改成-1(next[i+1]=-1)。
代码及详情如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
/*两个数组模拟链表*/
int main(){
int data[100];//值域
int next[100];//指针域
printf("输入元素个数:");
int N; //元素总数,data的最大下标为N-1,data[N-1]是最后一个结点
scanf("%d", &N);
printf("请输入值:");
int i;
for (i = 0; i < N; i++) {
scanf("%d", &data[i]);//赋值
next[i] = i + 1;//next[i]表示值域里面i位置的下一个值在next[i]位置,初始为i+1
}
next[N-1] = -1;//链表的最后一个结点
printf("当前链表:");
i = 0;
while (i != -1) {
printf("%d ", data[i]);
i = next[i];
}
printf("\n输入要插入的值:");
int num;
scanf("%d", &num);
data[N] = num;//num存到data的最后一个值的后面,data本来的最后一个值是data[N-1]
i = 0;
while (i != -1) {
if (data[next[i]] > num) {//碰到比num大的值就插在他的前面
next[N] = next[i];//先把当前位置的下一个位置存到num的指针域(next[N]=next[i]),
next[i] = N; //再把当前位置改成num位置(next[i]=N);
break;
}
else if (next[i] == -1) {//如果num是当前链表最大值就插在最后面
next[i] = i + 1;//把原来的末尾指针域改成 i+1(next[i]=i+1),
next[i + 1] = -1;//然后把新的末尾指针改成-1(next[i+1]=-1)。
break;
}
i = next[i];
}
printf("当前链表:");
i = 0;
while (i != -1) {
printf("%d ", data[i]);
i = next[i];
}
return 0;
}