您的位置:首页 > 其它

DList双向链表

2016-05-25 16:35 423 查看
//
//  DList.h
//  Algorithms&Data_structures
//
//  Created by TTc on 15-2-2.
//  Copyright (c) 2015年 TTc. All rights reserved.
//

#ifndef __Algorithms_Data_structures__DList__
#define __Algorithms_Data_structures__DList__

#include <stdlib.h>

/* define  a  structure for doubly_linked list */
typedef struct DlistElmt_{
void *data;
struct DlistElmt_ *prev;
struct DlistElmt_ *next;
}DlistElmt;

typedef struct Dlist_{
int size;
int(*match)(void *key1,void *key2);
void(*destroy)(void *data);
DlistElmt *head;
DlistElmt *tail;
}Dlist;

/* public Interfaces*/

void dlist_init(Dlist *dlist,void(*destroy)(void *data));

void dlist_destroy(Dlist *dlist);

int dlist_ins_next(Dlist *dlist,DlistElmt *element,const void *data);

int dlist_ins_prev(Dlist *dlist,DlistElmt *element,const void *data);

int dlist_remove(Dlist *dlist,DlistElmt *element, void **data);

#define dlist_size(dlist)  ((dlist)->size)
#define dlist_head(dlist)  ((dlist) ->head)
#define dlist_tail(dlist)  ((dlist) ->tail)

#define dlist_is_head(dlist)  ((element) ->prev == NULL? 1:0)
#define dlist_is_tail(dlist)  ((element) ->next == NULL? 1:0)

#define dlist_data(dlist)  ((dlist) ->data)
#define dlist_next(dlist)  ((dlist) ->next)
#define dlist_prev(dlist)  ((dlist) ->prev)

#endif /* defined(__Algorithms_Data_structures__DList__) */


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56
//
//  DList.c
//  Algorithms&Data_structures
//
//  Created by TTc on 15-2-2.
//  Copyright (c) 2015年 TTc. All rights reserved.
//

#include "dlist.h"
#include <stdlib.h>
#include <string.h>

void
dlist_init(Dlist *dlist,void(*destroy)(void *data)){
dlist->size = 0;
dlist->head = NULL;
dlist->tail = NULL;
dlist->destroy = destroy;
}

void
dlist_destroy(Dlist *dlist){
void *data;
/*remove each  element*/
while (dlist_size(dlist) > 0) {
if((dlist_remove(dlist, dlist_tail(dlist), (void**) &data) == 0)
&& dlist->destroy != NULL){
dlist->destroy(data);
}
}
//清空dlist 结构体
memset(dlist, 0, sizeof(Dlist));
}

/*1:  将新元素插入到双链表中 由参数element所指向的元素 之后
2: 同单链表最大的区别在于:除了要管理next
指针外,还必须管理prev指针,以保证链表的 反向链接关系 正确
*/
/* 插入成功返回0 ,反之返回 -1 */
/* O(1)*/
int
dlist_ins_next(Dlist *dlist,DlistElmt *element,const void *data){
DlistElmt *new_element;
//do not allow a NULL unless the list is empty
if(element == NULL && dlist_size(dlist) != 0){
return -1;
}
if((new_element = (DlistElmt*)malloc(sizeof(DlistElmt))) == NULL){
return -1;
}
//fill the data to the element
new_element->data = (void*)data;
//如果当前链表为 空表,再插入新元素 的情况
if(dlist_size(dlist) == 0){
new_element->prev = NULL; //链表的头元素 的 前驱指针 指向NULL
new_element->next = NULL; //链表的头元素 的 后驱指针 指向NULL(当前情况 链表中只要这一个元素)
dlist->head = new_element;
dlist->tail = new_element;//链表的尾指针也指向 当前元素
} else {
//如果当前链表为 非空表,再插入新元素 的情况

if(element->next == NULL){
dlist->tail = new_element;
} else{
//否则 将当前目标元素的 后一位置的元素 的 前驱指针 指向 要插入的元素
element->next->prev = new_element;
}

new_element->next = element->next; //要插入的元素的 next指针 指向 当前目标元素 后一位置 元素
new_element->prev = element;//要插入元素的 前驱函数 指向 当前目标元素
//如果 当前目标元素的 是当前链表的 尾元素,则 将 链表的尾元素 置为 新插入的元素(把链表的尾指针 tail 指向 要插入的元素)
//当前目标元素 的后驱指针 指向 要初入的元素
element->next = new_element;
}
dlist->size ++;
return 0;
}

/*1:  将新元素插入到双链表中 由参数element所指向的元素 之前
2: 同单链表最大的区别在于:除了要管理next
指针外,还必须管理prev指针,以保证链表的 反向链接关系 正确
3: 若element = NULL, 则双向链表应该为空,否则退出并返-1;
若element != NULL,则需要在element->prev位置插入元素,插入的新元素的数据域为第三个参数data.另外还需要考虑当element为head结点时的情况。
*/
/* 插入成功返回0 ,反之返回 -1 */
/* O(1)*/
int
dlist_ins_prev(Dlist *dlist,DlistElmt *element,const void *data){
DlistElmt *new_element;
//Do not allow a NULL unless the list is empty
if(element == NULL && dlist_size(dlist) != 0){
return -1;
}
if((new_element = (DlistElmt*)malloc(sizeof(DlistElmt))) == NULL){
return -1;
}
new_element->data = (void*)data;
//如果当前链表为 空表,再插入新元素 的情况
if(dlist_size(dlist) == 0){
dlist->head = new_element;
dlist->tail = new_element;//链表的尾指针也指向 当前元素
new_element->prev = NULL; //链表的头元素 的 前驱指针 指向NULL
new_element->next = NULL;//链表的头元素 的 后驱指针 指向NULL(当前情况 链表中只要这一个元素)
} else {
new_element->next = element;
new_element->prev = element->prev;
if(element->prev == NULL){
dlist->head = new_element;
}
else{
element->prev->next = new_element;
}
element->prev = new_element;
}

dlist->size++;

return 0;
}

/* 1: remove操作将指定得元素从 双链表中删除;同单链表最大的区别在于:除了要管理next
指针外,还必须管理prev指针,以保证链表的 反向链接关系 正确
2: 对于双链表还有一个不同于 单链表 的地方在于 :该接口 移除当前指定的元素,而不是移除指定元素之后的那个元素,因为每个元素都有一个指向其前驱的指针

3: element代表 目标节点, 删除操作针对 element节点
*/
/* 删除成功返回0 ,反之返回 -1 */
/* O(1)*/
int dlist_remove(Dlist *dlist,DlistElmt *element, void **data){
/*  Don't allow a NULL element or  removal from an empty  dlist */
if(element == NULL || dlist_size(dlist) == 0){
return -1;
}
*data = element->data;
/*  handle  removal from the head of the dlist */
// 若为 删除节点为 链表的 头节点
if(element == dlist->head){
//将链表头节点的 指针 指向 目标元素的 next指针(目标元素的下一个位置 元素)
dlist->head = element->next;
//若链表的head指针 指向NULL 则 tail 也必须指向NULL,删除元素后,可能为空表
if(dlist->head == NULL){
dlist->tail = NULL;
} else{
//若 head 指针 不为NULL ,则将必须将 目标元素的 前驱指针的 prev指向NULL(其实这个时候 element->next 就是 链表的 第一个元素 ,这个时候 第一元素的 前驱指针必须置为 NULL)
element->next->prev = NULL;
}
} else {
/*  handle  removal from other than the head of the dlist */
//将 当前要删除的元素的 前一个位置的元素 的 next指针 指向 当前元素的 next指针(也就是当前位置元素 的后一个位置的 元素)
element->prev->next = element->next;
//
if(element->next == NULL){
dlist->tail = element->prev;
}else{
//将 当前位置要删除元素的 后一个位置的元素 的前驱指针prev 指向 当前元素的前驱指针(也就是当前元素的 前一个位置的元素)
element->next->prev = element->prev;
}
}
free(element);
dlist->size --;
return 0;
}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169
//
//  test_dlist_main.c
//
//
//  Created by TTc on 16/5/25.
//
//
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#include "dlist.h"

typedef struct Cuboid_
{
int length;
int width;
int height;
}Cuboid;

Cuboid *cube_instance(const int length, const int width, const int height)
{
Cuboid *cb_ptr;
cb_ptr = (Cuboid *)malloc(sizeof(Cuboid));
if( cb_ptr == NULL )
return NULL;

cb_ptr->length = length;
cb_ptr->width = width;
cb_ptr->height = height;

return cb_ptr;
}

/*destroy */
void destroy(void *data)
{
free(data);
return;
}

/* main */
int main(int argc, char **argv)
{
int i;
Dlist dlist_exp;
DlistElmt *p = NULL;
Cuboid *cb1_ptr, *cb2_ptr, *cb3_ptr, *cb4_ptr, *cb5_ptr;
Cuboid *cb_ptr;

//cb1_ptr ~ cb5_ptr are the data of the 5 elements.
cb1_ptr = cube_instance(1,2,3);
cb2_ptr = cube_instance(6,10,8);
cb3_ptr = cube_instance(5,20,30);
cb4_ptr = cube_instance(17,100,25);
cb5_ptr = cube_instance(3,6,9);

//init the double linked list.
dlist_init(&dlist_exp, destroy);

//insert the 5 elements into the dlist
dlist_ins_next(&dlist_exp, NULL, (void *)cb1_ptr );  //insert data:cb1
p = dlist_head(&dlist_exp); //get the address of the first element
dlist_ins_next(&dlist_exp, p , (void *)cb2_ptr );   //insert data:cb2    cb1- cb2
p = dlist_next(p);          //pointer to the element containing the data cb2.
dlist_ins_prev(&dlist_exp, p, (void *)cb3_ptr );    //insert data:cb3   cb1- cb3- cb2
dlist_ins_prev(&dlist_exp, p, (void *)cb4_ptr );    //insert data:cb4   cb1- cb3- cb4- cb2
p = dlist_prev(p);          //pointer to the element conatining the data cb4.
dlist_ins_prev(&dlist_exp, p, (void *)cb5_ptr );      //insert data:cb5   cb1- cb3- cb5- cb4- cb2

//now the sequence is: head->cb1->cb3->cb5->cb4->cb2
printf("traverse and print:\n");
p = dlist_head(&dlist_exp); //get the head element;
for( i = 0; i < dlist_size(&dlist_exp); i++ )
{
cb_ptr = (Cuboid *)dlist_data(p); //get the element's data, every data is a Cuboid's pointer.
printf("i = %d: ",i);
printf("length = %d, width = %d, height = %d\n",
cb_ptr->length,
cb_ptr->width,
cb_ptr->height);
p = dlist_next(p); //pointer to next element;
}

//we'll remove the third element:that's containing the data of cb5(3,6,9)
p = dlist_head(&dlist_exp);
p = dlist_next(p);
p = dlist_next(p);
dlist_remove(&dlist_exp, p, (void **)&cb_ptr);
printf("the data of the third element: length = %d, width = %d, height = %d\n",
cb_ptr->length,
cb_ptr->width,
cb_ptr->height);
destroy(cb_ptr); //free the memory

//now we'll show you the remained elements,the sequence is :(head)cb1->cb3->cb4->cb2(tail)
printf("after remove the third elements:\n");
p = dlist_head(&dlist_exp);
for(i = 0; i < dlist_size(&dlist_exp); i++ )
{
cb_ptr = (Cuboid *)dlist_data(p);
printf("i = %d: ",i);
printf("length = %d, width = %d, height = %d\n",
cb_ptr->length,
cb_ptr->width,
cb_ptr->height);
p = dlist_next(p);
}

//destroy the double linked list
dlist_destroy(&dlist_exp);
printf("after destroy the list,its size = %d\n", dlist_size(&dlist_exp));
return 0;
}


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: