无头单链表面试题(2)

来源:互联网 发布:儿童学唱歌软件 编辑:程序博客网 时间:2024/05/29 09:09

一.先构造一个类型,把链表的初始化,尾插,尾删和查找相应结点的位置函数给出来

1.定义结构体类型,并重命名;

typedef struct Node{Datatype data;Node*next;}Node,*pNode;

2.链表的初始化,尾插,尾删和查找相应结点位置函数

(1)初始化函数(将链表置空)

void Init( pNode*list )    //链表初始化{assert(list);*list = NULL;}
(2)尾插函数

void Pushback(pNode*list,Datatype d)    //尾插{Node*ret = *list;Node*newNode = new Node;if (newNode != NULL){newNode->data = d;newNode->next = NULL;}if (ret == NULL)*list = newNode;else{while (ret->next){ret = ret->next;}ret->next = newNode;}}
(3)尾删函数

void Popback(pNode*list)       //尾删{Node*ret = *list;Node*temp =NULL;if (ret == NULL)return;if (ret->next == NULL){delete *list;*list = NULL;return;}while (ret->next){temp = ret;ret = ret->next;}delete (temp->next);temp->next = NULL;}
(4)查找相应结点位置

Node* Find(Node*list, Datatype d)    //查找位置{if (list == NULL)return NULL;Node*ret = list;while (ret){if (ret->data == d)return ret;ret = ret->next;}return NULL;}

二、链表的题

1.在链表指定位置插入一个结点


在pos处插入结点,先开辟一块空间,将要插入的元素放进新开辟的空间里,然后将新结点插入到pos之后,最后将新结点中的数据data与pos结点里的数据交换,插入完成。

void Insert(Node*pos, Datatype d)    //指定位置插入{if (pos == NULL)return;Datatype ddata;Node*newNode = new Node;if (newNode != NULL){newNode->next = NULL;}newNode->next = pos->next;pos->next = newNode;ddata = pos->data;pos->data = d;newNode->data = ddata;}


2.从尾到头打印单链表

利用递归函数先打印最里层结点,然后往前一个接一个打印

void ReverseShow(Node *list)    //2.从后向前打印单链表{if (list == NULL)return;ReverseShow(list->next);cout << list->data << " ";cout << endl;}


3.删除一个无头单链表的非尾结点(不能遍历链表)


删除非尾结点pos, 将pos的下一个结点中的元素转换到pos结点中,然后将pos与pos的下下一个结点连接,释放pos后一个结点,删除完成。

void DeleteNoTail(Node *pos)    //3.删除无头单链表的非尾节点{if (pos == NULL)return;Node*ret = NULL;pos->data = pos->next->data;ret = pos->next->next;delete (pos->next);pos->next = ret;}
4.在无头单链表的一个非头结点前插入一个结点(原理同1)

void PushNohead(Node*pos,Datatype d)             //4.在非头节点前插入一个节点{if (pos == NULL)return;Node*newNode = new Node;if (newNode != NULL)newNode->next = NULL;newNode->next = pos->next;pos->next = newNode;newNode->data = pos->data;pos->data = d;}

5.单链表实现约瑟夫环(JosephCircle)

   约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依规律重复下去,直到圆桌周围的人全部出列。

实现方法:

举例:假如一个环只有5个结点,从1开始,数到3,将3打印然后将2连到4上,删除3,。继续循环这下从4开始,删除1,将1打印然后将5连到2上,删除1..... 直到剩下一个结点就跳出循环,然后将剩下的这一个结点打印,删除。完成操作。

void YueSeFuCirle(Node**list,int k)                  //5.约瑟夫环     {assert(list);Node*first = *list;Node*ret = NULL;while (first!=first->next){int count = k - 2;while (count>0){first = first->next;count--;}ret = first;first = ret->next->next;cout << ret->next->data << " ";delete (ret->next);ret->next = first;}cout << first->data << endl;delete first;first = NULL;}


6.反转单链表


创建3个Node类型的指针,将链表的头赋给ret,赋NULL给newhead,赋NULL给p ; 

利用头插法,从链表的头开始取结点,然后用p记住下一个结点的位置,将取下来的结点头插到新链表newhead上,当ret==NULL时结束。

void Reverse(Node**list)       //6.逆序单链表{assert(list);Node*ret = *list;Node*newhead = NULL;Node*p = NULL;while (ret){p = ret->next;ret->next = newhead;newhead = ret;ret = p;}*list = newhead;}


7.单链表排序(冒泡排序)(升序排列)

与一般整型数据冒泡法类似,两层循环,一层控制次数,一层负责交换数据;在第二层循环里,比较两个结点的元素大小,如果前一个结点元素大于后一个节点元素,交换两个节点中的元素。

void BubbleSort(Node**list)                //7.单链表排序{assert(list);Node*ret = *list;Node*temp = *list;Node*tail = NULL;while (temp->next){while (ret->next!=tail){if ((ret->data) > (ret->next->data)){swap(ret->data, ret->next->data);}ret = ret->next;}tail = ret;ret = *list;temp = temp->next;}}


8.返回链表的中间结点位置

创建两个指针,一个快指针fast每次走两步,一个慢指针slow每次走一步。当fast走到尾时,slow刚好走到中间。

Node*MidPlace(Node*list)         //9.返回链表的中间节点位置{if (list == NULL)return NULL;Node*fast = list;Node*slow = list;while (fast&&fast->next){fast = fast->next->next;slow = slow->next;}return slow;}

 9.查找链表倒数第k个结点



创建两个指针,一个head指向头,一个front指向从头向后走k步的位置;

然后两个指针同时走,当front指向NULL时,head就指向倒数第k个结点了。

Node*AfterKplace(Node*list,int k)        //10.查找倒数第k个节点的位置{if (list == NULL)return NULL;Node*fast = list;while (k--){fast =fast->next;}while (fast){list = list->next;fast = fast->next;}return list;}

10.删除链表倒数第k个结点


创建两个指针,一个head指向头,一个front指向从头向后走k步的位置;

然后两个指针同时走,当front->next指向NULL时,head就指向倒数第k个结点的前一个了,把head->next->next记下,Node*ret=head->next->next;然后释放空间delete (head->next); 完成操作。

void Delete(Node**list, int k)       //11.删除链表倒数第k个节点{assert(list);Node*ret = *list;Node*fast = *list;while (k--){fast = fast->next;}while (fast->next){fast = fast->next;ret = ret->next;}fast = ret->next->next;delete (ret->next);ret->next = fast;}

11.判断链表是否带环,若带环返回环的入口点


Node* IsCircle(Node*list)          //12.判断链表是否带环,若带环返回环的入口点{if (list == NULL)return  NULL;Node*fast = list;Node*slow = list;while (fast&&fast->next){fast = fast->next->next;slow = slow->next;if (fast == slow){Node*ret = list;while (ret!=slow){ret = ret->next;slow = slow->next;}return slow;}}return NULL;}


12.求环的长度

先接收环的入口点  ret= IsCircle(list);

创建一个引用计数,当ret每向后走一步,引用计数加1.

int CircleLenth(Node*pos)          //12求环的长度,pos为环的入口点{int count = 1;Node*ret = pos;while (pos != ret->next){ret = ret->next;count++;}return count;}
13.判断判断链表是否相交,若相交返回交点(假设链表不带环)

Node*JudgeCross(Node*list1, Node*list2)     //13.判断判断链表是否相交,若相交返回交点(假设链表不带环){Node*p1 = list1;Node*p2 = list2;Node*Cross = NULL;while (p1->next != NULL){p1 = p1->next;}while (p2->next != NULL){p2 = p2->next;}if (p1 == p2){p2->next = list2;                   //将p2的尾结点与头结点相接Cross = IsCircle(list1);return Cross;}return NULL;}



















原创粉丝点击