链表实例
链表的经典习题

链表的经典习题练习1•:链式栈//链式栈(top指向第⼀位⽆效的头结点)public class LinkedStack<E> {Node<E> top;//内部类class Node<E> {protected E data;protected Node<E> next;public Node(E data) {this.data = data;}}public LinkedStack() {top = new Node(new Object());}//头插法public void push(E val){Node<E> newNode=new Node(val) ;//创建⼀个值为val的节点newNode.next=top.next; //新插⼊节点的next指向原top指向的nexttop.next=newNode;//再把top.next指向新节点}//获取栈顶元素并删除public E remove(){if(top.next==null){throw new UnsupportedOperationException("the stack has been empty");}E result=top.next.data;top.next=top.next.next;return result;}public E peek(){if(top.next==null){throw new UnsupportedOperationException("the stack has been empty");}return top.next.data;}//从top节点的下⼀个开始遍历,不为空则⼀直的打印public void show(){Node<E> tmp=top.next;while (tmp!=null){System.out.print(tmp.data+" ");tmp=tmp.next;}System.out.println();}public static void main(String[] args) {LinkedStack<Integer> l=new LinkedStack();l.push(3);l.push(4);l.push(5);l.show();System.out.println(l.peek());l.remove();//删除5l.show();l.remove();//删除4l.show();l.remove();//删除3l.show();}}练习2:查找链表中倒数第k个节点//单链表查找倒数第k个节点class FindLastK<E> {Node<E> head;class Node<E> {protected E data;protected Node<E> next;public Node(E data,Node<E> next) {this.data = data;this.next=next;}}////构造函数,第⼀个头结点有效,所以不需要构造函数// public FindLastK() {// this.head = new Node(new Object(),null);// }//找倒数第k个数的⽅法public E lastK(int k){Node<E> cur1=this.head.next;Node<E> cur2=this.head;//cur2指向头if(head==null){return null;}if(k>getLenth()||k<=0){return null;}else if(k==getLenth()){return head.data;}for(int i=1;i<=k;i++) {cur2=cur2.next;if(cur2==null){return null;}}while (cur2.next!=null){cur2=cur2.next;cur1=cur1.next;}return cur1.data;}//获取链表长度public int getLenth(){int length=0;Node<E> cu=head;if(head==null){return 0;}while (cu!=null){ //应该让cur去遍历,不能让head直接遍历,否则打印⼀次后show再次打印链表就会空 length++;cu=cu.next;}return length;}//尾插法public void add(E val) {Node<E> newNode = new Node(val,null);Node<E> current = head;if(head==null){head=newNode;return;}while (current.next != null) {current = current.next;}current.next = newNode;// newNode.next=null;}public void show() {Node<E> current = head;if(current==null){System.out.println("链表空!!");return;}while (current!=null&¤t.next!= null) {System.out.print(current.data + " ");current = current.next;}System.out.println(current.data);}}public class FindLastKTest{public static void main(String[] args) {FindLastK<Integer> f=new FindLastK<>();f.add(3);f.add(4);f.add(5);f.add(6);f.show();System.out.println("该链表的长度:"+f.getLenth());System.out.println(stK(1));//6System.out.println(stK(4));//3System.out.println(stK(5));//nullf.show();}}练习3:找到带环链表的⼊⼝节点import sun.awt.image.ImageWatched;//单链表查找倒数第k个节点public class LinkedExercise<E> {Node<E> head;static class Node<E> {protected E data;public Node<E> next;public Node(E data, Node<E> next) {this.data = data;this.next = next;}}////构造函数,第⼀个头结点有效,所以不需要构造函数// public FindLastK() {// this.head = new Node(new Object(),null);// }//找倒数第k个数的⽅法public E lastK(int k) {Node<E> cur1 = this.head.next;Node<E> cur2 = this.head;//cur2指向头if (head == null) {return null;} else if (k > getLenth() || k <= 0) {return null;}//如果找的倒数第k个恰好为链表长度,直接将头结点的数返回else if (k == getLenth()) {return head.data;}for (int i = 1; i <= k; i++) {cur2 = cur2.next;if (cur2 == null) {return null;}}//两个节点同时遍历,快节点遍历到最后⼀个节点时,慢节点指向的节点就是要找的节点while (cur2.next != null) {cur2 = cur2.next;cur1 = cur1.next;}return cur1.data;}//获取链表长度public int getLenth() {int length = 0;Node<E> cu = head;if (head == null) {return 0;}while (cu != null) { //应该让cur去遍历,不能让head直接遍历,否则打印⼀次后show再次打印链表就会空 length++;cu = cu.next;}return length;}//判断单链表是否有环/*** 快慢指针,先通过两个指针找到环内的节点,然后再⼀个节点从相交节点出发,* 另⼀个节点从头结点出发,再次相交的节点就是环的⼊⼝节点** @return*/public E getLinkCirclrVal() {Node<E> slow = this.head;Node<E> fast = this.head;//找到了相交节点while (fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;if (slow == fast) {break;}}if (fast == null) {return null;} else {fast = this.head;while (fast != slow) {fast = fast.next;slow = slow.next;}return slow.data;}}//尾插法public void add(E val) {Node<E> newNode = new Node(val, null);Node<E> current = head;if (head == null) {head = newNode;return;}while (current.next != null) {current = current.next;}current.next = newNode;// newNode.next=null;}public void show() {Node<E> current = head;if (current == null) {System.out.println("链表空!!");return;}while (current != null && current.next != null) {System.out.print(current.data + " ");current = current.next;}System.out.println(current.data);}//构造带环的链表public void con(LinkedExercise<E> link){//将两个节点都指向头LinkedExercise.Node list=link.head;LinkedExercise.Node p=link.head;//list遍历到最后⼀个节点while (list.next!=null){list=list.next;}//让最后⼀个节点的写⼀个指向头结点的下⼀个 6指向5list.next=p.next.next;}public static void main(String[] args) {LinkedExercise<Integer> f = new LinkedExercise<>();f.add(3);f.add(4);f.add(5);f.add(6);f.show();System.out.println("该链表的长度:" + f.getLenth());System.out.println(stK(1));//6System.out.println(stK(4));//3System.out.println(stK(5));//nullf.con(f);System.out.println("环的⼊⼝节点:"+f.getLinkCirclrVal());}}练习4:合并两个有序的链表(头结点⽆效时)包含头结点⽆效的⼤多数函数:class SingleLinekdListTakeHead<E extends Comparable> {protected Node<E> head;//头节点class Node<E> {protected E data;//数据域protected Node<E> next;//next引⽤域public Node(E data, Node<E> next) {this.data = data;this.next = next;}}//初始化headpublic SingleLinekdListTakeHead() {head = new Node(new Object(), null);}//在head之后直接插⼊⼀个节点,头插法public void addHead(E element) {Node<E> newNode = new Node(element, null);newNode.next = head.next;//先让新添加的节点的下⼀个指向原head节点指向的 head.next = newNode;//再让head节点指向新节点}//尾插法public void addTail(E element) {Node<E> newNode = new Node(element, null);Node<E> tail = head;//定义⼀个节点从头⾛到尾//tail⾛到当前链表的尾部while (tail.next != null) {tail = tail.next;}tail.next = newNode;newNode.next=null;}/*** 固定位置插⼊⼀个节点* 判断参数合法性* 找到pos位置的前⼀个节点* @param pos 固定位置* @param element 元素*/public void addPos(int pos, E element) {if (pos <= 0 || pos > getLength()) {return;}Node<E> prev = head.next;int index = 1;while (index++ < pos - 1) {prev = prev.next;}Node<E> newNode = new Node<>(element, null);newNode.next = prev.next;prev.next = newNode;}//删除元素为element的节点public boolean remove(E element) {//如果只有⼀个头结点,返回falseif (head.next == null) {return false;}//找到该元素所对应的节点 + 该元素所对应的节点的前⼀个 //从头结点开始遍历Node<E> tmp = head;while (tmp != null) {if (tmp.next != null && tmp.next.data == element) {//tmp.next是我们要删除的节点 tmp是删除节点的前⼀个 tmp.next = tmp.next.next;return true;}tmp = tmp.next;}return false;}//设置某个位置的值为newElementpublic void set(int pos, E newElement){if(pos <= 0 || pos > getLength()){return;}//找pos位置的节点Node<E> tmp = head.next;for(int i=1; i < pos; i++){tmp = tmp.next;}tmp.data = newElement;}//得到某个元素的值public E get(E element){Node<E> tmp = head.next;//从有效节点开始遍历while(tmp != null){if(tmp.data == element){return tmp.data; //找到的话,返回该节点}tmp = tmp.next;}return null;} //合并两个有序的单链表public void merge(SingleLinekdListTakeHead<E> list2){// LinkedExercise<E> list3=new LinkedExercise<>();Node<E> p=this.head;//最后合并成功的的链表Node<E> p1=this.head.next;//第⼀的链表Node<E> p2=list2.head.next;//第⼆个链表while (p1!=null && p2!=null){if(pareTo(p2.data)>=0){p.next=p2;//list3.add(p2.data);p2=p2.next;}else {p.next=p1;// list3.add(p1.data);p1=p1.next;}p=p.next;}if(p1!=null){ //链表1还有剩余节点p.next=p1;}p.next=p2;}// return p.data;}//返回长度public int getLength() {Node<E> tmp = head.next;int length = 0;while (tmp != null) {length++;tmp = tmp.next;}return length;}//打印栈public String toString() {StringBuilder strs = new StringBuilder();Node<E> tmp = head.next;while (tmp != null) {strs.append(tmp.data + " ");tmp = tmp.next;}return strs.toString(); //strs是StringBuilder类型,应该添加toString⽅法,才能返回String类型的 }//逆置带有头结点的单链表public void reverse(){if(head.next==null||head.next.next==null){return;}else {Node<E> cur=this.head.next.next;//指向第⼆个有效的节点this.head.next.next=null;Node<E> pos=null;while (cur!=null){pos=cur.next;//先将cur.next指向poscur.next=head.next;head.next=cur;//头插法,将节点插在head后cur=pos;}}}}public class Linked {public static void main(String[] args) {SingleLinekdListTakeHead<Integer> list=new SingleLinekdListTakeHead();list.addHead(3);list.addHead(5);list.addHead(8);System.out.println(list.toString());//8 5 3list.addTail(1);list.addTail(2);list.addTail(4);System.out.println(list.toString());//8 5 3 1 2 4list.reverse();System.out.println(list.toString());// list.addPos(2, 100); //在2 号位置加⼊元素100// System.out.println(list.toString());// list.addPos(0, 1000);// System.out.println(list.toString());//// list.remove(4);// System.out.println("删除值为4的元素:"+list.toString());//// list.set(2,2);//true,把2号元素的值改为2// System.out.println("把2号元素的值改为2:"+list.toString());// System.out.println(list.get(3));SingleLinekdListTakeHead list1=new SingleLinekdListTakeHead();list1.addTail(2);list1.addTail(6);list1.addTail(7);SingleLinekdListTakeHead list2=new SingleLinekdListTakeHead();list2.addTail(3);list2.addTail(4);list2.addTail(5);list2.addTail(9);list2.addTail(10);list1.merge(list2);System.out.println(list1.toString());}}练习5:链式队列package Exercise;public class LinkedQueue<T> {private Entry<T> front;private Entry<T> rear;private int count;public LinkedQueue(){this.front=this.rear=new Entry<>(null,null);}class Entry<T>{T data;Entry<T> next;public Entry(T data,Entry<T> next){this.data=data;this.next=next;}}public void offer(T data){Entry<T> node=new Entry<>(data,null);this.rear.next=node;this.rear=node;this.count++;}/***出队列需要判断队列空的情况,头节点⽆效;如果队列为空,需要将front和rear都指向空*/public void poll(){if(this.front.next!=null){this.front.next=this.front.next.next;if(this.front.next == null){this.rear = this.front;}this.count--;}}public int size(){return this.count;}public T peek(){return this.front.next.data;}public void show(){Entry<T> cur=this.front.next;while (cur!=null){System.out.print(cur.data+" ");cur=cur.next;}System.out.println();}public static void main(String[] args) {LinkedQueue l=new LinkedQueue();for (int i = 0; i < 4; i++) {l.offer(i);}l.show();System.out.println("队头元素为:"+l.peek());System.out.println("队列长度为:"+l.size());l.poll();l.show();}}难点:内部类和外部类的构造函数都需要对相应属性做初始化。
mfc编程cstringlist实例

mfc编程cstringlist实例MFC编程中的CStringList实例在MFC(Microsoft Foundation Classes)编程中,CStringList是一个非常有用的类,用于管理字符串的链表。
它提供了许多方便的功能,使得操作字符串链表变得更加简单和高效。
在本文中,我们将逐步回答关于CStringList的问题,并给出一些实例代码来帮助读者更好地理解和使用这个类。
问题1:什么是CStringList?CStringList是MFC框架中的一个类,它是一个模板类,用于处理字符串的链表。
它使用的是C++的模板机制,可以在链表中存储任意类型的数据。
但在这里,我们主要关注它在处理字符串方面的应用。
问题2:如何创建一个CStringList对象?要创建一个CStringList对象,只需简单地声明一个新的实例即可:CStringList strList;这将创建一个名为strList的CStringList对象。
您可以根据需要创建多个实例,并在程序的任何地方使用它们。
问题3:如何向CStringList中添加字符串?要向CStringList中添加字符串,可以使用AddHead()或AddTail()成员函数。
AddHead()函数将字符串添加到链表的头部,而AddTail()函数则将字符串添加到链表的尾部。
下面是一些示例代码:CStringList strList;strList.AddHead("Hello");strList.AddTail("World");这将创建一个名为strList的CStringList对象,并向其头部添加字符串"Hello",在其尾部添加字符串"World"。
问题4:如何遍历并访问CStringList中的字符串?要遍历并访问CStringList中的字符串,可以使用CstringList的一个迭代器。
链表及其应用

头指针是指向链表中第一个结点(或为头结点或为首
元素结点)的指针。 单链表可由一个头指针唯一确定。
头结点是在链表的首元素结点之前附设的一个结点;
数据域内只放空表标志和表长等信息;
首元素结点是指链表中存储线性表第一个数据元素
a1的结点。
33
第3章 链表及其应用
讨论1. 在链表中设置头结点有什么好处?
我们可以用结构体来定义静态链表的节点数据类型: typedef struct{ Datatype data; int next; }node;
一个静态链表可以描述为: #define maxsize 100 node nodepool[maxsize];//存放链表的数组 int head; //放头指针的head 在静态链表中进行插入与删除操作不需要移动元素,
4
第3章 链表及其应用
3.1 链表的基本概念
3.1.1 什么是链表 ☞ 3.1.2 链表的逻辑结构
3.1.3 链表的存储结构 3.1.4 静态链表和动态链表 3.1.5 链表的基本运算
5
第3章 链表及其应用
♣ 链表的逻辑结构
☞ 同一链表中所有数据元素的数据类型必须相同。 ☞ 链表中相邻的元素ai-1、ai间存在序偶关系,即 对于非空的链表,ai-1是ai的唯一直接前驱,ai+1是 ai的唯一直接后继;而a1无前驱,an无后继 ☞ 链表属于线性逻辑结构。
结点3的地址:p->next;
28
第3章 链表及其应用
H
a1
p
p
a2
a3
a4
a5 ∧
再令p = p->next, 数据元素a3值:p ->data
结点4的地址:p->next;
[转载整理]C语言链表实例
![[转载整理]C语言链表实例](https://img.taocdn.com/s3/m/0aca427eb94ae45c3b3567ec102de2bd9605debe.png)
[转载整理]C语⾔链表实例 C语⾔链表有单链表、双向链表、循环链表。
单链表由数据域和指针域组成,数据域存放数据,指针域存放该数据类型的指针便于找到下⼀个节点。
双链表则含有头指针域、数据域和尾指针域,域单链表不同,双链表可以从后⼀个节点找到前⼀个节点,⼆单链表则不⾏。
循环链表就是在单链表的基础上,将头结点的地址指针存放在最后⼀个节点的指针域⾥以,此形成循环。
此外还有双向循环链表,它同时具有双向链表和循环链表的功能。
单链表如:链表节点的数据结构定义struct node{int num;struct node *p;} ;在此链表节点的定义中,除⼀个整型的成员外,成员p是指向与节点类型完全相同的指针。
※在链表节点的数据结构中,⾮常特殊的⼀点就是结构体内的指针域的数据类型使⽤了未定义成功的数据类型。
这是在C中唯⼀规定可以先使⽤后定义的数据结构。
链表实例代码:1// 原⽂地址 /wireless-dragon/p/5170565.html2 #include<stdio.h>3 #include<stdlib.h>4 #include<string.h>56 typedef int elemType;//定义存⼊的数据的类型可以是int char78 typedef struct NODE{ //定义链表的结构类型9 elemType element;10struct NODE *next;11 }Node;1213/************************************************************************/14/* 以下是关于线性表链接存储(单链表)操作的19种算法 */1516/* 1.初始化线性表,即置单链表的表头指针为空 */17/* 2.创建线性表,此函数输⼊负数终⽌读取数据*/18/* 3.打印链表,链表的遍历*/19/* 4.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为⼀个空表 */20/* 5.返回单链表的长度 */21/* 6.检查单链表是否为空,若为空则返回1,否则返回0 */22/* 7.返回单链表中第pos个结点中的元素,若pos超出范围,则停⽌程序运⾏ */23/* 8.从单链表中查找具有给定值x的第⼀个元素,若查找成功则返回该结点data域的存储地址,否则返回NULL */24/* 9.把单链表中第pos个结点的值修改为x的值,若修改成功返回1,否则返回0 */25/* 10.向单链表的表头插⼊⼀个元素 */26/* 11.向单链表的末尾添加⼀个元素 */27/* 12.向单链表中第pos个结点位置插⼊元素为x的结点,若插⼊成功返回1,否则返回0 */28/* 13.向有序单链表中插⼊元素x结点,使得插⼊后仍然有序 */29/* 14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停⽌程序运⾏ */30/* 15.从单链表中删除表尾结点并返回它的值,若删除失败则停⽌程序运⾏ */31/* 16.从单链表中删除第pos个结点并返回它的值,若删除失败则停⽌程序运⾏ */32/* 17.从单链表中删除值为x的第⼀个结点,若删除成功则返回1,否则返回0 */33/* 18.交换2个元素的位置 */34/* 19.将线性表进⾏冒排序 */35363738/*注意检查分配到的动态内存是否为空*/3940414243/* 1.初始化线性表,即置单链表的表头指针为空 */44void initList(Node **pNode)45 {46 *pNode=NULL;47 printf("initList函数执⾏,初始化成功\n");48 }4950/* 2.创建线性表,此函数输⼊负数终⽌读取数据*/51 Node *creatList(Node *pHead)52 {53 Node *p1,*p2;54 p1=p2=(Node *)malloc(sizeof(Node));55if(p1 == NULL || p2 ==NULL)57 printf("内存分配失败\n");58 exit(0);59 }60 memset(p1,0,sizeof(Node));6162 scanf("%d",&p1->element);63 p1->next=NULL;6465while(p1->element >0) //输⼊的值⼤于0则继续,否则停⽌66 {67if(pHead == NULL)//空表,接⼊表头68 {69 pHead=p1;70 }71else72 {73 p2->next=p1;74 }7576 p2=p1;77 p1=(Node *)malloc(sizeof(Node));7879if(p1==NULL||p2==NULL)80 {81 printf("内存分配失败\n");82 exit(0);83 }84 memset(p1,0,sizeof(Node));85 scanf("%d",&p1->element);86 p1->next=NULL;87 }88 printf("CreatList函数执⾏,链表创建成功\n");89return pHead;90 }9192/* 3.打印链表,链表的遍历*/93void printList(Node *pHead)94 {95if(NULL==pHead)96 {97 printf("PrintList函数执⾏,链表为空\n");98 }99else100 {101while(NULL!=pHead)102 {103 printf("%d\n",pHead->element);104 pHead=pHead->next;105 }106 }107108 }109110111/* 4.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为⼀个空表 */ 112void clearList(Node *pHead)113 {114 Node *pNext;115116if(pHead==NULL)117 {118 printf("clearList函数执⾏,链表为空\n");119return;120 }121while(pHead->next!=NULL)122 {123 pNext=pHead->next;124free(pHead);125 pHead=pNext;126 }127 printf("clearList函数执⾏,链表已经清除!\n");128129 }130131/* 5.返回链表的长度*/132int sizeList(Node *pHead)133 {134int size=0;135136while(pHead!=NULL)137 {138 size++;139 pHead=pHead->next;141 printf("sizelist函数执⾏,链表长度为%d\n",size);142return size;143 }144145/* 6.检查单链表是否为空,若为空则返回1,否则返回0 */146int isEmptyList(Node *pHead)147 {148if(pHead==NULL)149 {150 printf("isEmptylist函数执⾏,链表为空!\n");151return1;152 }153154else155 printf("isEmptylist函数执⾏,链表⾮空!\n");156return0;157158 }159160/* 7.返回链表中第post节点的数据,若post超出范围,则停⽌程序运⾏*/161int getElement(Node *pHead,int pos)162 {163int i=0;164if(pos<1)165 {166 printf("getElement函数执⾏,pos值⾮法!");167return0;168 }169if(pHead==NULL)170 {171 printf("getElement函数执⾏,链表为空!");172 }173174while (pHead!=NULL)175 {176 ++i;177if(i==pos)178 {179break;180 }181 pHead=pHead->next;182 }183if(i<pos)184 {185 printf("getElement函数执⾏,pos值超出链表长度\n");186return0;187 }188 printf("getElement函数执⾏,位置%d中的元素为%d\n",pos,pHead->element);189190return1;191 }192193//8.从单⼀链表中查找具有给定值x的第⼀个元素,若查找成功后,返回该节点data域的存储位置,否则返回NULL 194 elemType *getElemAddr(Node *pHead,elemType x)195 {196if(NULL==pHead)197 {198 printf("getEleAddr函数执⾏,链表为空");199return NULL;200 }201if(x<0)202 {203 printf("getEleAddr函数执⾏,给定值x不合法\n");204return NULL;205 }206while((pHead->element!=x)&&(NULL!=pHead->next))//判断链表是否为空,并且是否存在所查找的元素207 {208 pHead=pHead->next;209 }210if(pHead->element!=x)211 {212 printf("getElemAddr函数执⾏,在链表中没有找到x值\n");213return NULL;214 }215else216 {217 printf("getElemAddr函数执⾏,元素%d的地址为0x%x\n",x,&(pHead->element));218 }219return &(pHead->element);220221 }222223224/*9.修改链表中第pos个点X的值,如果修改成功,则返回1,否则返回0*/225int modifyElem(Node *pNode,int pos,elemType x)226 {227 Node *pHead;228 pHead=pNode;229int i=0;230if(NULL==pHead)231 {232 printf("modifyElem函数执⾏,链表为空\n");233return0;234 }235236if(pos<1)237 {238 printf("modifyElem函数执⾏,pos值⾮法\n");239return0;240 }241242while(pHead!= NULL)243 {244 ++i;245if(i==pos)246 {247break;248 }249 pHead=pHead->next;250 }251252if(i<pos)253 {254 printf("modifyElem函数执⾏,pos值超出链表长度\n");255return0;256 }257 pNode=pHead;258 pNode->element=x;259 printf("modifyElem函数执⾏,修改第%d点的元素为%d\n",pos,x);260261return1;262263 }264265/* 10.向单链表的表头插⼊⼀个元素 */266int insertHeadList(Node **pNode,elemType insertElem)267 {268 Node *pInsert;269 pInsert=(Node *)malloc(sizeof(Node));270if(pInsert==NULL) exit(1);271 memset(pInsert,0,sizeof(Node));272 pInsert->element=insertElem;273 pInsert->next=*pNode;274 *pNode=pInsert;275 printf("insertHeadList函数执⾏,向表头插⼊元素%d成功\n",insertElem);276return1;277 }278279/* 11.向单链表的末尾添加⼀个元素 */280int insertLastList(Node *pNode,elemType insertElem)281 {282 Node *pInsert;283 Node *pHead;284 Node *pTmp;285286 pHead=pNode;287 pTmp=pHead;288 pInsert=(Node *)malloc(sizeof(Node));289if(pInsert==NULL) exit(1);290 memset(pInsert,0,sizeof(Node));291 pInsert->element=insertElem;292 pInsert->next=NULL;293while(pHead->next!=NULL)294 {295 pHead=pHead->next;296 }297 pHead->next=pInsert;298 printf("insertLastList函数执⾏,向表尾插⼊元素%d成功!\n",insertElem);299return1;300 }301302/* 12.向单链表中第pos个结点位置插⼊元素为x的结点,若插⼊成功返回1,否则返回0*/ 303int isAddPos(Node *pNode,int pos,elemType x)304 {305 Node *pHead;306 pHead=pNode;307 Node *pTmp;308int i=0;309310if(NULL==pHead)311 {312 printf("AddPos函数执⾏,链表为空\n");313return0;314 }315316if(pos<1)317 {318 printf("AddPos函数执⾏,pos值⾮法\n");319return0;320 }321322while(pHead!=NULL)323 {324 ++i;325if(i==pos)326break;327 pHead=pHead->next;328 }329330if(i<pos)331 {332 printf("AddPos函数执⾏,pos值超出链表长度\n");333return0;334 }335336 pTmp=(Node *)malloc(sizeof(Node));337if(pTmp==NULL) exit(1);338 memset(pTmp,0,sizeof(Node));339 pTmp->next=pHead->next;340 pHead->next=pTmp;341 pTmp->element=x;342343 printf("AddPos函数执⾏成功,向节点%d后插⼊数值%d\n",pos,x); 344return1;345 }346347/* 13.向有序单链表中插⼊元素x结点,使得插⼊后仍然有序 */348int OrrderList(Node *pNode,elemType x)349 {350//注意如果此数值要排到⾏尾要修改本代码351 Node *pHead;352 pHead=pNode;353 Node *pTmp;354355if(NULL==pHead)356 {357 printf("OrrderList函数执⾏,链表为空\n");358return0;359 }360361if(x<1)362 {363 printf("OrrderList函数执⾏,x值⾮法\n");364return0;365 }366367while(pHead!=NULL)368 {369if((pHead->element)>=x)370break;371 pHead=pHead->next;372 }373374375if(pHead==NULL)376 {377 printf("OrrderList函数查找完毕,该函数中没有该值\n");378return0;379 }380381382 pTmp=(Node *)malloc(sizeof(Node));383if(pTmp==NULL) exit(1);384 memset(pTmp,0,sizeof(Node));385 pTmp->next=pHead->next;386 pHead->next=pTmp;387 pTmp->element=x;388389 printf("OrrderList函数成功插⼊数值%d\n",x);390return1;391 }392393/*14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停⽌程序运⾏*/ 394int DelHeadList(Node **pList)395 {396 Node *pHead;397 pHead=*pList;398if(pHead!=NULL)399 printf("DelHeadList函数执⾏,函数⾸元素为%d删除成功\n",pHead->element); 400else401 {402 printf("DelHeadList函数执⾏,链表为空!");403return0;404 }405 *pList=pHead->next;406return1;407 }408409/* 15.从单链表中删除表尾结点并返回它的值,若删除失败则停⽌程序运⾏ */410int DelLastList(Node *pNode)411 {412 Node *pHead;413 Node *pTmp;414415 pHead=pNode;416while(pHead->next!=NULL)417 {418 pTmp=pHead;419 pHead=pHead->next;420 }421 printf("链表尾删除元素%d成功!\n",pHead->element);422free(pHead);423 pTmp->next=NULL;424return1;425 }426427/* 16.从单链表中删除第pos个结点并返回它的值,若删除失败则停⽌程序运⾏ */ 428int DelPos(Node *pNode,int pos)429 {430 Node *pHead;431 pHead=pNode;432 Node *pTmp;433434int i=0;435436if(NULL==pHead)437 {438 printf("DelPos函数执⾏,链表为空\n");439return0;440 }441442if(pos<1)443 {444 printf("DelPos函数执⾏,pos值⾮法\n");445return0;446 }447448while(pHead!=NULL)449 {450 ++i;451if(i==pos)452break;453 pTmp=pHead;454 pHead=pHead->next;455 }456457if(i<pos)458 {459 printf("DelPos函数执⾏,pos值超出链表长度\n");460return0;461 }462 printf("DelPos函数执⾏成功,节点%d删除数值%d\n",pos,pHead->element); 463 pTmp->next=pHead->next;464free(pHead);465return1;466 }467468/* 17.从单链表中删除值为x的第⼀个结点,若删除成功则返回1,否则返回0 */469int Delx(Node **pNode,int x)470 {471 Node *pHead;472 Node *pTmp;473 pHead=*pNode;474int i=0;475476if(NULL==pHead)477 {478 printf("Delx函数执⾏,链表为空");479return0;480 }481if(x<0)482 {483 printf("Delx函数执⾏,给定值x不合法\n");484return0;485 }486while((pHead->element!=x)&&(NULL!=pHead->next))//判断链表是否为空,并且是否存在所查找的元素487 {488 ++i;489 pTmp=pHead;490 pHead=pHead->next;491 }492if(pHead->element!=x)493 {494 printf("Delx函数执⾏,在链表中没有找到x值\n");495return0;496 }497if((i==0)&&(NULL!=pHead->next))498 {499 printf("Delx函数执⾏,在链表⾸部找到此元素,此元素已经被删除\n");500 *pNode=pHead->next;501free(pHead);502return1;503 }504 printf("Delx函数执⾏,⾸个为%d元素被删除\n",x);505 pTmp->next=pHead->next;506free(pHead);507return1;508 }509510/* 18.交换2个元素的位置 */511int exchange2pos(Node *pNode,int pos1,int pos2)512 {513 Node *pHead;514int *pTmp;515int *pInsert;516int a;517int i=0;518519if(pos1<1||pos2<1)520 {521 printf("DelPos函数执⾏,pos值⾮法\n");522return0;523 }524525 pHead=pNode;526while(pHead!=NULL)527 {528 ++i;529if(i==pos1)530break;531 pHead=pHead->next;532 }533534if(i<pos1)535 {536 printf("DelPos函数执⾏,pos1值超出链表长度\n");537return0;538 }539540 pTmp=&(pHead->element);541 i=0;542 pHead=pNode;543while(pHead!=NULL)544 {545 ++i;546if(i==pos2)547break;548 pHead=pHead->next;549 }550551if(i<pos2)552 {553 printf("DelPos函数执⾏,pos2值超出链表长度\n");554return0;555 }556557 pInsert=&(pHead->element);558 a=*pTmp;559 *pTmp=*pInsert;560 *pInsert=a;561562 printf("DelPos函数执⾏,交换第%d个和第%d个pos点的值\n",pos1,pos2); 563return1;564 }565566int swap(int *p1,int *p2)567 {568int a;569if(*p1>*p2)570 {571 a=*p1;572 *p1=*p2;573 *p2=a;574 }575return0;576 }577578/* 19.将线性表进⾏冒泡排序 */579int Arrange(Node *pNode)580 {581 Node *pHead;582 pHead=pNode;583584int a=0,i,j;585586if(NULL==pHead)587 {588 printf("Arrange函数执⾏,链表为空\n");589return0;590 }591592while(pHead!=NULL)593 {594 ++a;595 pHead=pHead->next;596 }597598 pHead=pNode;599for(i=0;i<a-1;i++)600 {601for(j=1;j<a-i;j++)602 {603 swap(&(pHead->element),&(pHead->next->element));604 pHead=pHead->next;605 }606 pHead=pNode;607 }608 printf("Arrange函数执⾏,链表排序完毕!\n");609return0;610 }611612int main()613 {614 Node *pList=NULL;615int length=0;616617 elemType posElem;618619 initList(&pList);620 printList(pList);621622 pList=creatList(pList);623 printList(pList);624625 sizeList(pList);626 printList(pList);627628 isEmptyList(pList);629630631 posElem=getElement(pList,3);632 printList(pList);633634 getElemAddr(pList,5);635636 modifyElem(pList,4,1);637 printList(pList);638639 insertHeadList(&pList,5);640 printList(pList);641642 insertLastList(pList,10);643 printList(pList);644645 isAddPos(pList,4,5); 646 printList(pList);647648 OrrderList(pList,6);649 printList(pList);650651 DelHeadList(&pList); 652 printList(pList);653654 DelLastList(pList);655 printList(pList);656657 DelPos(pList,5);658 printList(pList);659660 Delx(&pList,5);661 printList(pList);662663 exchange2pos(pList,2,5); 664 printList(pList);665666 Arrange(pList);667 printList(pList);668669 clearList(pList);670return0;671 }。
c语言链表大例题

printf("插入后:");
showPointLink(*h);
}
POINT *revangePointLink(POINT *h)
{
POINT *p, *q;
printf("逆序前:");
showPointLink(h);
if(h)
{
p = h;
h = h->next;
p->next = NULL;
choose = 0;
else
choose -= '0';
if(choose == 0)
{
printf("\n输入错误!");
printf("\n请重新选择(1-7)");
getch();
}
}
return choose;
}
void showMenu(void)
{
system("cls");
printf("\n\n屏幕上的点点的管理信息系统\n");
printf("请输入一个点的两个坐标");
printf("任意坐标值为0,则表示输入结束\n");
scanf("%d%d", &x, &y); //先从键盘输入一对坐标
while(x && y) //只要有一个为0loc(sizeof(POINT));
void showPointLink(POINT *head);
void showOnePoint(POINT);
void destroyLink(POINT *head);
c++链表范例

int o;
public:
Cylider()
{
cout<<"请输入圆柱体的底边半径和高:";
cin>>r>>h;
o=6;
}
Cylider(int rr,int hh)
{
r=rr;
h=hh;
o=6;
}
void showData()
{
private:
int a;//长
int b;//宽
int o;
public:
Rectangle()
{
cout<<"请输入矩形的长和宽:";
cin>>a>>b;
o=3;
}
Rectangle(int aa,int bb)
{
a=aa;
b=bb;
o=4;
}
Triangle(int aa,int bb)
{
a=aa;
b=bb;
o=4;
}
void showData()
{
cout<<"三角形:"<<endl;
cout<<"底边长为:"<<a<<endl;
cout<<"高为:"<<b<<endl;
{
cout<<"请输入球的半径:";
cin>>r;
o=5;
}
链表生活中举例子

链表生活中举例子链表是一种常见的数据结构,在生活中也有很多类似的例子可以来解释。
下面是符合要求的十个例子:1. 电线路:电线路可以看作是一条链表,电流从一端流向另一端。
每个电线都连接在一起,形成一个链式结构。
如果其中一个电线断开了,电流就无法顺利流通,就像链表中的节点断开一样。
2. 银行排队取款:在银行排队取款时,每个人按照先后顺序站在一起,形成一个队列。
当某个人取完款后,后面的人依次向前移动一个位置,就像链表中的节点删除和插入操作一样。
3. 图书馆书架:图书馆的书架上摆放着很多书籍,每本书都有自己的位置。
当有新书到达时,会被插入到合适的位置上,就像链表中的节点插入操作一样。
4. 手链:手链由一串串的珠子或者链节组成,每个珠子或链节都连接在一起。
当手链被拉伸时,每个珠子或链节都会依次移动,就像链表中的节点遍历一样。
5. 网络游戏中的队伍:在网络游戏中,玩家可以组队进行战斗。
每个队友按照先后顺序排列,形成一个队伍。
当队伍中有人离开或加入时,队伍的成员顺序会发生变化,就像链表中的节点删除和插入操作一样。
6. 交通信号灯:交通信号灯由红、黄、绿三个灯组成,每个灯都有自己的状态。
当信号灯的状态发生变化时,车辆会根据不同的灯光信号做出相应的动作,就像链表中的节点更新操作一样。
7. 餐厅的等候队列:在繁忙的餐厅,人们会排队等候就餐。
每个人按照先后顺序排列,形成一个等候队列。
当有桌子空出来时,排在队列最前面的人会被叫号,就像链表中的节点删除操作一样。
8. 航班座位预订系统:在航班座位预订系统中,每个座位都有自己的状态(已预订、空闲)。
当有人预订座位或取消预订时,座位的状态会发生变化,就像链表中的节点更新操作一样。
9. 电影院的座位安排:在电影院观影时,每个座位都有自己的位置。
当有人购买电影票时,会选择一个座位坐下,就像链表中的节点插入操作一样。
10. 城市地铁线路:城市地铁线路将不同的地铁站连接在一起,形成一个链式结构。
C语言链表实现商品库存管理系统

C语⾔链表实现商品库存管理系统本⽂实例为⼤家分享了C语⾔链表实现商品库存管理系统的具体代码,供⼤家参考,具体内容如下代码:12345678910111213141516171819202122 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#include <stdio.h>#include <stdlib.h>#include <string.h>//定义⼀个商品结构体typedef struct sp{char no[12]; //商品编号char name[40]; //名称int workload; //库存量struct sp *next; //指向下⼀节点的指针} SP;//函数声明放在这⾥void ListCreate(SP *L, int n); //创建商品链表节点void LIstSearch(SP *L); //查找商品信息void ListModify(SP *L); //修改商品信息void ListInsert(SP *L); //插⼊商品信息void ListDelete(SP *L); //删除商品信息void Input(SP *p, int i); //输⼊商品信息void SumSp(SP *L); //统计商品的库存总量void Sort(SP *L); //对每类商品的库存量进⾏排名void Menu(); //考试报名管理系统的菜单//商品库存管理系统的主函数⼊⼝int main(){int item, n; //item⽤于接收输⼊的命令,n⽤于接收输⼊的商品⼈数 SP *L = NULL; //初始化⼀个头节点L = (SP *)malloc(sizeof(SP)); //为头节点开辟内存空间L->next = NULL; //将头节点的指针域置空do{Menu(); //菜单printf("请输⼊相应的数字,进⾏相应的操作:\n");scanf("%d", &item);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 system("cls");switch(item){case1:printf("请输⼊您要录⼊的商品数⽬:");scanf("%d", &n);ListCreate(L, n);getchar();printf("\n请按任意键返回主菜单\n");getchar();system("cls");break;case2:LIstSearch(L); //查找商品信息getchar();printf("\n请按任意键返回主菜单\n");getchar();system("cls");break;case3:ListModify(L); //修改商品库存信息getchar();printf("\n请按任意键返回主菜单\n");getchar();system("cls");break;case4:ListDelete(L); //删除商品信息getchar();printf("\n请按任意键返回主菜单\n");getchar();system("cls");break;case5:ListInsert(L); //插⼊商品信息getchar();printf("\n请按任意键返回主菜单\n");getchar();system("cls");break;case6:SumSp(L);getchar();printf("\n请按任意键返回主菜单\n");getchar();system("cls");break;case7:Sort(L);getchar();printf("\n请按任意键返回主菜单\n");getchar();system("cls");break;case0: //退出商品库存管理系统printf("即将退出商品库存管理系统.....");exit(0);default:printf("您输⼊的指令不正确,请重新输⼊"); }printf("\n\n");} while(item);return0;}//创建链表,将新⽣成的节点插⼊到链表的表头void ListCreate(SP *L, int n){int i;for(i = 0; i < n; i++){SP *p;//将新⽣成的节点插⼊到链表中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 170 171 172 173 174 175 176 177 178 p = NULL;p = (SP *)malloc(sizeof(SP));Input(p, i);p->next = L->next;L->next = p;}printf("录⼊成功!");}//查找商品库存量void LIstSearch(SP *L){char n[40];SP *p = L->next;if(p == NULL)printf("数据为空,⽆法查找!");else{printf("请输⼊您要查找的商品名称:");scanf("%s", n);while(strcmp(p->name, n) != 0){p = p->next;if(p == NULL){printf("没有找到相关信息\n");return;}}printf("%s的库存量为%d\n",p->name,p->workload);}}//修改商品的库存量void ListModify(SP *L){int a;char nam[40];SP *p = L->next;if(p == NULL)printf("数据为空,⽆法修改!");else{printf("请输⼊您修改的商品名称:");scanf("%s",nam);while(strcmp(p->name, nam) != 0){p = p->next;if(p == NULL){printf("没有找到相关信息\n");return;}}printf("请输⼊您修改后的库存量:");scanf("%d",&p->workload);printf("修改成功");}}//删除商品信息void ListDelete(SP *L){char n[40];SP *p = L->next, *pre = L; //定义p指针指向头节点的指向,定义pre指向头节点,pre始终指向p的前驱节点 if(p == NULL)printf("数据为空,⽆法删除!");else{printf("请输⼊您要删除的商品名称:");scanf("%s", n);while(strcmp(p->name, n) != 0)180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 p = pre->next;if(p == NULL){printf("没有找到相关信息,⽆法删除\n"); return;}}pre->next = p->next;free(p);printf("删除成功");}}//插⼊商品库存的相关信息void ListInsert(SP *L){SP *s = NULL; //⽣成⼀个新节点ss = (SP *)malloc(sizeof(SP));printf("请输⼊商品的商品编号:");scanf("%s", s->no);printf("请输⼊商品的名称:");scanf("%s", s->name);printf("请输⼊商品的库存量:");scanf("%d", &s->workload);s->next = L->next;L->next = s;printf("插⼊成功!");}//统计商品的库存总量void SumSp(SP *L){int sum=0;SP *p=L->next;while(p!=NULL){sum+=p->workload;p=p->next;}printf("商品的库存总量为%d\n",sum);}//对每类商品的库存量进⾏排名void Sort(SP *L){SP *p,*q,*tail,*l;tail=NULL;while((L->next->next) != tail){p = L;q = L->next;while(q->next != tail){if((q->workload) > (q->next->workload)){p->next = q->next;q->next = q->next->next;p->next->next = q;q = p->next;}q = q->next;p = p->next;}tail = q;}printf("商品库存量从⼩到⼤结果如下:\n");l=L->next;while(l!=NULL){if(l->next!=NULL){printf("%s(%d)->",l->name,l->workload); l=l->next;242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293{ printf("%s(%d)",l->name,l->workload); l=l->next;}}}//输⼊商品库存的相关信息void Input(SP *p, int i){ printf("请输⼊第%d 个商品的商品编号:", i + 1);scanf("%s", p->no);printf("请输⼊第%d 个商品的名称:", i + 1); scanf("%s", p->name); printf("请输⼊第%d 个商品的库存量:", i + 1); scanf("%d", &p->workload);}//商品库存管理系统的菜单void Menu(){ printf("\n\n"); printf("\t\t\t===================商品库存管理系统======================\n"); printf("\t\t\t* 作者:XXX 班级:XXXXXXXXXXX 学号:XXXXXXXXXX *\n"); printf("\t\t\t* *\n");printf("\t\t\t* 1>. 录⼊商品库存信息 *\n"); printf("\t\t\t* 2>. 查找某个商品的库存量 *\n"); printf("\t\t\t* 3>. 修改某个商品的库存量 *\n");printf("\t\t\t* 4>. 删除某个商品库存相关信息 *\n");printf("\t\t\t* 5>. 插⼊某个商品的相关信息 *\n");printf("\t\t\t* 6>. 统计商品的库存总量 *\n"); printf("\t\t\t* 7>. 对每类商品的库存量排名 *\n"); printf("\t\t\t* 0>. 退出管理系统 *\n"); printf("\t\t\t* 欢迎使⽤本系统!*\n");printf("\t\t\t========================================================\n");printf("\t\t\t 输⼊选项,按回车进⼊选项: \n");}部分运⾏结果截图以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
常见链表示意图

(2)空表
L ─→ ∧ // ∧ 表头结点
有:L->next==L->prior==NULL
四.双向循环链 (1)空表
L ─→ //
有:L->next==L->prior==L
表头结点
(2)非空表
prior data next L ─→ // ─→ a1 ─→ ... ─→ an 表头结点 p 尾结点
有:H->next≠H, H≠NULL (2) 带表头结点的空循环单链表
H -→ // 头指针 头结点
有:H->next==H, H≠NULL
2.只设尾指针的循环链表
(1)非空表
/// → a1 → a2 表头结点 首结点 →...→ an 尾结点 tail 尾指针
有:tail指向表尾结点 tail->data==an tail->next 指向表头结点 tail->next->next指向首结点 tail->next->next->data==a1
(2) 空表 /// 表头结点 tail 尾指针
有:tail->next==tail
三.双向链表的一般形式 (1)非空表
prior data next L ─→ // ─→ ∧ a1 ─→ 表头结点 首结点 a2 ─→ ...─→ an ∧ 尾结点
有:L为头指针,L指向表头结点,L->next指向首结点 L->next->data==a1 L->prior指向尾结点, L->prior->data==an L->next->prior== L->prior->next==NULL
一.单链表的一般形式: (1)不带表头结点的单链表: data next head ---→ a1 ---→ a2 --→ ...--→ an
C#数据结构之单链表(LinkList)实例详解

C#数据结构之单链表(LinkList)实例详解本⽂实例讲述了C#数据结构之单链表(LinkList)实现⽅法。
分享给⼤家供⼤家参考,具体如下:这⾥我们来看下“单链表(LinkList)”。
在上⼀篇《》的最后,我们指出了:顺序表要求开辟⼀组连续的内存空间,⽽且插⼊/删除元素时,为了保证元素的顺序性,必须对后⾯的元素进⾏移动。
如果你的应⽤中需要频繁对元素进⾏插⼊/删除,那么开销会很⼤。
⽽链表结构正好相反,先来看下结构:每个元素⾄少具有⼆个属性:data和next。
data⽤来存放数据,⽽next⽤来指出它后⾯的元素是谁(有点“指针”的意思)。
链表中的元素,通常也称为节点Node,下⾯是泛型版本的Node.csnamespace 线性表{public class Node<T>{private T data;private Node<T> next;public Node(T val, Node<T> p){data = val;next = p;}public Node(Node<T> p){next = p;}public Node(T val){data = val;next = null;}public Node(){data = default(T);next = null;}public T Data{get { return data; }set { data = value; }}public Node<T> Next{get { return next; }set { next = value; }}}}链表在存储上并不要求所有元素按顺序存储,因为⽤节点的next就能找到下⼀个节点,这好象⼀根“⽤珠⼦串成的链⼦”,要找到其中的某⼀颗珠⼦,只要从第⼀颗节点(通常称为Head节点)开始,不断根据next指向找到下⼀个,直到找到需要的节点为⽌。
第二章 指针与链表

第二章指针与链表一、静态存贮和动态存贮1、静态存贮程序中的变量一经说明,计算机操作系统就会在内存空间中分配相应的存贮单元,其中变量名是存贮单元的地址,而变量的值是存贮单元的内容,且该存贮单元自始至终都被该变量所占用,直到程序结束。
如果变量是局部变量,那么在它的作用域内,一经说明也占有一定的存贮单元,直到退出其作用域为止。
这样的变量,在程序执行过程中,不能随时使用随时分配存贮空间,也不能在程序执行的过程中,释放这些空间。
也就是说,一旦给这些变量分配存贮空间,无论程序是否还需要使用,它们都要占用一定的存贮空间,以便给用户存贮数据。
我们称具有这样特点的存贮为静态存贮,它所对应的变量称为静态变量。
如字符类型、数组类型、记录类型等。
这类变量的优点是存贮方便,查找容易,可以通过一个简单的公式随机存取表中的任一元素,逻辑关系上相邻的两个元素在物理位置上也是相邻的,很容易找到前趋与后继元素;缺点是在线性表的长度不确定时,必须分配足够大的存储空间,经常浪费了宝贵的存储资源;而线性表的容量一经定义确定后就难以扩充;在插入和删除线性表的元素时,需要移动大量的元素,时间效率也比较差。
2、动态存贮在程序执行过程中,通过向操作系统申请存贮空间或释放存贮空间的命令,达到动态管理计算机的存贮空间,以保证存贮空间的充分利用。
存贮空间可以随时申请、随时释放,这样的存贮方式称为动态存贮,其变量称为动态变量。
指针变量即为动态变量。
动态存储所需要的空间可以是不连续的,这样有利于充分利用零散的小空间。
但缺无法用O(1)的时间实现存取了。
如何用这些零散的空间存储数组这些大规模数据呢?如何表示这些数据之间的逻辑关系呢?为了表示这些物理存储单元之间的逻辑关系,对于每个数据元素来说,除了要存储它本身的信息(数据域data)外,还要存储它的直接后继元素的存储位置(指针域,一般用link 或next 表示)。
我们往往把这两部分信息合在一起称为一个“结点node”。
第三章 链表

第三章 链表
第三章 链表
知识点
单链表的结点形式、组织方法和特点 单链表的基本运算和相应的算法 循环链表的组织方法和基本运算算法 双链表的结点形式、组织方法和特点 双链表的基本运算和相应的算法 顺序表与链表比较,各自的优、缺点 链表的应用 用十字链表表示稀疏矩阵
第三章 链表
难点
双链表插入、删除运算的算法 利用链接结构的特点设计有效算法,解决与链表结 构相关的应用问题
第三章 链表
算法分析
此算法的关键是while循环语句,开始时p 指针指向头结点,每一循环都修改指针 值,让它指向下一个结点,同时将计数 链表长度的变量count加1。 这样每循环一次就向后推移一个结点, 直到p所指结点*p的链域值为NULL为止。 空指针NULL起标志的作用,若无此标志, 尾结点链域的值为“无定义”,上述算 法中的while语句在做最后一次判断时将 出现“运行错”,这是应予避免的。
第三章 链表
3.3.2 链队列
链队列需要两个指针,其中队首指针front指向 链表的表头,队尾指针rear指向链表的表尾。 一般插入时只修改队尾结点的指针和队尾指针 rear,删除时只修改队首指针front。当将第一个 元素插入空队列或删除了最后一个元素而使队 列为空时,front和rear都需要修改。 front rear
当需要从单链表上删除结点时,就要通过删 除运算来完成。 删除单链表上一个其值为x的结点的主要操作 是:
1) 用遍历的方法在单链表上找到该结点; 2) 从单链表上删除该结点。
欲从单链表上删除一个结点,需修改该结点 的前一个结点的指针,如下面的图所示。
第三章 链表
q head
p x ∧
假设指针q指向待删除结点的前一个结点,指 针p指向要删除的结点,删除该结点的操作如 下:将该结点的前一个结点*q的链域指向*p 的后继结点(即q->next=p->next)。
循环链表和双向链表

b.head->next = NULL; //此时,b中已只剩第一个结点(头), 为其置空表标志
return k; //返回结果链表中的元素个数
}
为了进一步说明上述程序,举一个程序运行的例子, 其各次循环的运行结果如图5-6所示
p
7 0 3 2 -9 3 1 5
^
(a)A(x)=p5(x)=7+3x2-9x3+x5,进入循环前
该程序不断比较A链和B链中的一对结点的指数值 (称其为当前结点)。开始时A链和B链中参加比较
的当前结点都是它们的第一个元素。
主循环while结束后,可能出现下列3种情况:①A
链和B链同时被处理完;②只有B链处理完;③只有A
链处理完。 对第一和第二种情况,不需要“善后”处理。对第 三种情况,B链中尚有未被处理完的结点,需将其挂 接在结果链的尾部。循环外的“if(q 不为空)将q
p = p->next; } // if (x==0) … else … q0 = q; q = q->next; delete q0; //将q所指结点从表中删除并释放,令q新指向原所 指的下一个 } // if (p->exp > q->exp ) … else … } //while if (q!=NULL) p0->next = q;
为处理方便,在具体存储多项式时,我们规定:
所存储的多项式已约简,即已合并同类项,不 保留0系数项,各项按指数的升序排列。 (二)多项式加法实现—直接操作链表 为操作方便,我采用带头结点的非循环链表,下面给 出一个例子说明多项式的这种表示法。
设有一个一元5次多项式: P5(x)=7+3x-9x3+x5
linux 链表 实例

linux 链表实例一、链表概述链表是一种常见的数据结构,主要由一系列节点组成。
每个节点包含两个部分:数据域和指针域。
数据域用于存储数据,指针域用于存储下一个节点的地址。
链表的头部和尾部分别用头指针和尾指针表示。
链表的头指针通常指向第一个节点,尾指针指向最后一个节点或者NULL。
二、链表节点结构体定义在Linux 系统中,我们可以使用结构体来定义链表节点。
以下是一个简单的链表节点结构体定义:```ctypedef struct Node {int data; // 数据域,存储节点数据struct Node *next; // 指针域,指向下一个节点} Node;```三、链表操作实例3.1 链表创建创建链表的常见方法是使用循环逐个初始化节点。
以下是一个创建链表的示例:```code *create_list(int num) {Node *head = NULL, *tail = NULL;for (int i = 0; i < num; i++) {Node *new_node = (Node *) malloc(sizeof(Node));new_node->data = i + 1;new_node->next = NULL;if (head == NULL) {head = new_node;tail = new_node;} else {tail->next = new_node;tail = new_node;}}return head;}```3.2 链表插入在链表的尾部插入节点,以下是一个插入节点的示例:```cvoid insert_node(Node **head, int data) {Node *new_node = (Node *) malloc(sizeof(Node));new_node->data = data;new_node->next = NULL;if (*head == NULL) {*head = new_node;} else {Node *temp = *head;while (temp->next != NULL) {temp = temp->next;}temp->next = new_node;}}```3.3 链表删除根据节点值删除链表中的节点,以下是一个删除节点的示例:```cvoid delete_node(Node **head, int data) {if (*head == NULL) {return;}Node *temp = *head;while (temp->next != NULL && temp->next->data != data) { temp = temp->next;if (temp->next == NULL) {return;}if (temp->next->next == NULL) {free(temp->next);temp->next = NULL;} else {Node *next_node = temp->next->next;free(temp->next);temp->next = next_node;}}```3.4 链表遍历以下是一个遍历链表的示例:```cvoid traverse_list(Node *head) {Node *temp = head;while (temp != NULL) {printf("%d -> ", temp->data);temp = temp->next;printf("NULL");}```四、总结与拓展本文介绍了Linux 系统中链表的基本操作,包括链表的创建、插入、删除和遍历。
c语言1链表例题

以下是一个简单的 C 语言链表示例题目:题目描述:给定一个整数数组,请将数组中的元素按逆序输出,并返回逆序输出后的数组。
示例:输入:[1,2,3,4,5]输出:[5,4,3,2,1]解题思路:可以使用链表来实现逆序输出数组。
具体步骤如下:1.定义一个链表结构体,包含一个整数和一个指向下一个节点的指针。
2.遍历给定的整数数组,将每个元素作为链表的节点插入到链表中。
3.定义一个指针指向链表的头节点,从头节点开始遍历链表,依次输出每个节点的值。
4.返回输出的结果数组。
代码如下:c复制代码#include<stdio.h>#include<stdlib.h>typedef struct ListNode {int val;struct ListNode *next;} ListNode;int* reverseList(int* head_ref, int size) {ListNode *p = (ListNode*)malloc(sizeof(ListNode)); // 创建头节点p->val = 0; // 头节点值为0,可以根据实际情况修改p->next = NULL; // 头节点指向空,表示链表为空ListNode *q = p; // q指向头节点,作为输出结果的起始位置for (int i = 1; i <= size; i++) { // 从第二个元素开始遍历数组ListNode *tmp = (ListNode*)malloc(sizeof(ListNode)); // 创建新节点tmp->val = head_ref[i]; // 将当前元素赋值给新节点tmp->next = NULL; // 新节点指向空,表示新节点为链表的最后一个节点q->next = tmp; // q指向的节点的下一个节点指向新节点,完成插入操作q = tmp; // q指向新节点,作为输出结果的下一个位置}int *res = (int*)malloc(sizeof(int) * size); // 创建结果数组int cnt = 0; // 结果数组计数器while (p->next != NULL) { // 遍历链表,依次输出每个节点的值到结果数组中res[cnt++] = p->next->val;p = p->next; // p向后移动到下一个节点}free(p); // 释放头节点内存空间return res; // 返回结果数组}。
链表在现实世界中的应用

链表在现实世界中的应用链表是一种常用的数据结构,它由一系列节点组成,每个节点包含两个部分:数据和指向下一个节点的指针。
链表在计算机科学中被广泛应用于各种场景,而在现实生活中,我们也可以找到许多应用链表的例子:1. 文件系统:在计算机的文件系统中,目录的结构就是一个链表。
每个目录(文件夹)都包含多个文件和子目录。
子目录可以包含更多的文件和子目录,形成了一个层次结构。
这种结构可以用链表来表示,其中每个节点都代表一个目录,节点中的数据部分包含目录的名称,而指针部分指向下一个目录。
2. 网页浏览器的历史记录:当你在网页浏览器中浏览网页时,浏览器的历史记录功能使用链表来记录你访问过的网页。
新访问的网页会被添加到链表的头部,而链表的尾部是你最早访问的网页。
这样,你就可以方便地向前翻页,查看你之前访问过的网页。
3. 电话簿:在电话簿应用中,联系人信息被存储在一个链表中。
每个节点都代表一个联系人,节点中的数据部分包含联系人的姓名和电话号码,指针部分指向下一个联系人。
通过这种方式,你可以方便地按照字母顺序或其他方式浏览联系人列表。
4. 音乐播放器:在许多音乐播放器中,歌曲的播放列表使用链表来组织。
用户可以添加、删除和编辑播放列表,这些操作都可以在链表上方便地实现。
5. 操作系统:在操作系统的进程管理中,链表用于存储正在运行的进程。
每个节点代表一个进程,节点中的数据部分包含进程的状态和相关信息,指针部分指向下一个进程。
操作系统需要经常对链表进行操作,如创建新进程、删除进程和调度进程等。
以上只是链表在现实世界中的一些应用示例,实际上链表的应用非常广泛,它是一种非常有用的数据结构。
单链表应用实例及代码实现

单链表应⽤实例及代码实现问题:使⽤带 head 头的单向链表实现 –英雄列表管理完成对英雄⼈物的增删改查操作。
⾸先准备⼀个hero类:1. class hero {2. private int num;//序号(排名)3. private String name;//名称4. private String nikname;//别名5. private hero next;//指向下⼀个6.7. public hero(int num, String name, String nikname) { ... } //构造器8.9. public int getNum() { ... }10. public void setNum(int num) { ... }11. public String getName() { ... }12. public void setName(String name) { ... }13. public String getNikname() { ... }14. public void setNikname(String nikname) { ... }15. public hero getNext() { ... }16. public void setNext(hero next) { ... }17.18. @Override19. public String toString() { ... } //为了显⽰⽅便显⽰重写tostring20. }1) 第⼀种⽅法:在添加英雄时,直接添加到链表的尾部(add())思路分析: 添加(创建) 1、先创建⼀个head头节点(①不存放具体数据,②作⽤就是表⽰单链表头next)private hero head = new hero(-1, "", ""); //先初始化⼀个头节点,头节点不能动,不存放具体数据 2、之后我们每添加⼀个节点,就直接加⼊到链表的最后 遍历 1、通过⼀个辅助变量遍历,帮助遍历整个链表2) 第⼆种⽅式在添加英雄时,根据排名将英雄插⼊到指定位置(如果有这个排名,则添加失败,并给出提⽰) 思路分析: 1、⾸先找到新添加的节点的位置,是通过辅助变量,通过遍历来搞定 2、新的节点.next=temp.next (temp为插⼊后的新节点的前⼀个节点) 3、将temp.next=新的节点3) 修改节点 思路分析: 1、先找到该节点,通过遍历 2、 = ; temp.nickname= newHero.nickname;4) 删除节点(delete()) 思路分析: 1、先找到需要删除的这个节点的前⼀个节点temp 2、 temp.next=temp.next.next 3、删除的节点,将不会有其他引⽤,会被GC掉单链表代码实现:1. public class singlelinkedlist {2. //先初始化⼀个头节点,头节点不能动,不存放具体数据3. private hero head = new hero(-1, "", "");4.5. //添加节点到单向链表6. /**7. * 思路:当不考虑标编号顺序时8. * 1、找到当前链表的最后节点9. * 2、将最后这个节点的next指向新的节点10. */11. public void add(hero h) {12. //因为head节点不能动,因此我们需要⼀个辅助变量temp13. hero temp = head;14. //遍历链表,找到最后⼀个节点15. while (true) {16. if (temp.getNext() == null) {17. break;19. //如果没有到最后,将temp后移20. temp = temp.getNext();21. }22. //当退出while循环时,temp就指向了链表的最后23. //将最后这个节点的next指向新的节点24. temp.setNext(h);25. }26.27. //第⼆种⽅式在添加英雄时,根据排名将英雄插⼊到指定位置28. //(如果有这个排名,则添加失败,并给出提⽰)29. public void addByOrder(hero h) {30. //因为头节点不能动,因此我们仍然通过⼀个辅助指针(变量)来帮助找到添加的位置31. //因为单链表,因为我们找的temp是位于添加位置的前⼀个节点,否则插⼊不了32. hero temp = head;33. boolean flag = false;// flag 标志添加的编号是否存在,默认为 false34. while (true) {35. if (temp.getNext() == null) {//说明 temp 已经在链表的最后36. break;37. } else if (temp.getNext().getNum() > h.getNum()) {//位置找到,就在 temp 的后⾯插⼊38. break;39. } else if (temp.getNext().getNum() == h.getNum()) {//说明希望添加的 heroNode 的编号已然存在40. flag = true;41. break;42. }43. temp = temp.getNext();//后移,遍历当前链表44. }45. if (flag) { //不能添加,说明编号存在46. System.out.println("添加的序号为" + h.getNum() + "的英雄序号已经存在,添加失败。