链表的翻转
1. 代码中指明了链表的定义,以及初始化,初始化使用尾插法实现。
2. 链表的翻转采用三种方式,分别是递归,栈,以及对链表逆序后,再输出
代码如下:
#include <iostream>
#include<stack>
using namespace std;
typedef struct Node{
int data;
Node* next;
}Node;
//尾部添加
Node* tailAdd(Node* head, int e){
Node* t = new Node;
t->data = e;
t->next = NULL;
if(head == NULL){
head = t;
}else if(head ->next == NULL){
head->next = t;
}else{
Node* p = head->next;
while(p->next != NULL){
p = p->next;
}
p->next = t;
}
return head;
}
//顺序输出
void print(Node* head){
Node* p = head;
while(p!=NULL){
cout<<p->data<<" ";
p = p->next;
}
cout<<endl;
}
//递归 逆序输出
void dg(Node *head){
Node* p = head;
if(p!=NULL){
dg(p->next);
cout<<p->data<<" ";
}
}
//栈,实现逆序
void reversePrint(Node* head){
stack<int > s;
while(head!=NULL){
s.push(head->data);
head = head->next;
}
while(!s.empty()){
cout << s.top() << " ";
s.pop();
}
cout<<endl;
}
//还有一种,链表逆序后输出
Node* revers(Node* head){
if(head == NULL || head->next == NULL){
return head;
}
Node* p1 = head; //p1保存翻转后的链表
Node* p2 = head->next; //p2保存原始链表
Node* p3 = NULL; //临时存储结点
head->next = NULL; //pHead的第一个结点是尾结点,尾结点下一个结点是NULL;
while(p2!=NULL){ // p2为空,停止循环
p3 = p2; // p2指向的当前结点,存到临时结点
p2 = p2->next; //p2向后指一个结点,为下次循环做准备
p3->next = p1; //p3指向已经翻转的链表p1,实现链表翻转
p1 = p3; //p3重新赋值给p1
}
head = p1; //把p1赋值给头结点head。
return head;
}
int main()
{
Node* head = NULL;
for(int i=1;i<=5;i++){
head = tailAdd(head,i); //尾部添加数据
}
print(head); //顺序输出链表
dg(head); //翻转递归输出
reversePrint(head); //栈翻转输出
head = revers(head); //先将链表逆序返回
print(head); //再把逆序的链表输出
return 0;
}
链表合并
Node* Merge(Node* pHead1, Node* pHead2)
{
Node* p = new Node;
p->data = 0;
p->next = NULL;
if(pHead1==NULL && pHead2==NULL){
p =NULL;
return p;
}else if(pHead1==NULL){
p = pHead2;
return p;
}else if(pHead2 == NULL){
p = pHead1;
return p;
}else{
Node* p1=pHead1;
Node* p2=pHead2;
if(pHead1->data < pHead2->data){
p = pHead1;
p1 = p1->next;
}else{
p = pHead2;
p2 = p2->next;
}
pHead1 = p;
while(p1!=NULL && p2!=NULL){
if(p1->data < p2->data){
p->next = p1;
p1 = p1->next;
p = p->next;
}else{
p->next = p2;
p2 = p2->next;
p = p->next;
}
}
if(p1!=NULL){
p->next = p1;
}else if(p2!=NULL){
p->next = p2;
}else{
p->next = NULL;
}
return pHead1;
}
}
链表中倒数第k个结点
有两种方法:
1. 先遍历链表,算出链表结点数count,第二次直接遍历到第count-k个结点。但是要注意,可能链表结点数cout小于k,此时要返回NULL。这一条件要先判断。
代码:
Node* FindKthToTail(Node* pListHead, unsigned int k) { //k表示倒数第k个结点
int count = 1;
Node* p =pListHead;
if(pListHead==NULL || k==0){
count=0;
}else{
while(p->next != NULL){ //先遍历链表
count++;
p = p->next;
}
}
Node* r =new Node;
r = NULL;
if(count<k || count==0){
r =NULL;
return r;
}else{
p = pListHead;
for(int i=0;i<count-k;i++){ //遍历到链表count-k个结点
p = p->next;
}
r = p;
return r;
}
}
2. 可以用两个指针,第一个指针遍历到第k个结点的时候,第二个指针再走到第一个结点,两个指针之间始终保持k-1的距离,当第一个指针的next==NULL,第二个指针对应的位置,就是倒数第k个结点。
Node* FindKthToTail(Node* pListHead, unsigned int k) {
Node* first = pListHead;
Node* second = pListHead;
Node* r =new Node;
int count = 1;
if(pListHead==NULL || k==0){
r = NULL;
return r;
}else{
while(first->next != NULL){
count++;
if(count>=k+1){
second = second->next;
}
first = first->next;
}
if(count<k){
r = NULL;
return r;
}else{
r = second;
return r;
}
}
}