结构
单链表节点
//链表的节点public class Node{#region 数据域public int index;public string str;#endregion#region 指针域public Node next;//下一个节点#endregion//创建这个节点时,存入数据public Node(int index,string str){this.index = index;this.str = str;}}
单链表对象类
public class SingleLinkList{public LinkNode head { get; } = new LinkNode(0, "");//头节点,这个节点没有具体数据,表示单链表的头(有些链表没有头节点)//1.添加节点到链表末尾//2.显示全部数据//3.查询节点//4.插入节点//5.修改节点//6.删除节点}
1.添加节点到末尾
在SingleLinkList类里面的方法
//添加节点到链表的末尾public void AddLast(LinkNode node){//找到当前链表的最后一个节点,将最后一个节点的next指向这个新的节点LinkNode temp = head;//声明一个临时指针,先指向链表头while (true)//循环遍历这个链表的节点{if (temp.next == null){//如果当前节点的下一个节点为null,就说明当前节点就是最后一个了,因此退出循环break;}//如果没有退出当前循环,就说明没有到最后一个节点,这个临时指针就指向下一个节点temp = temp.next;}//退出循环就说明找到了最后一个节点,temp就是最后一个节点,连接上新的节点,添加完成temp.next = node;}
2.显示全部节点
在SingleLinkList类里面的方法
就是遍历一遍链表。
//显示链表全部数据public void Show(){if (head.next == null){Console.WriteLine("链表为空");return;}LinkNode temp = head.next;//链表不为空的话至少有一个数据while (true){Console.WriteLine(temp.index + temp.str);if (temp.next == null){break;}temp = temp.next;}}
3.查询节点
在SingleLinkList类里面的方法
//根据str查找数据节点public LinkNode Select(string str){if (head.next == null){Console.WriteLine("链表为空");return null;}LinkNode temp = head.next;bool isFind = false;//一个标记,表示有没有查询到数据while (true){if (temp.str == str)//查到了数据,退出循环,temp就是要找的节点{isFind = true;break;}if (temp.next == null)//最后一个节点了{break;}temp = temp.next;}if (isFind)//找到了数据就返回temp这个数据节点{return temp;}else//没找到就返回空{return null;}}
4.插入节点
在SingleLinkList类里面的方法
//添加的时候按顺序某个值的顺序添加,也叫插入public void AddOrder(LinkNode node){LinkNode temp = head;bool isExist = false;//添加的节点的某个值是否 已经存在while (true){if (temp.next==null)//先判断是不是在最后,当前节点在链表最后就退出循环{break;}//当前节点的下一个节点比新节点的数据大,那么新节点插入到当前节点和下一个节点之间。(我这里是升序,降序思路反过来)if (temp.next.index > node.index){break;}if (temp.index == node.index)//如果发现值一样的就不能添加了,当然这个判断重复根据情况而定,有些需要有些不需要{isExist = true;break;}temp = temp.next;}if (isExist){Console.WriteLine("已经存在了不能添加");return;}else{//用新节点next指向下一个节点,当前节点next指向新节点,新节点就插入到中间了,链子又连接起来了node.next = temp.next;temp.next = node;}}
5.修改节点
在SingleLinkList类里面的方法
//通过index值修改节点数据public void Update(LinkNode node){if (head.next == null){Console.WriteLine("链表为空");return;}LinkNode temp = head.next;bool isFind = false;//是否找到对应要修改的节点while (true){if (temp.index == node.index)//找到了节点{isFind = true;break;}if (temp.next == null)//最后一个节点了{break;}temp = temp.next;}if (isFind){//找到了就修改节点数据temp.str = node.str;}else{Console.WriteLine("没有找到该节点");}}
6.删除节点
在SingleLinkList类里面的方法
//通过index删除对应的节点public void Delete(int index){if (head.next == null){Console.WriteLine("链表为空");}LinkNode temp = head;bool isFind = false;//是否找到对应的节点while (true){if (temp.next == null){break;}//temp表示要删除节点的上一个节点,如果temp直接代表这个要删除的节点,那要删除的节点的上一个和下一个节点无法连接if (temp.next.index==index){isFind = true;break;}temp = temp.next;}if (isFind){//要删除的节点是temp.next,把temp指向temp.next.next,中间temp.next没有引用就删除了temp.next = temp.next.next;}else{Console.WriteLine("没有找到数据");}}
单链表题
1.得到单链表有效节点个数
就是遍历,计数
//单链表有效节点的个数,传入上方单链表的头节点,头结点不算有效节点static int SingleLinkListCount(LinkNode head){//有头节点的要去掉头节点if (head.next == null){return 0;}LinkNode temp = head.next;int count = 0;while (temp != null){count++;temp = temp.next;}return count;}
2.查找单链表中倒数第k个节点
思路:
- 从链表头到尾遍历得到有效节点个数
- 得到链表的有效节点个数size后,从头开始遍历到(size-k)个就可以得到
找到返回该节点,否这返回null
/*查找单链表中倒数第k个元素*/static LinkNode FindLast_k_Node(LinkNode head,int k){if (head.next == null)//链表为空{return null;}LinkNode temp = head.next;int size = SingleLinkListCount(head);//调用上面的方法得到链表有效数据个数//用for限制遍历到size-k为止for(int i = 0; i < size - k; i++){//不用做什么,就迭代到下一个,最后一个就是倒数第k个元素temp = temp.next;}return temp;}
3.单链表的反转
思路:
先定义一个节点
LinkNode reverseHead = new LinkNode();- 从头到尾遍历原来的链表,每遍历一个节点,就将其取出,并放在新的链表reverseHead的最前端
- 原来链表的
head.next=reverseHead.next
图解




static void reverseLinkList(LinkNode head){//链表为空或者只有一个节点,不用反转if (head.next == null || head.next.next == null){return;}//定义一个辅助指针,帮助遍历原来的链表LinkNode cur = head.next;LinkNode next = null;//指向当前节点(cur)的下一个节点LinkNode reverseHead = new LinkNode(0,"");//反转的开始节点while (cur != null){next = cur.next;//把当前节点的下一个节点暂时保存在next里面,因为要把reverseHead.next放在当前节点的nextcur.next = reverseHead.next;//想象cur是反转链表的第一个,就要把反转链表之后的节点都放在cur之后reverseHead.next = cur;//cur放在reverseHead反转链表头的第一个cur = next;//当前节点后移}head.next = reverseHead.next;//原链表的head指向反转链表的next}
4.从尾到头打印单链表
思路:
方式1先反转单链表,再遍历打印。这样做会破坏原来的单链表的结构。
方式2利用栈这个数据结构,将各个节点压入栈中,利用栈的先进后出的特点,就实现了逆序打印的效果
这里使用方式2
先写一个简单的栈结构
public class SimpleStack<T>{T[] t = null;int top = -1;//栈顶部默认-1,初始没有数据public SimpleStack(int i){t = new T[i];}//入栈public void Push(T t){if (top + 1 >= this.t.Length){Console.WriteLine("栈满了");return;}else{top++;this.t[top] = t;}}//出栈public T Pop(){if (top == -1){Console.WriteLine("栈没有数据");return default(T);}return this.t[top--];}}
然后,遍历链表入栈,遍历出栈
//反转打印链表,传入第一个有效节点static void showReverseLinkList(LinkNode node){SimpleStack<LinkNode> stack = new SimpleStack<LinkNode>(10);while (node != null){stack.Push(node);node = node.next;}while (true){LinkNode linknode = stack.Pop();if (linknode == null)break;Console.WriteLine(linknode.index+linknode.str);}}
