在编程领域,数据结构与算法向来都是提升编程能力的重点。而一般常见的数据结构是链表,栈,队列,树等。事实上C#也已经封装好了这些数据结构,在头文件 System.Collections.Generic 中,直接创建并调用其成员方法就行。不过我们学习当然要知其然,亦知其所以然。

本文实现的是链表中的单链表和双向链表,并且实现了一些基本方法

一. 定义一个链表接口 MyList

接口里声明了我们要实现的方法:

  1. interface MyList<T>
  2. {
  3. int GetLength(); //获取链表长度
  4. void Clear(); //清空链表
  5. bool IsEmpty(); //判断链表是否为空
  6. void Add(T item); //在链表尾部添加新节点
  7. void AddPre(T item,int index); //在指定节点前添加新节点
  8. void AddPost(T item,int index); //在指定节点后添加新节点
  9. T Delete(int index); //按索引删除节点
  10. T Delete(T item,bool isSecond = true); //按内容删除节点,如果有多个内容相同点,则删除第一个
  11. T this[int index] { get; } //实现下标访问
  12. T GetElem(int index); //根据索引返回元素
  13. int GetPos(T item); //根据元素返回索引地址
  14. void Print(); //打印
  15. }

二. 实现单链表

2.1 节点类

先定义一个单链表所用的节点类,Node。而且我们要实现泛型

先定义一个数据域和下一节点(“Next”),并进行封装,然后给出数个重载构造器。这一步比较简单,这里直接给出代码

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace 线性表
  7. {
  8. /// <summary>
  9. /// 单向链表节点
  10. /// </summary>
  11. /// <typeparam name="T"></typeparam>
  12. class Node<T>
  13. {
  14. private T data; //内容域
  15. private Node<T> next; //下一节点
  16. public Node()
  17. {
  18. this.data = default(T);
  19. this.next = null;
  20. }
  21. public Node(T value)
  22. {
  23. this.data = value;
  24. this.next = null;
  25. }
  26. public Node(T value,Node<T> next)
  27. {
  28. this.data = value;
  29. this.next = next;
  30. }
  31. public T Data
  32. {
  33. get { return data; }
  34. set { data = value; }
  35. }
  36. public Node<T> Next
  37. {
  38. get { return next; }
  39. set { next = value; }
  40. }
  41. }
  42. }

2.2 链表类

创建一个链表类,命名为 LinkList 并继承 MyList

先定义一个头结点,尾节点和一个 count;

其中,head 表示该链表的头部,不包含数据;

tail 表示尾节点,指向该链表最后一个节点,当链表中只有 head 时,tail 指向 head。定义 tail 会方便接下来的操作

count 用来表示该链表中除了 head 以外的节点个数

构造函数:

  1. /// <summary>
  2. /// 构造器
  3. /// </summary>
  4. public LinkList()
  5. {
  6. head = new Node<T>();
  7. tail = head;
  8. count = 0;
  9. }

在我们实现成员函数之前,先实现两个特别的方法,因为在许多的成员方法中都要做两个操作:

  • 判断索引 index 是否合法,即是否小于0或者大于当前链表的节点个数
  • 寻找到 index 所代表的节点

①. 判断索引是否合法,然后可以根据其返回的数值进行判断操作

②. 寻找节点。

定义这两个方法主要是它们的重复使用率高,所以把它们的代码抽出来。

相对于数组,链表的插入与删除更方便,而查找却更加费时,一般都是从头结点开始遍历链表,时间复杂度为 O(n) ,而跳跃链表则会对查询进行优化,当然这会在下一篇中详述。现在继续来实现成员方法。

1. 获取链表长度

​ 

 这个方法实际上是比较简单的,因为 count 会随着添加,删除等操作自动增减,所以直接返回 count 就相当于 链表长度。

需要注意的是,本文中的 count 是不计算空头结点的,即 head 不会计算入内

2. 清空链表

这里要注意对 tail 的操作,而 head.Next 原本所指的节点不再被引用后,会被GC自动回收

3. 判断链表是否为空

因为本文实现的链表是带空头结点的,所以这里认为,当除了头结点外没有别的节点时,则为空链表

4. 在链表尾部添加节点

在链表尾添加节点一般考虑两种情况:

  • 当前除了头结点没有别的节点,此时相当于创建第一个节点
  • 寻找到最后一个节点

对于带空头结点的链表来说,这两种情况有着一样的操作,只不过第一种情况要多做一步:让 head 指向新创建的节点

定义了 tail 节点省去了 遍历寻找最后节点的步骤,如果此时是空链表的话,tail 则指向 head

5. 在指定索引的前或后添加节点

这两个方法的思路实际上相差无几的

如图,当 index 为 F 时:

  • AddPost: ① 找到 F 节点 ②创建 NEW 节点;③ NEW 节点指向 G;④ F 指向 NEW 节点
  • AddPre   :  ① 找到 E 节点 ②创建 NEW 节点;③ NEW 节点指向 F ;④ E 指向 NEW 节点

 AddPre 相当于 index - 1 处的 AddPost;AddPost 相当于 index + 1 处的 AddPre(当然,这是在 index -1 与 index + 1 合法的情况下)

6. 两种删除节点方法

  • 按索引删除:找到索引所指节点,删除
  • 按元素删除:找元素所在的索引;当找不到该元素时表明链表中不存在应该删除的节点,不执行删除操作;当链表中存在多个相同的元素时,找到并删除第一个

两种删除方法操作都是相似的,只是搜索节点的方法不同,删除时要严格注意节点间指向的,即注意书写代码时的顺序

7. 实现下标访问

这是个比较有趣的实现。前文说过对比于数组,链表胜于增减,弱于访问。对链表实现下标式访问,虽然它的内核依然是遍历链表,然后返回节点,但在使用上会方便许多,如同使用数组一般。

8. 根据索引返回元素

这个和 GetNode 方法一致

9. 根据元素返回索引地址

这个方法也是比较简单的,只是需要注意的一点是:while循环条件中 && 号两端的条件不能调换位置。因为如果调换位置后,当链表遍历到最后一个节点仍没找到元素时,pstr 会被赋值下一节点(此时为NULL),然后循环继续执行,执行到 !pstr.Data.Equals(item) 这一句时会报空指针,因为此时 pstr 就是空指针;还有因为这是泛型,所以判断两个值是否相等不能用 == 号,除非你重载 == 号。

10.打印链表

至此,所以的成员方法都实现了,先来测试一下。

1

.

其它功能读者可以自行测试,完整代码:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace 线性表
  7. {
  8. class LinkList<T> : MyList<T>
  9. {
  10. private Node<T> head; //头结点
  11. private Node<T> tail; //尾节点
  12. private int count; //节点个数
  13. /// <summary>
  14. /// 构造器
  15. /// </summary>
  16. public LinkList()
  17. {
  18. head = new Node<T>();
  19. tail = head;
  20. count = 0;
  21. }
  22. /// <summary>
  23. /// 实现下标访问法
  24. /// </summary>
  25. /// <param name="index"></param>
  26. /// <returns></returns>
  27. public T this[int index]
  28. {
  29. get
  30. {
  31. int i = IsIndexVaild(index);
  32. if(i == -1) return default(T);
  33. int k = 0;
  34. Node<T> pstr = head;
  35. while (k++ < index )
  36. {
  37. pstr = pstr.Next;
  38. }
  39. return pstr.Data;
  40. }
  41. }
  42. /// <summary>
  43. /// 在链表最末端添加新节点
  44. /// </summary>
  45. /// <param name="item"></param>
  46. public void Add(T item)
  47. {
  48. Node<T> tailNode = new Node<T>(item);
  49. tail.Next = tailNode;
  50. tail = tailNode;
  51. if (count == 0) head.Next = tailNode;
  52. count++;
  53. }
  54. /// <summary>
  55. /// 在第 index 号元素后插入一个节点
  56. /// <param name="item"></param>
  57. /// <param name="index"></param>
  58. public void AddPost(T item, int index)
  59. {
  60. int i = IsIndexVaild(index);
  61. if (i == -1) return;
  62. //找到索引元素
  63. Node<T> pstr = GetNode(index);
  64. //链接新节点
  65. Node<T> node = new Node<T>(item);
  66. node.Next = pstr.Next;
  67. pstr.Next = node;
  68. if (index == count) tail = node;
  69. count++;
  70. pstr = null;
  71. }
  72. /// <summary>
  73. /// 在第 index 号元素前插入一个节点
  74. /// </summary>
  75. /// <param name="item"></param>
  76. /// <param name="index"></param>
  77. public void AddPre(T item, int index)
  78. {
  79. int i = IsIndexVaild(index);
  80. if (i == -1) return;
  81. //找到索引的前一位元素
  82. Node<T> pstr = GetNode(index - 1);
  83. //链接新节点
  84. Node<T> node = new Node<T>(item);
  85. node.Next = pstr.Next;
  86. pstr.Next = node;
  87. count++;
  88. pstr = null;
  89. }
  90. /// <summary>
  91. /// 清空链表
  92. /// </summary>
  93. public void Clear()
  94. {
  95. head.Next = null;
  96. tail = head;
  97. }
  98. /// <summary>
  99. /// 删除指定位置的元素
  100. /// </summary>
  101. /// <param name="index"></param>
  102. /// <returns></returns>
  103. public T Delete(int index)
  104. {
  105. int i = IsIndexVaild(index);
  106. if (i == -1) return default(T);
  107. //找到索引的前一位元素
  108. Node<T> pstr = GetNode(index - 1);
  109. if (pstr.Next == null) return default(T);
  110. Node<T> qstr = pstr.Next;
  111. pstr.Next = qstr.Next;
  112. T t = qstr.Data;
  113. pstr = null;
  114. qstr.Next = null;
  115. qstr = null;
  116. count--;
  117. return t;
  118. }
  119. /// <summary>
  120. /// 按内容删除
  121. /// </summary>
  122. /// <param name="item"></param>
  123. /// <param name="isSecond"></param>
  124. /// <returns></returns>
  125. public T Delete(T item,bool isSecond = true)
  126. {
  127. int k = GetPos(item);
  128. if (k == -1) return default(T);
  129. int i = 0;
  130. Node<T> pstr = head;
  131. while (i++ < k -1)
  132. {
  133. pstr = pstr.Next;
  134. }
  135. Node<T> qstr = pstr.Next;
  136. pstr.Next = qstr.Next;
  137. T t = qstr.Data;
  138. pstr = null;
  139. qstr.Next = null;
  140. qstr = null;
  141. count--;
  142. return t;
  143. }
  144. /// <summary>
  145. /// 返回指定索引的元素
  146. /// </summary>
  147. /// <param name="index"></param>
  148. /// <returns></returns>
  149. public T GetElem(int index)
  150. {
  151. int i = IsIndexVaild(index);
  152. if (i == -1) return default(T);
  153. return GetNode(index).Data;
  154. }
  155. /// <summary>
  156. /// 返回链表长度
  157. /// </summary>
  158. /// <returns></returns>
  159. public int GetLength()
  160. {
  161. return count;
  162. }
  163. /// <summary>
  164. /// 根据元素返回其索引值
  165. /// </summary>
  166. /// <param name="item"></param>
  167. /// <returns></returns>
  168. public int GetPos(T item)
  169. {
  170. int k = 0;
  171. Node<T> pstr = head.Next;
  172. while (pstr != null && item != null && !pstr.Data.Equals(item))
  173. {
  174. pstr = pstr.Next;
  175. k++;
  176. }
  177. if (pstr == null)
  178. {
  179. Console.WriteLine("所查找元素不存在");
  180. return -1;
  181. }
  182. return k ;
  183. }
  184. /// <summary>
  185. /// 判断链表是否为空
  186. /// </summary>
  187. /// <returns></returns>
  188. public bool IsEmpty()
  189. {
  190. if (head == null || head.Next == null) return true;
  191. return false;
  192. }
  193. /// <summary>
  194. /// 打印
  195. /// </summary>
  196. public void Print()
  197. {
  198. Node<T> pstr = head.Next;
  199. int i = 1;
  200. while(pstr != null)
  201. {
  202. Console.WriteLine("第 " + i++ + "个元素是: " + pstr.Data);
  203. pstr = pstr.Next;
  204. }
  205. }
  206. /// <summary>
  207. /// 判断索引是否错误
  208. /// </summary>
  209. /// <param name="index"></param>
  210. /// <returns></returns>
  211. public int IsIndexVaild(int index)
  212. {
  213. //判断索引是否越界
  214. if (index < 0 || index > count)
  215. {
  216. Console.WriteLine("索引越界,不存在该元素");
  217. return -1;
  218. }
  219. return 0;
  220. }
  221. /// <summary>
  222. /// 根据索引找到元素
  223. /// </summary>
  224. /// <param name="index"></param>
  225. /// <returns></returns>
  226. public Node<T> GetNode(int index)
  227. {
  228. int k = 0;
  229. Node<T> pstr = head;
  230. while (k++ < index)
  231. {
  232. pstr = pstr.Next;
  233. }
  234. return pstr;
  235. }
  236. }
  237. }

三. 双向链表

双向链表在思路上和单链表差不多,只是多了一个指向上一个节点的 Prev,所以代码上要更小心地处理。具体就不多赘述了,直接给出代码吧

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace 线性表
  7. {
  8. class DBNode<T>
  9. {
  10. private T data;
  11. private DBNode<T> next;
  12. private DBNode<T> prev;
  13. public DBNode()
  14. {
  15. this.data = default(T);
  16. this.next = null;
  17. this.prev = null;
  18. }
  19. public DBNode(T value)
  20. {
  21. this.data = value;
  22. this.next = null;
  23. this.prev = null;
  24. }
  25. public DBNode(T value, DBNode<T> next)
  26. {
  27. this.data = value;
  28. this.next = next;
  29. this.prev = null;
  30. }
  31. public T Data
  32. {
  33. get { return data; }
  34. set { data = value; }
  35. }
  36. public DBNode<T> Next
  37. {
  38. get { return next; }
  39. set { next = value; }
  40. }
  41. public DBNode<T> Prev
  42. {
  43. get { return prev; }
  44. set { prev = value; }
  45. }
  46. }
  47. }

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace 线性表
  7. {
  8. class DBLinkList<T> : MyList<T>
  9. {
  10. private DBNode<T> head;
  11. private DBNode<T> tail;
  12. private int count;
  13. /// <summary>
  14. /// 构造器
  15. /// </summary>
  16. public DBLinkList()
  17. {
  18. head = new DBNode<T>();
  19. tail = head;
  20. count = 0;
  21. }
  22. /// <summary>
  23. /// 实现下标访问法
  24. /// </summary>
  25. /// <param name="index"></param>
  26. /// <returns></returns>
  27. public T this[int index]
  28. {
  29. get
  30. {
  31. int i = IsIndexVaild(index);
  32. if (i == -1) return default(T);
  33. int k = 0;
  34. DBNode<T> pstr = head;
  35. while (k++ < index)
  36. {
  37. pstr = pstr.Next;
  38. }
  39. return pstr.Data;
  40. }
  41. }
  42. /// <summary>
  43. /// 在链表最末端添加新节点
  44. /// </summary>
  45. /// <param name="item"></param>
  46. public void Add(T item)
  47. {
  48. if (count == 0)
  49. {
  50. DBNode<T> DbNode = new DBNode<T>(item);
  51. DbNode.Prev = head;
  52. head.Next = DbNode;
  53. tail = DbNode;
  54. count++;
  55. return;
  56. }
  57. DBNode<T> tailDBNode = new DBNode<T>(item);
  58. tailDBNode.Prev = tail;
  59. tail.Next = tailDBNode;
  60. tail = tailDBNode;
  61. count++;
  62. }
  63. /// <summary>
  64. /// 在第 index 号元素后插入一个节点,index 为 1,2,3,4.....
  65. /// </summary>
  66. /// <param name="item"></param>
  67. /// <param name="index"></param>
  68. public void AddPost(T item, int index)
  69. {
  70. //判断索引是否越界
  71. int i = IsIndexVaild(index);
  72. if (i == -1) return;
  73. //找到索引元素
  74. DBNode<T> pstr = GetNode(index);
  75. //链接新节点
  76. DBNode<T> newNode = new DBNode<T>(item);
  77. newNode.Next = pstr.Next;
  78. newNode.Prev = pstr;
  79. if(pstr.Next != null) pstr.Next.Prev = newNode;
  80. pstr.Next = newNode;
  81. //如果是在最后节点添加
  82. if (index == count) tail = newNode;
  83. count++;
  84. pstr = null;
  85. }
  86. /// <summary>
  87. /// 在第 index 号元素前插入一个节点,index 为 1,2,3,4.....
  88. /// </summary>
  89. /// <param name="item"></param>
  90. /// <param name="index"></param>
  91. public void AddPre(T item, int index)
  92. {
  93. //判断索引是否越界
  94. int i = IsIndexVaild(index);
  95. if (i == -1) return;
  96. //找到索引的前一位元素
  97. DBNode<T> pstr = GetNode(index - 1);
  98. //链接新节点
  99. DBNode<T> newNode = new DBNode<T>(item);
  100. newNode.Next = pstr.Next;
  101. newNode.Prev = pstr;
  102. pstr.Next.Prev = newNode;
  103. pstr.Next = newNode;
  104. count++;
  105. pstr = null;
  106. //在 index 处AddPre相当于在 index - 1 处 AddPost,不过并不需要判断尾节点
  107. }
  108. /// <summary>
  109. /// 清空链表
  110. /// </summary>
  111. public void Clear()
  112. {
  113. head.Next = null;
  114. tail = head;
  115. }
  116. /// <summary>
  117. /// 删除指定位置的元素
  118. /// </summary>
  119. /// <param name="index"></param>
  120. /// <returns></returns>
  121. public T Delete(int index)
  122. {
  123. //判断索引是否越界
  124. int i = IsIndexVaild(index);
  125. if (i == -1) return default(T);
  126. //找到索引的前一位元素
  127. DBNode<T> pstr = head;
  128. int k = 0;
  129. while (k++ < index - 1 && pstr != null)
  130. {
  131. pstr = pstr.Next;
  132. }
  133. if (pstr.Next == null) return default(T);
  134. DBNode<T> qstr = pstr.Next;
  135. T t = qstr.Data;
  136. pstr.Next = qstr.Next;
  137. qstr.Next.Prev = pstr;
  138. pstr = null;
  139. qstr.Next = null;
  140. qstr = null;
  141. count--;
  142. return t;
  143. }
  144. /// <summary>
  145. /// 按内容删除
  146. /// </summary>
  147. /// <param name="item"></param>
  148. /// <param name="isSecond"></param>
  149. /// <returns></returns>
  150. public T Delete(T item,bool isSecond = true)
  151. {
  152. int k = GetPos(item);
  153. if (k == -1) return default(T);
  154. int i = 0;
  155. DBNode<T> pstr = head;
  156. while (i++ < k - 1)
  157. {
  158. pstr = pstr.Next;
  159. }
  160. DBNode<T> qstr = pstr.Next;
  161. T t = qstr.Data;
  162. pstr.Next = qstr.Next;
  163. if(qstr.Next != null) qstr.Next.Prev = pstr;
  164. pstr = null;
  165. qstr.Next = null;
  166. qstr = null;
  167. count--;
  168. return t;
  169. }
  170. /// <summary>
  171. /// 返回指定索引的元素
  172. /// </summary>
  173. /// <param name="index"></param>
  174. /// <returns></returns>
  175. public T GetElem(int index)
  176. {
  177. int i = IsIndexVaild(index);
  178. if (i == -1) return default(T);
  179. int k = 0;
  180. DBNode<T> pstr = head;
  181. while (k++ < index)
  182. {
  183. pstr = pstr.Next;
  184. }
  185. return pstr.Data;
  186. }
  187. /// <summary>
  188. /// 返回链表长度
  189. /// </summary>
  190. /// <returns></returns>
  191. public int GetLength()
  192. {
  193. return count;
  194. }
  195. /// <summary>
  196. /// 根据元素返回其索引值
  197. /// </summary>
  198. /// <param name="item"></param>
  199. /// <returns></returns>
  200. public int GetPos(T item)
  201. {
  202. int k = 0;
  203. DBNode<T> pstr = head.Next;
  204. while (pstr != null && item != null && !pstr.Data.Equals(item))
  205. {
  206. pstr = pstr.Next;
  207. k++;
  208. }
  209. if (pstr == null)
  210. {
  211. Console.WriteLine("所查找元素不存在");
  212. return -1;
  213. }
  214. return k;
  215. }
  216. /// <summary>
  217. /// 判断链表是否为空
  218. /// </summary>
  219. /// <returns></returns>
  220. public bool IsEmpty()
  221. {
  222. if (head == null || head.Next == null) return true;
  223. return false;
  224. }
  225. /// <summary>
  226. /// 打印
  227. /// </summary>
  228. public void Print()
  229. {
  230. DBNode<T> pstr = head.Next;
  231. while (pstr != null)
  232. {
  233. Console.WriteLine(pstr.Data);
  234. pstr = pstr.Next;
  235. }
  236. }
  237. /// <summary>
  238. /// 判断索引是否错误
  239. /// </summary>
  240. /// <param name="index"></param>
  241. /// <returns></returns>
  242. public int IsIndexVaild(int index)
  243. {
  244. //判断索引是否越界
  245. if (index < 0 || index > count)
  246. {
  247. Console.WriteLine("索引越界,不存在该元素");
  248. return -1;
  249. }
  250. return 0;
  251. }
  252. /// <summary>
  253. /// 根据索引找到元素
  254. /// </summary>
  255. /// <param name="index"></param>
  256. /// <returns></returns>
  257. public DBNode<T> GetNode(int index)
  258. {
  259. int k = 0;
  260. DBNode<T> pstr = head;
  261. while (k++ < index)
  262. {
  263. pstr = pstr.Next;
  264. }
  265. return pstr;
  266. }
  267. }
  268. }

总结

事实上,链表是一种比较简单且常用的数据结构。实现起来并不困难,只是要小心谨慎。下一篇会说到跳跃链表,跳跃链表的效率更高。好了,希望本文能对大家有所帮助

【 C# 】(一) ------------- 泛型带头节点的单链表,双向链表实现的更多相关文章

  1. 带头节点的单链表-------C语言实现

    /***************************************************** Author:Simon_Kly Version:0.1 Date:20170520 De ...

  2. 不带头结点的单链表------C语言实现

    File name:no_head_link.c Author:SimonKly Version:0.1 Date: 2017.5.20 Description:不带头节点的单链表 Funcion L ...

  3. 有一个线性表,采用带头结点的单链表L来存储,设计一个算法将其逆置,且不能建立新节点,只能通过表中已有的节点的重新组合来完成。

    有一个线性表,采用带头结点的单链表L来存储,设计一个算法将其逆置,且不能建立新节点,只能通过表中已有的节点的重新组合来完成. 分析:线性表中关于逆序的问题,就是用建立链表的头插法.而本题要求不能建立新 ...

  4. java编写带头结点的单链表

    最近在牛客网上练习在线编程,希望自己坚持下去,每天都坚持下去练习,给自己一个沉淀,不多说了 我遇到了一个用java实现单链表的题目,就自己在做题中将单链表完善了一下,希望大家作为参考也熟悉一下,自己 ...

  5. C/C++中创建(带头结点、不带头结点的)单链表

    1.带头结点的单链表(推荐使用带头结点的单链表)(采用尾插法) 了解单链表中节点的构成 从上图可知,节点包含数据域和指针域,因此,在对节点进行定义时,我们可以如下简单形式地定义: /* 定义链表 */ ...

  6. c语言实现--不带头结点的单链表操作

    1,不带头结点的单链表操作中,除了InitList(),GetElem(),ListInsert(),ListDelete()操作与带头结点的单链表有差别外,其它的操作基本上一样. 2,不带头结点单链 ...

  7. 链表习题(2)-一个集合用带头结点的单链表L表示,编写算法删除其值最大的结点。

    /*一个集合用带头结点的单链表L表示,编写算法删除其值最大的结点.*/ /* 算法思想:使用pre,p,premax,max四个指针,pre和p进行比较,premax和max进行最后的删除操作 通过遍 ...

  8. 链表习题(1)-设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点

    /*设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点*/ /* 算法思想:设f(L,x)的功能是删除以L为首结点指针的单链表中所有值等于x的结点, 则显然有f(L->next,x)的 ...

  9. C语言:将带头节点的单向链表结点域中的数据从小到大排序。-求出单向链表结点(不包括头节点)数据域中的最大值。-将M*N的二维数组中的数据,按行依次放入一维数组,

    //函数fun功能是将带头节点的单向链表结点域中的数据从小到大排序. //相当于数组的冒泡排序. #include <stdio.h> #include <stdlib.h> ...

随机推荐

  1. 1070. [SCOI2007]修车【费用流】

    Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同 的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序, ...

  2. P2110 欢总喊楼记

    题目描述 诗经有云: 关关雎鸠,在河之洲.窈窕淑女,君子好逑. 又是一个被风吹过的夏天--一日欢总在图书馆中自习,抬起头来,只见一翩跹女子从面前飘过,真是回眸一笑百媚生,六宫粉黛无颜色!一阵诗情涌上欢 ...

  3. [BJWC2008]雷涛的小猫

    嘟嘟嘟 dp. 刚开始我想的是dp[i][j]表示在第 i 棵树上,高度为h能吃到的最多的果子,如此能得到转移方程: dp[i][j] = max(dp[i][j + 1], dp[k][j + de ...

  4. Jsp实现在线作业提交系统

    Jsp实现在线作业提交系统 作为 Computer Science 的学生,凌晨四点之前睡都应该感到羞耻. 项目托管地址:https://github.com/four-in-the-morning/ ...

  5. C语言不使用加号实现加法运算的几种方法

    今天看到<编码:隐匿在计算机软硬件背后的语言>的第十二章:二进制加法器.讲述了全加器,半加器的原理以及如何实现加法.实现加法时所使用的全加器,半加器中包含的所有逻辑门在C语言中都有相应的运 ...

  6. 20155314 2016-2017-2 《Java程序设计》第2周学习总结

    20155314 2016-2017-2 <Java程序设计>第2周学习总结 教材学习内容总结 学习目标 了解Java编程风格 认识Java的类型与变量 掌握Java流程控制的方法(分支. ...

  7. pip问题解决方案

    错误信息:usr/bin/pip: No such file or directory 解决办法(一共四步,按照下面的步骤来从1到4,最后你会发现问题都解决了): 1.which pip /usr/l ...

  8. 初识Qt窗口界面

    1.新建一个新的Qt Gui应用,项目名称随意,例如MyMainWindow,基类选择QMainWindow,类名为MainWindow. 2.项目建立后,双击mainwindow.ui文件,在界面的 ...

  9. sql查询以及常见问题理解解析

    推荐w3挺好的基础网站:https://www.w3cschool.cn/t_sql/t_sql_date_functions.html =,<,>,> =,<=,IN,BET ...

  10. P1586 四方定理

    题目描述 四方定理是众所周知的:任意一个正整数nn ,可以分解为不超过四个整数的平方和.例如:25=1^{2}+2^{2}+2^{2}+4^{2}25=12+22+22+42 ,当然还有其他的分解方案 ...