指针与链表练习
C程序设计(链表)习题与答案
一、单选题1、链表不具有的特点是()。
A.不必事先估计存储空间B.插入、删除不需要移动元素C.可随机访问任一元素D.所需空间与线性表长度成正比正确答案:C2、链接存储的存储结构所占存储空间()。
A.分两部分,一部分存放结点值,另一部分存放结点所占单元数B.只有一部分,存放结点值C.分两部分,一部分存放结点值,另一部分存放表示结点间关系的指针D.只有一部分,存储表示结点间关系的指针正确答案:C3、链表是一种采用()存储结构存储的线性表。
A.网状B.星式C.链式D.顺序正确答案:C4、有以下结构体说明和变量的定义,且指针p指向变量a,指针q指向变量b,则不能把结点b连接到结点a之后的语句是()。
struct node {char data;struct node *next;} a,b,*p=&a,*q=&b;A.(*p).next=q;B.p.next=&b;C.a.next=q;D.p->next=&b;正确答案:B5、下面程序执行后的输出结果是()。
#include <stdio.h>#include <stdlib.h>struct NODE {int num; struct NODE *next;};int main(){ struct NODE *p,*q,*r;p=(struct NODE*)malloc(sizeof(struct NODE));q=(struct NODE*)malloc(sizeof(struct NODE));r=(struct NODE*)malloc(sizeof(struct NODE));p->num=10; q->num=20; r->num=30;p->next=q;q->next=r;printf("%d",p->num+q->next->num);return 0;}A.30B.40C.10D.20正确答案:B6、下面程序执行后的输出结果是()。
链表的经典习题
链表的经典习题练习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();}}难点:内部类和外部类的构造函数都需要对相应属性做初始化。
数据结构单元4练习参考答案
单元测验4一.判断题(下列各题,正确的请在前面的括号内打√;错误的打╳)(√)(1)队列是限制在两端进行操作的线性表。
(√)(2)判断顺序队列为空的标准是头指针和尾指针都指向同一个结点。
(×)(3)在链队列上做出队操作时,会改变front指针的值。
(√)(4)在循环队列中,若尾指针rear大于头指针front,其元素个数为rear- front。
(×)(5)在单向循环链表中,若头指针为h,那么p所指结点为尾结点的条件是p=h。
(√)(6)链队列在一定范围内不会出现队满的情况。
(×)(7)在循环链队列中无溢出现象。
(×)(8)栈和队列都是顺序存储的线性结构。
(×)(9)在队列中允许删除的一端称为队尾。
(×)(10)顺序队和循环队关于队满和队空的判断条件是一样的。
二.填空题(1)在队列中存取数据应遵循的原则是先进先出。
(2)队列是被限定为只能在表的一端进行插入运算,在表的另一端进行删除运算的线性表。
(3)在队列中,允许插入的一端称为队尾。
(4)在队列中,允许删除的一端称为队首(或队头)。
(5)队列在进行出队操作时,首先要判断队列是否为空。
(6)顺序队列在进行入队操作时,首先要判断队列是否为满。
(7)顺序队列初始化后,front=rear= -1 。
(8)解决顺序队列“假溢出”的方法是采用循环队列。
(9)循环队列的队首指针为front,队尾指针为rear,则队空的条件为 front == rear 。
(10)链队列LQ为空时,LQ->front->next= NULL 。
(11)设长度为n的链队列用单循环链表表示,若只设头指针,则入队操作的时间复杂度为 O(n)。
(12)设长度为n的链队列用单循环链表表示,若只设尾指针,则出队操作的时间复杂度为 0(1)。
(13)在一个链队列中,若队首指针与队尾指针的值相同,则表示该队列为空。
(14)设循环队列的头指针front指向队首元素,尾指针rear指向队尾元素后的一个空闲元素,队列的最大空间为MAXLEN,则队满标志为:front==(rear+1)%MAXLEN 。
第08章指针和链表真题
历年真题(指针)一、2003年1月10.以下定义语句中,错误的是(A ) int a{}={1,2}; (B ) char *a[3];(C ) char s[10]=”text ”; (D ) int n=5,a[n];14.下列语句执行后的结果是 。
y=5;p=&y;x=*p++;(A )x=5,y=5 (B )x=5,y=6(C )x=6,y=5 (D )x=6,y=615. 执行下面的语句后,表达式*(p[0]+1)+**(q+2)的值为 。
int a[]={5,4,3,2,1};*p[]={a+3,a+2,a+1,a};**q=p;(A )8 (B )7 (C )6 (D )516. 经过下面的语句int I,a[10],*p;定义后,下列语句中合法的是 。
(A )p=100; (B )p=a[5];(C )p=a+2; (D )p=&(i+2);29. 有如下程序main(){ char ch[2][5]={“6937”, “8254”},*p[2];int i,j,s=0;for(i=0;i<2;i++) p[i]=ch[i];for(i=0;i<2;i++)for(j=0;p[i][j]>‟0‟;j+=2)s=10*s+p[i][j]-…0‟;printf(“%d\n ”,s);}该程序的输出结果是 。
(A )69825 (B )63825 (C )6385 (D )69382530. 若建立如下图所示的单项链表结构date nextheadS在该链表结构中,指针p ,s 分别指向图中所示节点,则不能将s 所指的节点插入链表末尾仍构成单向链表的语句组是 。
(A ) p=p->next;s->next=p;p->next=s;(B)p=p->next;s->next=p->next;p->next=s;(C)s->next=NULL;p =p->next;p->next=s;(D)p=(*p).next;(*s).next=(*p).next; (*p).next=s;试卷二试题二:把下列程序补充完整实现两个字符串的比较,即自己写个strcmp函数,函数原型为:int strcmp(char *p1,char *p2)设p1指向字符串s1,p2指向字符串s2,要求:当s1=s2时,返回值为0。
数据结构链表习题
练习题:1)在一个单链表head中,若要在指针p所指结点后插入一个q指针所指结点,则执行_____。
A. p->next=q->next; q->next=p;B. q->next=p->next; p=q;C. p->next=q->next; p->next=q;D. q->next=p->next; p->next=q;2)在一个单链表head中,若要删除指针p所指结点的后继结点,则执行_____。
A. p=p->next;free(p);B. p->next=p->next->next; free(p);C. q= p->next ;q->next=p->next; free(q);D. q=p->next; p->next=q->next ;free(q);3)若长度为n的线性表(a1, a2,…, a n)采用顺序存储,在第i个位置上插入一个新元素,需要依次向后移动个数据元素。
A n-iB n-i-1C n-i+1D n+i3)完成下列打印带头单链表的各元素的算法.typedef struct List{ int data;struct List *next;} Node,*Link;void printlk(Link head){Link p=head->next;{ printf(“%d\n”,p->data);}4)已知无头单链表A和B表示两个集合,本算法实现A=A-B (集合的补运算)。
typedef struct node {int data;struct node *next;}lnode;void setminus(lnode *&A,lnode *B)while (B!=NULL){p=A;}A=A->next;}5)下列算法创建n个元素的带头单链表.typedef struct lnode { int data;struct lnode *next;}lnode,*linklist ;void create(linklist &head, int n){linklist p; int i;head=(linklist)malloc(sizeof(lnode));A head->next=nullfor(i=n;i>0;i--){p =(linklist)malloc(sizeof(lnode));scanf(“%d”,&p->data);B p->next=head->nextC head->next=p}}。
课堂练习题---链表
1、设单链表中指针P指着结点A ,若要删除A之后结点(若存在),则需要修改指针的操作为()。
A. p->next=p->next->nextB. p=p->nextC. p=p->next->nextD. P->next=p8.从一个具有n个节点的单链表中查找其值等于x结点时,在查找成功的情况下,需平均比较个结点。
A. nB. n/2C. (n-1)/2D. (n+1)/22.在一个单链表中,已知*q结点是*p结点的前驱结点,若在*q和*p之间插入*s 结点,则执行。
A. s->next=p->next; p->next=s;B. p->next=s->next; s->next=p;C. q->next=s; s->next=p;D. p->next=s; s->next=q;3.线性表采用链式存储时,其地址。
A. 必须是连续的B.部分地址必须是连续的C. 一定是不连续的D. 连续与否均可以4.设单链表中指针p指着结点(数据域为m),指针f指着将要插入的新结点(数据域为x),当x插在结点m之后时,只要先修改后修改p->link=f即可。
A. f->link=p;B. f->link=p->link;C. p->link=f->link;D. f=nil;5.在双向链表存储结构中,删除p所指的结点时需修改指针。
A. ((p->rlink) ->rlink) ->link=p; p->rlink=(p->rlink) ->rlink;B. (p->llink) ->rlink=p->rlink; (p->rlink) ->llink=p->llink;C. p->llink=(p->llink) ->llink; ((p->llink) ->llink) ->rlink=p;D. ((p->llink) ->llink) ->rlink=p; p->llink=(p->llink) ->llink;6.在双向链表存储结构中,删除p所指的结点的前趋结点(若存在)时需修改指针。
链表
第二章习题填空题1.当线性表的元素总数基本稳定,且很少进行插入和删除操作,但要求以最快的速度存取线性表中的元素时,应采用_______存储结构。
2.线性表L=(a1,a2,…,an)用数组表示,假定删除表中任一元素的概率相同,则删除一个元素平均需要移动元素的个数是________。
3.设单链表的结点结构为(data,next),next为指针域,已知指针px指向单链表中data为x的结点,指针py指向data为y的新结点 , 若将结点y插入结点x之后,则需要执行以下语句:_______; ______;4.在一个长度为n的顺序表中第i个元素(1<=i<=n)之前插入一个元素时,需向后移动________个元素。
5.在单链表中设置头结点的作用是________。
6.对于一个具有n个结点的单链表,在已知的结点*p后插入一个新结点的时间复杂度为________,在给定值为x的结点后插入一个新结点的时间复杂度为________。
7.根据线性表的链式存储结构中每一个结点包含的指针个数,将线性链表分成________和_______;而又根据指针的连接方式,链表又可分成________和________。
8.在双向循环链表中,向p所指的结点之后插入指针f所指的结点,其操作是_______、_______、 _______、________。
9.在双向链表结构中,若要求在p 指针所指的结点之前插入指针为s 所指的结点,则需执行下列语句:s^ .next:=p; s^ .prior:= ________;p^ .prior:=s;________:=s;10.链接存储的特点是利用________来表示数据元素之间的逻辑关系。
11.顺序存储结构是通过________表示元素之间的关系的;链式存储结构是通过________表示元素之间的关系的。
12.对于双向链表,在两个结点之间插入一个新结点需修改的指针共 ______个,单链表为_______个。
链表概念及其表示经典练习题
链表概念及其表示经典练习题
链表是计算机中常用的一种数据结构,它由若干个节点组成,
每个节点包含数据和指向下一个节点的指针。
链表分为单向链表、
双向链表和循环链表。
单向链表
单向链表中,每个节点只有一个指向下一个节点的指针,最后
一个节点的指针指向空地址。
单向链表的插入和删除操作比较简单,但是查找操作需要从头节点开始遍历。
练题
1. 实现单向链表的创建、插入、删除和遍历操作。
2. 反转单向链表。
3. 查找单向链表中倒数第k个节点。
双向链表
双向链表中,每个节点有两个指针,一个指向前一个节点,一个指向下一个节点。
双向链表的插入和删除操作比单向链表更加灵活,但是需要对前后节点的指针进行操作。
练题
1. 实现双向链表的创建、插入、删除和遍历操作。
2. 反转双向链表。
3. 查找双向链表中倒数第k个节点。
循环链表
循环链表中,最后一个节点的指针指向头节点,形成一个环。
相比于单向链表和双向链表,循环链表更加灵活,可以实现循环遍历。
练题
1. 实现循环链表的创建、插入、删除和遍历操作。
2. 反转循环链表。
3. 查找循环链表中倒数第k个节点。
以上是链表的概念及其表示,以及相应的经典练习题。
掌握这些知识,可以对链表有更深入的理解,也更利于进行编程实现。
c语言链表指针编程题
以下是一个使用链表和指针的 C 语言编程题:题目:将一个无序整数数组按照升序排列,并存储在链表中。
要求:1.定义一个链表节点结构体,包含一个整数和一个指向下一个节点的指针。
2.实现一个函数,将无序整数数组按照升序排列,并将结果存储在链表中。
3.实现一个函数,遍历链表并输出每个节点的值。
示例:输入:复制代码无序整数数组:[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]输出:复制代码链表节点值:[1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]以下是一个可能的实现:c复制代码#include<stdio.h>#include<stdlib.h>// 定义链表节点结构体typedef struct Node {int value;struct Node* next;} Node;// 插入节点到链表尾部Node* insertNode(Node* head, int value) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->value = value;newNode->next = NULL;if (head == NULL) {head = newNode;} else {Node* current = head;while (current->next != NULL) {current = current->next;}current->next = newNode;}return head;}// 将无序整数数组按照升序排列,并将结果存储在链表中Node* sortAndBuildList(int arr[], int n) {Node* head = NULL; // 头节点指针,初始为空for (int i = 0; i < n; i++) { // 将数组元素插入链表尾部head = insertNode(head, arr[i]);}// 对链表进行排序(可以使用快速排序、归并排序等算法)// 这里简单起见,只使用了冒泡排序算法进行排序,实际应用中应使用更高效的排序算法。
单向链表练习题
单向链表练习题单向链表练习题链表是一种常见的数据结构,它由一系列节点组成,每个节点包含一个数据元素和一个指向下一个节点的指针。
在计算机科学中,链表常用于实现其他数据结构,如栈和队列。
掌握链表的基本操作对于编程人员来说是至关重要的。
在本篇文章中,我们将通过一些练习题来加深对单向链表的理解。
1. 反转链表题目:给定一个单向链表,将其反转。
示例:输入:1 -> 2 -> 3 -> 4 -> 5输出:5 -> 4 -> 3 -> 2 -> 1解析:反转链表是一个常见的链表操作。
我们可以使用三个指针prev、curr和next来完成反转。
初始时,prev指向null,curr指向头节点。
我们需要将curr的next指针指向prev,然后移动prev、curr和next指针,直到遍历完整个链表。
2. 链表中倒数第k个节点题目:给定一个单向链表,找到链表中倒数第k个节点。
示例:输入:1 -> 2 -> 3 -> 4 -> 5,k = 2输出:4解析:要找到链表中倒数第k个节点,我们可以使用双指针法。
首先,我们让一个指针p1指向链表的头节点,然后让另一个指针p2指向链表的第k个节点。
接下来,同时移动p1和p2指针,直到p2指向链表的末尾。
此时,p1指向的节点就是倒数第k个节点。
3. 合并两个有序链表题目:给定两个有序链表,将它们合并为一个有序链表。
示例:输入:1 -> 2 -> 4, 1 -> 3 -> 4输出:1 -> 1 -> 2 -> 3 -> 4 -> 4解析:合并两个有序链表是一个常见的链表操作。
我们可以使用递归或迭代的方式来实现。
递归的思路是比较两个链表的头节点,将较小的节点作为合并后的链表的头节点,并递归地合并剩余的节点。
迭代的思路是使用一个额外的指针来指向合并后的链表的末尾,然后比较两个链表的头节点,将较小的节点接在末尾,并更新指针和链表头。
习题3(链表)
习题3(链表)一、选择题(1)链接存储的存储结构所占存储空间( A )。
A)分两部分,一部分存放结点值,另一部分存放表示结点间关系的指针B)只有一部分,存放结点值C)只有一部分,存储表示结点间关系的指针D)分两部分,一部分存放结点值,另一部分存放结点所占单元数(2)线性表若采用链式存储结构时,要求内存中可用存储单元的地址( D )。
A)必须是连续的B)部分地址必须是连续的C)一定是不连续的D)连续或不连续都可以(3)线性表L在( B )情况下适用于使用链式结构实现。
A)需经常修改结点值B)需不断删除插入C)含有大量的结点D)结点结构复杂(4)单链表的存储密度( C )。
A)大于1 B)等于1 C)小于1 D)不能确定(5)若指定有n个元素的向量,则建立一个有序单链表的时间复杂性的量级是( C )。
A)O(1) B)O(n) C)O(n2) D)O(nlog2n)(6)在单链表中,要将s所指结点插入到p所指结点之后,其语句应为( D )。
A)s->next=p+1; p->next=s; B)(*p).next=s; (*s).next=(*p).next;C)s->next=p->next; p->next=s->next; D)s->next=p->next; p->next=s;(7)在双向链表存储结构中,删除p所指的结点时须修改指针( A )。
A)p->next->prior=p->prior; p->prior->next=p->next;B)p->next=p->next->next; p->next->prior=p;C)p->prior->next=p; p->prior=p->prior->prior;D)p->prior=p->next->next; p->next=p->prior->prior;(8)在双向循环链表中,在p指针所指的结点后插入q所指向的新结点,其修改指针的操作是( C )。
第二章 指针与链表
第二章指针与链表一、静态存贮和动态存贮1、静态存贮程序中的变量一经说明,计算机操作系统就会在内存空间中分配相应的存贮单元,其中变量名是存贮单元的地址,而变量的值是存贮单元的内容,且该存贮单元自始至终都被该变量所占用,直到程序结束。
如果变量是局部变量,那么在它的作用域内,一经说明也占有一定的存贮单元,直到退出其作用域为止。
这样的变量,在程序执行过程中,不能随时使用随时分配存贮空间,也不能在程序执行的过程中,释放这些空间。
也就是说,一旦给这些变量分配存贮空间,无论程序是否还需要使用,它们都要占用一定的存贮空间,以便给用户存贮数据。
我们称具有这样特点的存贮为静态存贮,它所对应的变量称为静态变量。
如字符类型、数组类型、记录类型等。
这类变量的优点是存贮方便,查找容易,可以通过一个简单的公式随机存取表中的任一元素,逻辑关系上相邻的两个元素在物理位置上也是相邻的,很容易找到前趋与后继元素;缺点是在线性表的长度不确定时,必须分配足够大的存储空间,经常浪费了宝贵的存储资源;而线性表的容量一经定义确定后就难以扩充;在插入和删除线性表的元素时,需要移动大量的元素,时间效率也比较差。
2、动态存贮在程序执行过程中,通过向操作系统申请存贮空间或释放存贮空间的命令,达到动态管理计算机的存贮空间,以保证存贮空间的充分利用。
存贮空间可以随时申请、随时释放,这样的存贮方式称为动态存贮,其变量称为动态变量。
指针变量即为动态变量。
动态存储所需要的空间可以是不连续的,这样有利于充分利用零散的小空间。
但缺无法用O(1)的时间实现存取了。
如何用这些零散的空间存储数组这些大规模数据呢?如何表示这些数据之间的逻辑关系呢?为了表示这些物理存储单元之间的逻辑关系,对于每个数据元素来说,除了要存储它本身的信息(数据域data)外,还要存储它的直接后继元素的存储位置(指针域,一般用link 或next 表示)。
我们往往把这两部分信息合在一起称为一个“结点node”。
【原创】数据结构:链表练习题
数据结构练习:链表【练习目的】这份练习主要考察对链表的认识和程序设计的能力。
【结构要求】这份练习中所用到的链表包括两个结构体。
左边的结构体是链表结点的结构。
value存放的是结点中包含的数字;next存放的是下一个结点的地址。
右边的结构体是整张链表的结构。
head和tail分别指向的是链表的第一个元素和最后一个元素。
size是链表中元素的个数。
【函数】这份练习,我们要实现下面这些函数LinkedList*newLinkedList();『新建』创建一个新的链表。
新链表创建的时候,head和tail指针都指向NULL。
因为新建的时候表中没有任何元素,所以size=0。
void insert(LinkedList*list,int value);『插入』将一个数字value插入链表list。
插入的时候,只能在链表的尾部插入(即指针tail 所指的位置)。
void remove(LinkedList*list,int value);『删除』将一个数字value从链表list里面删除。
如果value不存在,必须输出一段提示,说明这个数字不存在。
如果有多个value存在,则只删除离表头最近的那个。
int count(LinkedList*list);『计数』计算并返回链表中元素的个数。
void replicate(LinkedList*list,int times);『复制』将链表list复制times次。
例:如果链表list={1,2,3},当调用replicate(list, 3)的时候,链表变成:list={1,2,3,1,2,3,1,2,3}。
void reverse(LinkedList*list);『逆转』将链表list倒过来。
例:如果链表list={1,2,3},当调用reverse(list);时,链表变成:list={3,2,1}。
void removeAllBut(LinkedList*list,int value);『保留』删除链表list中除了value之外的其他所有数字。
链表相关的一些题目
链表相关的⼀些题⽬将单向链表按某值划分成左边⼩、中间相等、右边⼤的形式:【题⽬】给定⼀个单向链表的头节点head,节点的值类型是整型,再给定⼀个整数pivot。
实现⼀个调整链表的函数,将链表调整为左部分都是值⼩于pivot的节点,中间部分都是值等于pivot的节点,右部分都是值⼤于pivot的节点。
除这个要求外,对调整后的节点顺序没有更多的要求。
例如:链表9->0->4->5->1,pivot=3。
调整后链表可以是1->0->4->9->5,也可以是0->1->9->5->4。
总之,满⾜左部分都是⼩于3的节点,中间部分都是等于3的节点(本例中这个部分为空),右部分都是⼤于3的节点即可。
对某部分内部的节点顺序不做要求。
【思路】遍历链表,将链表按pivot值的⼤⼩划分成三个链表,分别为small表、equal表、big表,存储⼩于pivot的元素,等于pivot的元素,⼤于pivot 的元素。
划分完后将三个链表连接起来,返回头指针即可。
【Code】public static class Node{public int value;public Node next;public Node(int value){this.value = value;}}public static Node SmallEqualBig(Node head,int pivot){Node sH = null;Node sT = null;Node eH = null;Node eT = null;Node bH = null;Node bT = null;Node next = null;//将原链表按pivot的值进⾏划分,成三个链表while(head!=null){next = head.next;head.next = null;if(head.value<pivot){if(sH==null){sH = head;sT = head;}else {sT.next = head;//向当前表尾的后继插⼊新节点sT = head;//指针后移到新插⼊的节点}}else if(head.value==pivot){if(eH==null){eH = head;eT = head;}else {eT.next = head;eT = head;}}else {if(bH==null){bT = head;}else {bT.next = head;bT = head;}}head =next;}//将三个链表从⼩中⼤进⾏连接//small连接equal表if(sT!=null){sT.next = eH;eT = eT == null? sT:eT;}//equal表连接big表if(eT!=null){eT.next = bH;}//返回头指针return sH!=null?sH:eH!=null?eH:bH;}复制含有随机指针节点的链表【题⽬】⼀种特殊的链表节点类描述如下:public class Node { public int value; public Node next; public Node rand; public Node(int data) { this.value = data; }}Node类中的value是节点值,next指针和正常单链表中next指针的意义⼀样,都指向下⼀个节点,rand指针是Node类中新增的指针,这个指针可能指向链表中的任意⼀个节点,也可能指向null。
C++笔试题:关于链表和指针
C++笔试题:关于链表和指针
给你一个单链表和一个指向特定节点的指针,如何在一个特定时间删除这个节点?
删除节点我们需要两个东西,一个是要删除节点的前一个节点的地址和它的后一个节点。
这个面试题情况下我们只知道当前节点的地址
假设这个节点如下:
data=thedata
next=pointertothenextnode
再假设这个链表如下所示我们只知道当前的节点地址
preiousnode->currentnode->nextnode
//拷贝当前节点的下一个节点的内容到当前节点
nextnode=currentnode->next
currentnode->data=nextnode->data
currentnode->next=nextnode->next
注意:如果当前节点是链表的最后一个元素的话,这个方法不适用。
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]
一、选择题1.下列程序段的时间复杂度为()。
i=0,s=0; while (s<n) {s=s+i;i++;}(A) O(n1/2) (B) O(n1/3) (C) O(n) (D) O(n2)2.设某链表中最常用的操作只是在链表中进行查找,则最好采取下列()存储方式最节省运算时间。
(A) 无序静态表(B) 有序静态表(C) 单向链表(D) 双向循环链表3.设指针q指向单链表中结点A,指针p指向单链表中结点A的后继结点B,指针s指向被插入的结点X,则在结点A和结点B插入结点X的操作序列为()。
(A) s->next=p->next;p->next=-s;(B) q->next=s;s->next=p;(C) p->next=s->next;s->next=p;(D) p->next=s;s->next=q;4.设输入序列为1、2、3、4、5、6,则通过栈的作用后可以得到的输出序列为()。
(A) 5,3,4,6,1,2 (B) 3,2,5,6,4,1(C) 3,1,2,5,4,6 (D) 1,5,4,6,2,35.设有一个10阶的下三角矩阵A(包括对角线),按照从上到下、从左到右的顺序存储到连续的55个存储单元中,每个数组元素占1个字节的存储空间,则A[5][4]地址与A[0][0]的地址之差为()。
(A) 10 (B) 19 (C) 28 (D) 556.设一棵m叉树中有N1个度数为1的结点,N2个度数为2的结点,……,Nm个度数为m的结点,则该树中共有()个叶子结点。
(A) ∑=-miiNi1)1((B) ∑=miiN1(C) ∑=miiN2(D) ∑=-+miiNi2)1(17. 二叉排序树中左子树上所有结点的值均()根结点的值。
(A) < (B) > (C) = (D) !=8. 设一组权值集合W=(15,3,14,2,6,9,16,17),要求根据这些权值集合构造一棵哈夫曼树,则这棵哈夫曼树的带权路径长度为()。
链表+指针基本练习
3 以下程序的输出结果是
A)3 B)4 C)1 D)2 main() { int a[10]={1,2,3,4,5,6,7,8,9,10},*p=a; printf("%d\n",*(p+2)); }
4、 以下程序的输出结果是
A)不确定的值 B)3 C)2 D)1 main() { int n[2]={0},i,j,k=2; for(i=0;i<k;i++) for(j=0;j<k;j++) n[j]=n[i]+1; printf("%d\n",n[k]); }
第9章 数组
51804、 若有定义 、 若有定义: struct node { int data; struct node *next; }; 及函数: 及函数: void fun(struct node *head) { struct node *p=head; while(p) { struct node *q=p->next; free(p); p=q; } } 调用时head是指向链表首结点的指针,整个链表的结构如下图: 是指向链表首结点的指针, 调用时 是指向链表首结点的指针 整个链表的结构如下图: ┌─┬─┐ ┌─┬─┐ ┌─┬─┐ head →│2 │ ┼→│15│ ┼→… →│27│ ┼→NULL └─┴─┘ └─┴─┘ └─┴─┘ 则函数fun()的功能是( )。 的功能是( 则函数 的功能是 答案: 答案:A A、 删除整个单向链表 B、 删除单向链表中的一个结点 、 、 C、 显示单向链表中的所有数据 D、 创建单向链表 、 、
C语言链表基本练习
第9章 数组
51801、 若有以下定义: 、 若有以下定义: struct link { int data; struct link *next; } *head, *p; 并已建立如下图所示的链表结构: 并已建立如下图所示的链表结构: ┌──┬──┐ ┌──┬──┐ ┌──┬──┐ head →│data│next┼→ │data│next →...→data│NULL│ └──┴──┘ └──┴──┘ └──┴──┘ 指针p指向如下结点 指向如下结点: 指针 指向如下结点 ┌──┬──┐ p →│data│next│ └──┴──┘ 则能够把p所指结点插入到链表中成为链表第 个结点的程序段是( 所指结点插入到链表中成为链表第2个结点的程序段是 则能够把 所指结点插入到链表中成为链表第 个结点的程序段是( )。 答案: 答案:A A、 p->next = head->next; head->next = p; 、 B、 head->next = p; p->next = head->next; 、 C、 p.next = head.next; head.next = p; 、 D、 (*head).next = p; (*p).next = (*head).next; 、
指针和链表复习题
一、选择题(共20分。
每题1分)1.若有char *p = "Hello",则以下选项中错误的是:( )A.char &a = *p;B.char *s = *p;C.char *q = p+2;D.p= p+2;2.设有说明int x[5] = {1,2,3,4,5},*p = x;输出值不是5的是:A.cout<<sizeof(x)/sizeof(int)<<'\n';B.cout<<sizeof(x)/sizeof(x[0])<<'\n';C.cout<<sizeof(p)/sizeof(int)<<'\n';D.cout<<sizeof(x)/sizeof(1)<<'\n';3.设有说明语句:char *s[] = {"Student","Teacher","Father","Mother"},*ps = s[2];执行语句:cout<<*s[1]<<','<<ps<<','<<*ps<<'\n';则输出结果是:A.T,Father,FB.Teacher,F,FatherC.Teacher,Father,FatherD.语法错,无输出4.设有语句char s[ ] = "246",*ptr = s;cout<<(char)(*(ptr+1)+1)<<'\n';执行以上语句后输出:A. 46B. 6 C.5 D. 535.设有说明语句:float fun(int &,char *);int x;char s[200];对以下函数fun的调用中正确的调用格式是A.fun(&x,s)B. fun(x,s)C. fun(x,*s) D .fun(&x,*s)6、设s和t分别为指向两个长度相同的字符数组指针,则循环语句while( (7) )可以正确实现字符串t到s 的完整复制功能。
指针与链表练习
指针与链表练习1、围绕着山顶有10 个洞,一只兔子和一只狐狸各住一个洞,狐狸总想吃掉兔子。
一天兔子对狐狸说,你想吃我有一个条件,第一次隔一个洞找我,第二次隔两个洞找我,以后依次类推,次数不限。
若能找到我,你就可以饱餐一顿,在没找到我之前不能停止。
狐狸一想只有10 个洞,寻找的次数又不限,哪有找不到的道理,就答应了条件。
结果就是没找着。
现请你编写一程序,假定狐狸找了1000 次,兔子躲在哪个洞里才安全。
2、输入一串大写字母,用这些字母建立一个指针链表,然后输出这个链表。
链表中可能有一些重复的字母,将重复的多余字母从链表中删除,只留下第1个,输出链表。
再将剩余链表中的字符按ASCII码升序重排,然后输出该链表。
例如:输入:DSDFRSSDFGDKAHHAUJDJG输出:DSDFRSSDFGDKAHHAUJDJGDSFRGKAHUJADFGHJKRSU3、约瑟夫的新问题源程序文件名 jsf.pas可执行文件名 jsf.exe输入文件名 jsf.in输出文件名 jsf.out时间限制 1秒问题描述将1~M这M个自然数按由小到大的顺序沿顺时针方向围成一圈。
以S为起点,先沿顺时针方向数到第N个数就出圈,然后再沿逆时针方向数到第K个数再出圈,再沿顺时针方向数到第N个数就出圈,然后再沿逆时针方向数到第K个数再出圈,……。
这样按顺时针方向和逆时针方向不断出圈,直到全部数都出圈为止。
请打印先后出圈的数的序列。
输入格式文件中共4行,每行为一个自然数,分别表示M,S,N,K。
M不超过1000。
输出格式仅1行,先后出圈的数的序列,每个数之间有1个空格。
样例输入(jsf.in)8132样例输出(jsf.out)3 1 5 2 74 6 8(解释:先从1开始沿顺时针方向数到3,所以3先出圈;再从2开始沿逆时针方向数到1,所以1出圈;再从2开始沿顺时针方向数到5,所以5出圈,再从4开始沿逆时针方向数到2,所以2出圈,……)DOCUMENT源程序名 DOCUMENT.???(PAS,C,C++)可执行文件名 DOCUMENT.EXE输入文件名 DOCUMENT.IN输出文件名 DOCUMENT.OUT时间限制 2SAndy很喜欢旧电脑。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
指针与链表练习
1、围绕着山顶有10 个洞,一只兔子和一只狐狸各住一个洞,狐狸总想吃掉兔子。
一天兔子对狐狸说,你想吃我有一个条件,第一次隔一个洞找我,第二次隔两个洞找我,以后依次类推,次数不限。
若能找到我,你就可以饱餐一顿,在没找到我之前不能停止。
狐狸一想只有10 个洞,寻找的次数又不限,哪有找不到的道理,就答应了条件。
结果就是没找着。
现请你编写一程序,假定狐狸找了1000 次,兔子躲在哪个洞里才安全。
2、输入一串大写字母,用这些字母建立一个指针链表,然后输出这个链表。
链表中可能有一些重复的字母,将重复的多余字母从链表中删除,只留下第1个,输出链表。
再将剩余链表中的字符按ASCII码升序重排,然后输出该链表。
例如:输入:DSDFRSSDFGDKAHHAUJDJG
输出:DSDFRSSDFGDKAHHAUJDJG
DSFRGKAHUJ
ADFGHJKRSU
3、约瑟夫的新问题
源程序文件名 jsf.pas
可执行文件名 jsf.exe
输入文件名 jsf.in
输出文件名 jsf.out
时间限制 1秒
问题描述
将1~M这M个自然数按由小到大的顺序沿顺时针方向围成一圈。
以S为起点,先沿顺时针方向数到第N个数就出圈,然后再沿逆时针方向数到第K个数再出圈,再沿顺时针方向数到第N个数就出圈,然后再沿逆时针方向数到第K个数再出圈,……。
这样按顺时针方向和逆时针方向不断出圈,直到全部数都出圈为止。
请打印先后出圈的数的序列。
输入格式
文件中共4行,每行为一个自然数,分别表示M,S,N,K。
M不超过1000。
输出格式
仅1行,先后出圈的数的序列,每个数之间有1个空格。
样例输入(jsf.in)
8
1
3
2
样例输出(jsf.out)
3 1 5 2 7
4 6 8
(解释:先从1开始沿顺时针方向数到3,所以3先出圈;再从2开始沿逆时针方向数到1,所以1出圈;再从2开始沿顺时针方向数到5,所以5出圈,再从4开始沿逆时针方向数到2,所以2出圈,……)
DOCUMENT
源程序名 DOCUMENT.???(PAS,C,C++)
可执行文件名 DOCUMENT.EXE
输入文件名 DOCUMENT.IN
输出文件名 DOCUMENT.OUT
时间限制 2S
Andy很喜欢旧电脑。
他喜欢任何和旧电脑有关的东西,并且他在自己现代的计算机里装着旧的操作系统。
Andy也很喜欢为旧电脑写程序。
最近他决定为他的文本模式的操作系统写一个文本编辑器。
他遇到的最困难任务是要处理文档索引。
一个文档的索引是所有在文档中出现的单词按字典顺序的排列,并且附上这些单词出现的页码。
Andy感觉他没有能力写文本编辑器的这个实现索引的组件,所以他请你帮忙。
一篇文档是一些段落的组合。
每一个段落包含一行或者多行。
段落之间以一个空行为区分。
首先这篇文档是有页码的——即分成了很多的页。
每一页最多有n行。
一页上是一行接着一行的,直到排满n行为止。
以下是分页法则:
●如果一页的最后一行是一段的最后一行,则下面的空行被忽略。
因此,没有一页
纸是由空行打头的。
●如果一页最后一行是一段的第一行,且这一段不止一行,那么这一行将被移到下
一页。
●如果一页最后一行是一段的倒数第二行,且这一段超过3行,那么这一行被移到
下一页。
●如果一页最后一行是一段的倒数第二行,且这一段只有2或3行,那么这一整段
被移到下一页。
运用这个分页法则,直到整个文档全部编号页码。
一个单词是一串英文字母。
大小写不敏感。
文档的索引包含文档中每一个单词和他们出现的位置(即页码)。
一个单词对应的页码必须按升序排列。
数字之间用逗号间隔。
如果一个单词在连续的几页中出现,则对开始的页码和最后的页码被列出来,中间用减号(-)相隔,例如“3-5,7-10,12,13,15”。
输入
在输入文件的第一行是一个整数n(4<=n<=100)。
输入文件的其他部分包含要被索引的文档。
输入文件的大小不超过20,000字节。
如果一行什么都没有则视为空行。
每行没有开始和结尾的空格。
文档不包含连续的两个空行。
文档的第一行不是空行。
每一行不超过200个字符。
输出
输出所有出现在文档中的单词。
单词必须按字典顺序列出,一个单词一行。
在每一个单词之后是一个空格,然后是页码编号,编号的格式按照题目的要求。
单词都用大写字母表示。
样例
DOCUMENT.IN
6
From thousands of teams competing in regional
contests held from September to December 2004
world-wide, seventy-five teams will advance to
the World Finals in Shanghai, April 3-7, 2005.
Awards, prizes, scholarships, and bragging rights
will be at stake for some of the world’s finest
university students of the computing science.
Join us for the challenge, camaraderie,
and the fun! Become the best of the best
of the best in ACM ICPC!
ACM ICPC is the best contest!
DOCUMENT.OUT
ACM 3
ADVANCE 1
AND 2,3
APRIL 1
AT 2
AWARDS 2
BE 2
BECOME 3
BEST 3
BRAGGING 2
CAMARADERIE 3
CHALLENGE 3
COMPETING 1
COMPUTING 2
CONTEST 3
CONTESTS 1
DECEMBER 1
FINALS 1
FINEST 2
FIVE 1
FOR 2,3
FROM 1
FUN 3
HELD 1
ICPC 3
IN 1,3
IS 3
JOIN 3
OF 1-3 PRIZES 2 REGIONAL 1 RIGHTS 2
S 2 SCHOLARSHIPS 2 SCIENCE 2 SEPTEMBER 1 SEVENTY 1 SHANGHAI 1 SOME 2
STAKE 2 STUDENTS 2 TEAMS 1
THE 1-3 THOUSANDS 1 TO 1 UNIVERSITY 2 US 3
WIDE 1
WILL 1,2 WORLD 1,2。