c言語 片方向連結リスト
c言語の片方向連結リストのプログラムについて質問があります.
下記のプログラムの関数int get_index(ListPtr l, int value)に以下のようなコードを書く.リストl において値value を持つセルの位置を返す.返り値は,最初のセルが値value を持っていれば0,次のセルが値value を持っていれば1,...,値value を持っているセルが存在しなければ–1とする.
また,関数void add(ListPtr l, int index, int value)に以下のようなコードを書く.リストl の位置index に値value を持つセルを挿入.挿入前のリストに対して:index が0 のときは先頭に挿入,index が1 のときは(0から数えて)1番目のセルの前に挿入,index が2 のときは(0から数えて)2番目のセルの前に挿入,...,index がリストのサイズと等しいときはリストの末尾に挿入,それ以外の場合は何もしなくてよい.
これらのコードはどのように書けばよいのでしょうか?
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
/* 連結リスト中のノードの構造体 */
struct node {
int val; /* 値 */
struct node *next; /* 次ノード */
};
/* セルとそのポインタの型 */
typedef struct node Node;
typedef Node *NodePtr;
/* セルを一つ生成 */
NodePtr create_node(int v) {
NodePtr n = NULL;
n = malloc(sizeof(Node));
n->val = v;
n->next = NULL;
return n;
}
/* セルを表示 */
void print_node(NodePtr n) {
if (n != NULL) {
printf("<%d>", n->val);
}
else {
printf("(null)");
}
}
/* 連結リストの構造体 */
struct list {
/* 先頭セルへのポインタ */
NodePtr head;
};
/* 連結リストとそのポインタの型 */
typedef struct list List;
typedef List *ListPtr;
/* 空の連結リストを生成 */
ListPtr create_list(void) {
ListPtr l = NULL;
l = malloc(sizeof(List));
l->head = NULL;
return l;
}
/* 連結リスト l が空かどうか判定 */
int is_empty(ListPtr l) {
return (l->head == NULL);
}
/* リスト l の内容を表示 */
void print_list(ListPtr l) {
NodePtr n = NULL;
if (is_empty(l)) {
printf("(empty)\n");
return;
}
n = l->head;
while (n != NULL) {
print_node(n);
n = n->next;
}
printf("\n");
}
/* リスト l の先頭にセルを挿入 */
void add_first(ListPtr l, int val) {
NodePtr n = NULL;
n = create_node(val);
n->next = l->head;
l->head = n;
}
/* リスト l の先頭セルを削除 */
int delete_first(ListPtr l) {
NodePtr n = NULL;
int v;
/* リストが空なら -1 を返す(負の値はリストに含まれないと仮定)*/
if (is_empty(l)) return -1;
v = l->head->val;
n = l->head;
l->head = l->head->next;
free(n);
n = NULL;
return v;
}
/* 連結リスト l のサイズを取得 */
int get_list_size(ListPtr l) {
NodePtr n = NULL;
int size;
size = 0;
n = l->head;
while (n != NULL) {
size++;
n = n->next;
}
return size;
}
/*
* 連結リスト l における index 番目のセルの値を取得
* (そのようなセルが存在しなければ -1 を返す)
*/
int get_value(ListPtr l, int index) {
NodePtr n = NULL;
if (index < 0) return -1;
n = l->head;
while (index > 0 && n != NULL) {
n = n->next;
index--;
}
return (n == NULL) ? -1 : n->val;
}
/* リスト l 中の全セルを削除(ループ版)*/
void delete_all(ListPtr l) {
NodePtr n = NULL, m = NULL;
n = l->head;
while (n != NULL) {
m = n;
n = n->next;
free(m);
}
l->head = NULL;
}
/* セル n 以降を全て削除(内部処理用の再帰関数)*/
void delete_rest(NodePtr n) {
if (n->next != NULL) delete_rest(n->next);
free(n);
}
/* リスト l 中の全セルを削除(再帰版)*/
void delete_all_recursively(ListPtr l) {
if (l->head == NULL) return;
delete_rest(l->head);
l->head = NULL;
}
/* リスト l 全体を削除 */
#define delete_list(l) (delete_list0(l),l=NULL)
void delete_list0(ListPtr l) {
delete_all(l);
free(l);
}
/* リスト l において値 val を持つセルの位置を返す */
int get_index(ListPtr l, int value) {
return -1;
}
/* リスト l の位置 index に値 val を持つセルを挿入 */
void add(ListPtr l, int index, int value) {
}
/* 連結リストの使用例 */
int main(void) {
FILE *fp = NULL;
char buf[10];
int age;
ListPtr l = NULL;
l = create_list();
add_first(l, 28);
add_first(l, 40);
add_first(l, 33);
add_first(l, 15);
print_list(l);
delete_first(l); print_list(l);
delete_first(l); print_list(l);
delete_first(l); print_list(l);
delete_first(l); print_list(l);
return 0;
}
補足
p1というポインタを使ってたどっていくので、もっと複雑になりませんか? 入れ替えを複数回行いたいので、 a1->next=a5; のように固定して書けません・・・