[数据结构与算法] : 单向链表

Posted moon1992

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[数据结构与算法] : 单向链表相关的知识,希望对你有一定的参考价值。

头文件

 1 // filename: list.h
 2 typedef int ElementType;
 3 
 4 #ifndef _LIST_H_
 5 #define _LIST_H_
 6 
 7 struct Node;
 8 typedef struct Node *PtrToNode;
 9 typedef PtrToNode List;
10 typedef PtrToNode Position;
11 
12 List MakeEmpty(List L);
13 int IsEmpty(List L);
14 int IsLast(Position P, List L);
15 Position Find(ElementType X, List L);
16 void Delete(ElementType X, List L);
17 Position FindPrevious(ElementType X, List L);
18 void Insert(ElementType X, List L, Position P);
19 void DeleteList(List L);
20 Position Header(List L);
21 Position First(List L);
22 Position Advance(Position P);
23 ElementType Retrieve(Position P);
24 void PrintElement(ElementType X);
25 void TraversList(List L);        // 正序遍历(递归法)
26 void ReverseTraversList(List L); // 逆序遍历(递归法)
27 void TraverseL(List L);          // 对于一个庞大的栈递归可能造成越出栈空间, 使用goto消除尾递归
28 void TraverseL2(List L);         // while循环遍历
29 
30 #endif

源文件

filename: list.c

  1 #include "list.h"
  2 #include <malloc.h>
  3 #include <stdlib.h>
  4 
  5 struct Node
  6 {
  7     ElementType Element;
  8     PtrToNode Next;
  9 };
 10 
 11 // 创建或者清空链表
 12 List MakeEmpty(List L)
 13 {
 14     if(L != NULL)
 15         DeleteList(L);
 16     else
 17     {
 18         L = (List)malloc( sizeof(struct Node) );
 19         if(L == NULL)
 20         {
 21             exit(-1);
 22         }
 23         L->Next = NULL;  // 非常重要
 24     }
 25     return L;
 26 }
 27 
 28 int IsEmpty(List L)
 29 {
 30     return L->Next == NULL;
 31 }
 32 
 33 int IsLast(Position P, List L)
 34 {
 35     return P->Next == NULL;
 36 }
 37 
 38 // 查找
 39 Position Find(ElementType X, List L)
 40 {
 41     Position P;
 42     P = L->Next;
 43     while(P != NULL && P->Element != X)
 44         P = P->Next;
 45     return P;
 46 }
 47 
 48 // 删除, 注意先判断待删除的元素是否在链表中
 49 void Delete(ElementType X, List L)
 50 {
 51     Position P = FindPrevious(X, L);// 获得待删除元素的前驱
 52 
 53     if( !IsLast(P, L) ) // 如果X的前驱P是最后一个元素, 则表示L中无X
 54     {
 55         Position Q = P->Next;
 56         P->Next = Q->Next;
 57         free(Q);
 58     }
 59 }
 60 
 61 // 查找前驱, 注意区分Find操作与FindPrevious的区别是P的初始值不同
 62 Position FindPrevious(ElementType X, List L)
 63 {
 64     Position P;
 65     P = L;
 66     while(P->Next != NULL && P->Next->Element != X)
 67         P = P->Next;
 68     return P;
 69 }
 70 
 71 // 插入, 在P之后插入
 72 void Insert(ElementType X, List L, Position P)
 73 {
 74     Position TmpCell;
 75     // 先创建一个新节点
 76     TmpCell = (List)malloc( sizeof(struct Node) );
 77     if(TmpCell == NULL)
 78     {
 79         exit(-1);
 80     }
 81 
 82     TmpCell->Element = X;
 83     TmpCell->Next = P->Next;
 84     P->Next = TmpCell;
 85 }
 86 
 87 // 销毁链表, 需要两个指针
 88 void DeleteList(List L)
 89 {
 90     Position P, Q;
 91 
 92     P = L->Next; // 重要, 保留头节点
 93     L->Next = NULL;
 94     while(P != NULL)
 95     {
 96         Q = P->Next;
 97         free(Q);
 98         P = Q;
 99     }
100 }
101 
102 Position Header(List L)
103 {
104     return L;
105 }
106 
107 Position First(List L)
108 {
109     return L->Next;
110 }
111 
112 Position Advance(Position P)
113 {
114     return P->Next;
115 }
116 
117 ElementType Retrieve(Position P)
118 {
119     return P->Element;
120 }
121 
122 void PrintElement(ElementType X)
123 {
124     printf("%d ", X);
125 }
126 
127 // 递归遍历链表
128 void TraversList(List L)
129 {
130     if(L != NULL)
131     {
132         PrintElement(L->Element);
133         TraversList(L->Next);
134     }
135 }
136 
137 // 递归反向打印链表
138 void ReverseTraversList(List L)
139 {
140     if(L != NULL)
141     {
142         ReverseTraversList(L->Next);
143         PrintElement(L->Element);
144     }
145 }
146 
147 void TraverseL(List L)
148 {
149     top:
150         if(L != NULL)
151         {
152             PrintElement(L->Element);
153             L = L->Next;
154             goto top;
155         }
156 }
157 
158 // 遍历链表, 非递归实现, 推荐
159 void TraverseL2(List L)
160 {
161     while(L != NULL)
162     {
163         PrintElement(L->Element);
164         L = L->Next;
165     }
166 }

测试文件

 1 #include "list.h"
 2 #include <stdio.h>
 3 
 4 void
 5 PrintList( const List L )
 6 {
 7     Position P = Header( L );
 8 
 9     if( IsEmpty( L ) )
10         printf( "Empty list\n" );
11     else
12     {
13         do
14         {
15             P = Advance( P );
16             printf( "%d ", Retrieve( P ) );
17         } while( !IsLast( P, L ) );
18         printf( "\n" );
19     }
20 }
21 
22 void TraverseList(const List L)
23 {
24     Position P = Header(L);
25     if( IsEmpty(L) )
26         printf("链表为空\n");
27     else
28     {
29         do
30         {
31             P = Advance(P);
32             printf("%d ", Retrieve(P));
33         } while( !IsLast(P, L) );
34         printf("\n");
35     }
36 }
37 
38 main( )
39 {
40     List L;
41     Position P;
42     int i;
43 
44     L = MakeEmpty( NULL );
45     P = Header( L );
46     // TraverseList( L );
47     TraverseList(L);
48 
49     for( i = 0; i < 10; i++ )
50     {
51         Insert( i, L, P );
52         TraverseList( L );
53         P = Advance( P );
54     }
55     for( i = 0; i < 10; i+= 2 )
56         Delete( i, L );
57 
58     for( i = 0; i < 10; i++ )
59         if( ( i % 2 == 0 ) == ( Find( i, L ) != NULL ) )
60             printf( "Find fails\n" );
61 
62     printf( "Finished deletions\n" );
63 
64     TraverseList( L );
65     TraversList( Advance(L) );
66     printf("\n");
67     ReverseTraversList( Advance(L) );
68     printf("\n");
69     TraverseL( Advance(L) );
70     printf("\n");
71     TraverseL2( Advance(L) );
72     printf("\n");
73 
74     DeleteList( L );
75 
76     return 0;
77 }

 

以上是关于[数据结构与算法] : 单向链表的主要内容,如果未能解决你的问题,请参考以下文章

java数据结构与算法:java代码模拟带头节点单向链表的业务

数据结构与算法学习-单向链表的实现

Java数据结构与算法——单向链表

[数据结构与算法] : 单向链表

数据结构与算法: 约瑟夫问题(丢手绢)

算法入门(七,数据结构,单向链表与双链表)