線形リストの途中に新たな要素を指定要素の前に追加します。
// 線形リストの作成
#include <stdio.h>
#include <stdlib.h>
struct list {
int key;
struct list *next;
};
struct list *get_list(void);
void print_list(struct list *p);
int get_data(void);
void insert_before(struct list *x, struct list *p);
#define EOD -1
/* 初期データリスト */
int a[ ] = { 1, 2, 3, 4, 5, 6, EOD };
int main( )
{
struct list *listptr, *new;
listptr = get_list( );
print_list( listptr );
new = (struct list *)malloc(sizeof(struct list));
new->key = 888;
new->next = NULL;
insert_before( new, listptr->next->next );
print_list( listptr );
return 0;
}
/* 入力データが空になるまでリストを作成 */
struct list *get_list( void ) {
int d;
struct list *p,*newp;
p = NULL; // リストの先頭項目を終端するNULLを入れる
while( ( d = get_data( ) ) != EOD) {
// 一項目分の記憶領域を確保し,その領域へのポインタを返す
// (struct list *)はmallocの返すデータの型をlist構造体型の情報にキャスト(変換)
newp = (struct list *)malloc(sizeof(struct list));
newp->key = d; // mallocで取得した一項目分の記憶領域にデータを書き込む
newp->next = p; // pに保管していた一つ前の項目のアドレス(最初はNULL)をnextアドレスとして書込む
p = newp; // 現記憶領域へのポインタをpに保管
print_list( p );
}
return p; // この時点で、pはリストの最終項目へのポインア(のアドレス)
}
/* データ取得 */
int get_data(void) {
static int i=0;
return a[i++];
}
/* リストの印刷 */
void print_list(struct list *p) {
while (p != NULL) {
printf("<%d> [%0x %0x] ", p->key, p, p->next);
p = p->next;
}
printf("\n");
}
/* リストへの挿入: 指定要素の直前 */
/* pで示される構造体の前にxで示される構造体を挿入 */
void insert_before(struct list *x, struct list *p) {
struct list tmp;
printf("<Insert [%0x] before [%0x]>\n", x, p);
printf("<p key=%d next=%0x>\n", p->key, p->next);
printf("<x key=%d next=%0x>\n", x->key, x->next);
tmp = *x;
printf("<tmp [%0x] key=%d next=%0x>\n", tmp, tmp.key, tmp.next);
*x = *p;
printf("<x [%0x] key=%d next=%0x>\n", x, x->key, x->next);
*p = tmp;
printf("<p [%0x] key=%d next=%0x>\n", p, p->key, p->next);
p->next = x;
printf("<p [%0x] key=%d next=%0x>\n", p, p->key, p->next);
}
実行結果は
C:\TDM-GCC-64\work>linklistInsertBackword <1> [9b1390 0] <2> [9b74f0 9b1390] <1> [9b1390 0] <3> [9b7510 9b74f0] <2> [9b74f0 9b1390] <1> [9b1390 0] <4> [9b7530 9b7510] <3> [9b7510 9b74f0] <2> [9b74f0 9b1390] <1> [9b1390 0] <5> [9b7550 9b7530] <4> [9b7530 9b7510] <3> [9b7510 9b74f0] <2> [9b74f0 9b1390] <1> [9b1390 0] <6> [9b7570 9b7550] <5> [9b7550 9b7530] <4> [9b7530 9b7510] <3> [9b7510 9b74f0] <2> [9b74f0 9b1390] <1> [9b1390 0] <6> [9b7570 9b7550] <5> [9b7550 9b7530] <4> [9b7530 9b7510] <3> [9b7510 9b74f0] <2> [9b74f0 9b1390] <1> [9b1390 0] <Insert [9b7590] before [9b7530]> <p key=4 next=9b7510> <x key=888 next=0> <tmp [62fdf0] key=888 next=0> <x [9b7590] key=4 next=9b7510> <p [9b7530] key=888 next=0> <p [9b7530] key=888 next=9b7590> <6> [9b7570 9b7550] <5> [9b7550 9b7530] <888> [9b7530 9b7590] <4> [9b7590 9b7510] <3> [9b7510 9b74f0] <2> [9b74f0 9b1390] <1> [9b1390 0]
挿入処理の本体は
void insert_before(struct list *x, struct list *p) {
struct list tmp;
tmp = *x; //step1
printf("<tmp [%0x] key=%d next=%0x>\n", tmp, tmp.key, tmp.next);
*x = *p; //step2
printf("<x [%0x] key=%d next=%0x>\n", x, x->key, x->next);
*p = tmp; //step3
printf("<p [%0x] key=%d next=%0x>\n", p, p->key, p->next);
p->next = x; //step4
printf("<p [%0x] key=%d next=%0x>\n", p, p->key, p->next);
}
実行イメージは
