c++ 单链表 双向链表 链表笔试题


1 单链表 以及链表笔试题

--------------------------------Slist.h----


#ifndef __SLIST_H__


#define __SLIST_H__



//#pragma once

#include <iostream>

using namespace std;


typedef int DataType;


struct Node

{

Node(const DataType& d)

:_data(d)

,_next(NULL)

{}

DataType _data;

struct Node* _next;

};


class Slist

{

friend ostream& operator<<(ostream& os, const Slist& s);

public:

Slist()

:_head(NULL)

,_tail(NULL)

{

}


Slist(const Slist& s)

:_head(NULL)

,_tail(NULL)

{

Node* cur = s._head;

while(cur)

{

PushBack(cur->_data);

cur = cur->_next;

}

}


Slist& operator=(Slist s)

{

swap(_head, s._head);

swap(_tail, s._tail);

return *this;

}


~Slist()

{

Node* cur = _head;

while(cur && cur != _tail)//用cur != _tail 防止存在环时 入口点释放两次 导致程序崩溃

{

Node* del = cur;

cur = cur->_next; 

delete del;

}

delete _tail;

_head = NULL;

_tail = NULL;

}


public:

void PushBack(const DataType& d);

void PopBack();

void PushFront(const DataType& d);

void PopFront();

Node* Find(const DataType& d);

void Insert(Node* pos, const DataType& d);

void Reverse();

void Sort();

void Remove(const DataType& d);

void RemoverAll(const DataType& d);


int GetLength();


/*面试题*/


/* 1、判断两个单链表是不是相交*/


static bool CheckCross(const Slist& list1, const Slist& list2);


/* 2、找到两个单链表的交点*/

static Node* GetCrossNode(Slist& list1, Slist& list2);


/* 3、判断一个单链表是否带环*/

Node* CheckCycle();

/* 4、求取环的长度*/

int GetCircleLength();


/* 5、找到环的入口点*/

Node* GetCycleEntryNode(Node* meetNode);

private:

Node* _head;

Node* _tail;


};


#endif //__SLISH_H__



-------------------------------------Slist.cpp----


#include "Slist.h"

ostream& operator<<(ostream& os, const Slist& s)

{

if(NULL == s._head)

return os;

Node* cur = s._head;

while(NULL != cur)

{

os<<cur->_data<<"->";

cur = cur->_next;

}

os<<"over";

return os;

}


void Slist::PushBack(const DataType& d)

{

Node* newNode = new Node(d);

if(_head == NULL)

{

_head = newNode;

_tail = newNode;

}

else

{

_tail->_next = newNode;

_tail = newNode;

}


}


void Slist::PopBack()

{

if(NULL == _head)

{

return ;

}

else if(_head == _tail)

{

delete _tail;

_tail = _head = NULL;

}

else

{

Node* cur = _head;

while(_tail != cur->_next)

{

cur = cur->_next;

}

delete _tail;

_tail = cur;

_tail->_next = NULL;

}

}


void Slist::PushFront(const DataType& d)

{

Node* newNode = new Node(d);

if(NULL == _head)

{

_head = _tail = newNode;

}

else 

{

newNode->_next = _head;

_head = newNode;

}

}


void Slist::PopFront()

{

Node* del = _head;

if(NULL == _head)

{

return ;

}

else if(NULL == _head->_next)

{

_head = _tail = NULL;

}

else

{

_head = _head->_next;

}

delete del;

}


Node* Slist::Find(const DataType& d)

{

Node* cur = _head;

while(cur != NULL)

{

if(cur->_data == d)

{

return cur;

}

cur = cur->_next;

}

return NULL;

}

void Slist::Insert(Node* pos, const DataType& d)//pos后插

{

if(NULL == pos)

{

return ;

}


Node* newNode = new Node(d);

if(pos == _tail)

{

_tail->_next = newNode;

_tail = newNode;

}

else

{

newNode->_next = pos->_next;

pos->_next = newNode;

}

}


//=================================

void Slist::Reverse()

{

if(NULL == _head || NULL == _head->_next)

{

return;

}


Node* pos = _head->_next;

_tail =_head;

_head->_next = NULL;

while(NULL != pos)

{

Node* tmp = pos->_next;

pos->_next = _head;

_head = pos;

pos = tmp;

}

}


void Slist::Sort()

{

Node* pos = _head;

while(NULL != pos)

{

bool flag = true;

Node* index = pos;

Node* min = pos;

while(NULL != index)

{

if(index->_data < min->_data)

{

min = index;

flag = false;

}

index = index->_next;

}

if(true == flag)

{

return;

}

DataType tmp = min->_data;

min->_data = pos->_data;

pos->_data = tmp;

pos = pos->_next;

}

}

void Slist::Remove(const DataType& d)

{

if(NULL == _head)

{

return;

}

Node* pos = _head;

if(pos->_data == d)//头节点

{

if(NULL == pos->_next)

{

delete pos;

_head = _tail = NULL;

}

else

{

Node* del = pos;

pos = pos->_next;

_head = pos;

delete del;

}

return;

}



while(NULL != pos && NULL != pos->_next)

{

if(pos->_next->_data == d)

{

Node* del = pos->_next;

pos->_next = del->_next;

if(del == _tail)

{

_tail = pos;

pos->_next = NULL;

}

delete del;

return;

}

else

{

pos = pos->_next;

}

}

}

void Slist::RemoverAll(const DataType& d)

{

//一定要先删后面的 再考虑第一个

//(若先考虑第一个 删到最后 又成了考虑第一个的情况)

if(NULL == _head)

{

return;

}


Node* pos = _head;

while( pos != _tail)

{

if(pos->_next->_data == d)

{

Node* del = pos->_next;

pos->_next = del->_next;

if(del == _tail)

{

_tail = pos;

_tail->_next = NULL;

delete del;

break;

}

delete del;

}

else

{

pos = pos->_next;

}

}

pos = _head;

if(pos->_data == d)

{

if(pos == _tail)//防止全是d

{

delete pos;

_head = _tail = NULL;

}

else

{

Node* del = pos;

_head = pos->_next;

delete del;

}

}

}


//===============================笔试题 80:12

int Slist::GetLength()

{

int count = 0;

Node* pos = _head;

while(pos)

{

pos = pos->_next;

count++;

}

return count;

}

/* 1、判断两个单链表是不是相交 (主要是判断最后一个点是否相同)*/

bool Slist::CheckCross(const Slist& list1, const Slist& list2)

{

if(NULL == list1._head || NULL == list2._head)

{

return false;

}

Node* l1 = list1._head;

Node* l2 = list2._head;

while(l1->_next)

{

l1 = l1->_next;

}

while(l2->_next)

{

l2 = l2->_next;

}

if(l1 == l2)

{

return true;

}

else

{

return false;

}

}


/* 2、找到两个单链表的交点 

 * (快慢指针应用)

 *  快的先走多出的步 (可能为0 退化成等长) 然后两条链一起走 同时判断是否相等

 */

Node* Slist::GetCrossNode(Slist& list1, Slist& list2)

{

if(list1._head == NULL || list2._head == NULL)

{

return NULL;

}

Node* fast = list1._head;

Node* slow = list2._head;

int len1 = list1.GetLength();

int len2 = list2.GetLength();

int diff = len1 - len2;

if(diff < 0)

{

diff = diff * (-1);

fast = list2._head;

slow = list1._head;

}

while(diff--)

{

fast = fast->_next;

}

while(fast && slow)

{

if(fast == slow)

{

return fast;

}

fast = fast->_next;

slow = slow->_next;

}

return NULL;

}


/*

 * 3 判断一个单链表是否带环

 * (快慢指针)

 */

Node* Slist::CheckCycle()

{

if(NULL == _head)

{

return NULL;

}

Node* slow = _head;

Node* fast = _head;

while(fast && fast->_next)

{

slow = slow->_next;

fast = fast->_next->_next;

if(fast == slow)

{

return fast;

}

}

return NULL;

}


/*

 * 4 求取环的长度

 * 

 */

int Slist::GetCircleLength()

{

Node* meet = CheckCycle();

int count = 0;

if(meet)

{

Node* cur = meet;

do

{

cur = cur->_next;

count++;

}while(cur != meet);

}

return count;

}


/*

 * 5 找到环的入口点

 * 两个指针 一次走一步 一个从头开始走 一个从环上的相遇点开始走

 * 两指针相遇点即为入口点

 */


/* 方法1

Node* Slist::GetCycleEntryNode(Node* meet)

{

Node* list1 = _head;

Node* list2 = meet;

while(list1 && list2)

{

if(list1 == list2)

{

return list1;

}

list1 = list1->_next;

list2 = list2->_next;

}

return NULL;

}

*/


/* 方法2

 * 从判断环的相遇点拆开 拆成两条相交的链 问题转化成求相交链的交点

 */


Node* Slist::GetCycleEntryNode(Node* meet)

{

if(NULL == meet || NULL == _head)

{

return NULL;

}

Slist s1,s2,s3;

s1._head =_head;

s1._tail = meet;

s2._head = meet->_next;

s2._tail = meet;

s1._tail->_next = NULL;//拆分


Node* ret = GetCrossNode(s1, s2);


s1._tail->_next = s2._head;//还原


s1._head = s1._tail = NULL;

s2._head = s2._tail = NULL;


return ret;

}


--------------------------------------------------test.cpp----



#include "Slist.h"


/*

 * 测试

 * ostream& operator<<(ostream& os, const Slist& s)

 * void Slist::PushBack(const DataType& d) 

 * void Slist::PopBack()

 */

void test1()

{

Slist s1;

s1.PushBack(1);

s1.PushBack(2);

s1.PushBack(3);

s1.PushBack(4);

cout<<s1<<endl;


s1.PopBack();

cout<<s1<<endl;

s1.PopBack();

cout<<s1<<endl;

s1.PopBack();

cout<<s1<<endl;

s1.PopBack();

cout<<s1<<endl;

s1.PopBack();

cout<<s1<<endl;

}


/*

 * 测试

 * void PushFront(const DataType& d);

 * void PopFront();

 */

void test2()

{

Slist s1;

s1.PushFront(1);

s1.PushFront(2);

s1.PushFront(3);

s1.PushFront(4);

cout<<s1<<endl;


s1.PopFront();

cout<<s1<<endl;

s1.PopFront();

cout<<s1<<endl;

s1.PopFront();

cout<<s1<<endl;

s1.PopFront();

cout<<s1<<endl;

s1.PopFront();

cout<<s1<<endl;

s1.PopFront();

cout<<s1<<endl;

}


/*

 * 测试

 * Node* Find(const DataType& d);

 * void Insert(Node* pos, const DataType& d);

 */

void test3()

{

Slist s1;

s1.PushBack(1);

s1.PushBack(2);

s1.PushBack(3);

s1.PushBack(4);

cout<<s1<<endl;


/*cout<<s1.Find(5)<<endl;

cout<<s1.Find(1)<<endl;

cout<<s1.Find(3)->_data<<endl;

cout<<s1.Find(4)->_data<<endl;*/


s1.Insert(s1.Find(0),0);

cout<<s1<<endl;

s1.Insert(s1.Find(1),0);

cout<<s1<<endl;

s1.Insert(s1.Find(2),8);

cout<<s1<<endl;

s1.Insert(s1.Find(4),9);

cout<<s1<<endl;

}


/*

 * 测试

 * void Reverse();

 * void Sort();

 */

void test4()

{

Slist s1,s2,s3,s4;

s1.PushBack(1);

s1.PushBack(2);

s1.PushBack(3);

s1.PushBack(4);

s3.PushBack(1);

s4.PushBack(1);

s4.PushBack(2);

cout<<s1<<endl;

cout<<s2<<endl;

cout<<s3<<endl;

cout<<s4<<endl;

cout<<"================="<<endl;

s1.Reverse();

cout<<s1<<endl;

s2.Reverse();

cout<<s2<<endl;

s3.Reverse();

cout<<s3<<endl;

s4.Reverse();

cout<<s4<<endl;

cout<<"================="<<endl;


s1.Sort();

cout<<s1<<endl;

s2.Sort();

cout<<s2<<endl;

s3.Sort();

cout<<s3<<endl;

s4.Sort();

cout<<s4<<endl;


}


/*

 * 测试

 * void Remove(const DataType& d);

 * void RemoverAll(const DataType& d);

 *

 */

void test5()

{

Slist s1;

s1.PushBack(1);

s1.PushBack(1);

s1.PushBack(2);

s1.PushBack(3);

s1.PushBack(4);

s1.PushBack(1);

s1.PushBack(2);

s1.PushBack(3);

s1.PushBack(4);

s1.PushBack(1);

s1.PushBack(1);

cout<<s1<<endl;

cout<<"================="<<endl;


/*s1.Remove(0);

cout<<s1<<endl;

s1.Remove(1);

cout<<s1<<endl;

s1.Remove(3);

cout<<s1<<endl;

s1.Remove(4);

cout<<s1<<endl;*/


s1.RemoverAll(5);

cout<<s1<<endl;

s1.RemoverAll(1);

cout<<s1<<endl;


}


//===============面试题测试==================


/*

 * 测试

 * static bool CheckCross(const Slist& list1, const Slist& list2);

 * static Node* GetCrossNode(Slist& list1, Slist& list2);

 */

void test6()

{

Slist s1,s2;

s1.PushBack(1);

s1.PushBack(2);

s1.PushBack(3);

s1.PushBack(4);


s2.PushBack(1);

s2.PushBack(2);

s2.PushBack(3);

Node* p_tail = s2.Find(3);

p_tail->_next = s1.Find(4);

cout<<Slist::CheckCross(s1, s2)<<endl;

cout<<Slist::GetCrossNode(s1,s2)->_data<<endl;

p_tail->_next = NULL;

}


/*

 * 测试

 * Node* CheckCycle();

 * int Slist::GetCircleLength()

 */

void test7()

{

Slist s1;

s1.PushBack(1);

s1.PushBack(2);

s1.PushBack(3);

s1.PushBack(4);

s1.Find(4)->_next = s1.Find(1);

cout<<s1.CheckCycle()->_data<<endl;

cout<<s1.GetCircleLength()<<endl;

s1.Find(4)->_next = NULL;//防止析构出错

}


/*

 * 测试

 * Node* Slist::GetCycleEntryNode(Node* meet)

 */

void test8()

{

Slist s1;

s1.PushBack(1);

s1.PushBack(2);

s1.PushBack(3);

s1.PushBack(4);

s1.Find(4)->_next = s1.Find(3);

cout<<s1.GetCycleEntryNode(s1.CheckCycle())->_data;

//改造析构后 析构可以处理环 不用再s1.Find(4)->_next = NULL;


s1.Find(4)->_next = s1.Find(1);

cout<<s1.GetCycleEntryNode(s1.CheckCycle())->_data;

//s1.Find(4)->_next = NULL;

}


int main()

{

test8();


getchar();

return 0;

}

========================================================================

2 双向链表


--------------------------------------------DList.h----


#pragma once


#include <iostream>

using namespace std;

typedef int DataType;


struct Node

{

Node(const DataType& d)

:_data(d)

,_prev(NULL)

,_next(NULL)

{

}

Node* _next;

Node* _prev;

DataType _data;

};


class DList

{

friend ostream& operator<<(ostream& os, const DList& d);

public:

DList()

:_head(NULL)

,_tail(NULL)

{}


~DList()

{

Node* cur = _head;

while(cur)

{

Node* del = cur;

cur = cur->_next;

delete del;

}

}

public:

void PushBack(const DataType& d);

void PushFront(const DataType& d);

void PopBack();

void PopFront();

Node* Find(const DataType& d);

void Insert(Node* pos, const DataType& d);

void Sort();

void Reverse();

void Remove(const DataType& d);

void RemoveAll(const DataType& d);

void Erase(Node* pos);//删除


private:

Node* _head;

Node* _tail;

};

------------------------------------DList.cpp----


#define _CRT_SECURE_NO_WARNINGS 1


#include "DList.h"


ostream& operator<<(ostream& os, const DList& d)

{

Node* cur = d._head;

while(cur)

{

os<<cur->_data<<"<=>";

cur = cur->_next;

}

os<<"over";

return os;

}


void DList::PushBack(const DataType& d)

{

Node* newNode = new Node(d);

if(NULL == _head)

{

_head = newNode;

_tail = newNode;

}

else

{

_tail->_next = newNode;

newNode->_prev = _tail;

_tail = newNode;

}//============120:18

}

void DList::PushFront(const DataType& d)

{

Node* newNode = new Node(d);

if(NULL == _head)

{

_head = newNode;

_tail = newNode;

return;

}

else 

{

newNode->_next = _head;

_head = newNode;

}

}

void DList::PopBack()

{

if(NULL == _head)

{

return;

}

else if(_head == _tail)

{

delete _head;

_head = _tail = NULL;

}

else

{

_tail = _tail->_prev;

delete _tail->_next;

_tail->_next = NULL;

}

}

void DList::PopFront()

{

if(NULL == _head)

{

return;

}

else if(_tail == _head)

{

delete _head;

_head = _tail = NULL;

}

else

{

Node* del = _head;

_head = _head->_next;

_head->_prev = NULL;

delete del;

}

}


Node* DList::Find(const DataType& d)

{

Node* cur = _head;

while(cur)

{

if(cur->_data == d)

{

return cur;

}

cur = cur->_next;

}

return NULL;

}

void DList::Insert(Node* pos, const DataType& d)

{

if(NULL == pos)

{

return;

}

Node* newNode = new Node(d);

newNode->_next = pos->_next;

newNode->_prev = pos;

pos->_next = newNode;

if(pos == _tail)

{

_tail = newNode;

}

}


void DList::Sort()

{

if(NULL == _head)

{

return;

}

Node* cur = _head;

while(cur->_next)

{

bool flag = true;

Node* min = cur;

Node* index = cur;

while(index)

{

if(index->_data < min->_data)

{

min = index;

flag = false;

}

index = index->_next;

}

if(flag)

{

return;

}

DataType tmp = min->_data;

min->_data = cur->_data;

cur->_data = tmp;


cur = cur->_next;

}

}


void DList::Reverse()

{

Node* cur = _head;

_head = NULL;

_tail = NULL;

while(cur)

{

PushFront(cur->_data);

cur = cur->_next;

}

}


void DList::Remove(const DataType& d)

{

Node* del = Find(d);

if(del)

{

if(_head == _tail)//一个结点

{

delete del;

_head = _tail = NULL;

return;

}

if(_head == del)//在头结点 但不是一个结点

{

_head = del->_next;

_head->_prev = NULL;

delete del;

return;

}

if(del == _tail)

{

_tail = del->_prev;

_tail->_next = NULL;

delete del;

return;

}

del->_prev->_next = del->_next;

del->_next->_prev = del->_prev;

delete del;

}

}


void DList::RemoveAll(const DataType& d)

{

Node* del = Find(d);

while(del)

{

Remove(d);

del = Find(d);

}

}


void DList::Erase(Node* pos) //删除

{

if(NULL == _head || NULL == pos)

{

return;

}

if(_head == _tail )

{

if(_head == pos)

{

delete pos;

_head = _tail = NULL;

return;

}

}

if(pos == _head)

{

_head = _head->_next;

_head->_prev = NULL;

delete pos;

return;

}


if(pos == _tail)

{

_tail = _tail->_prev;

_tail->_next = NULL;

delete pos;

return;

}


pos->_prev->_next = pos->_next;

pos->_next->_prev = pos->_prev;

delete pos;

}

--------------------------------test.cpp----


#define _CRT_SECURE_NO_WARNINGS 


#include "DList.h"


/*

 * 测试

 * PushBack() PopBack() operator<<

 */

void test1()

{

DList l1;

l1.PushBack(1);

l1.PushBack(2);

l1.PushBack(3);

l1.PushBack(4);

cout<<l1<<endl;

l1.PopBack();

cout<<l1<<endl;

l1.PopBack();

cout<<l1<<endl;

l1.PopBack();

cout<<l1<<endl;

l1.PopBack();

cout<<l1<<endl;

l1.PopBack();

cout<<l1<<endl;

l1.PopBack();


}


/*

 * 测试

 * void DList::PopBack()

 * void DList::PopFront()

 */

void test2()

{

DList l1;

l1.PushFront(1);

cout<<l1<<endl;

l1.PushFront(2);

cout<<l1<<endl;

l1.PushFront(3);

cout<<l1<<endl;

l1.PushFront(4);

cout<<l1<<endl;

l1.PopFront();

cout<<l1<<endl;

l1.PopFront();

cout<<l1<<endl;

l1.PopFront();

cout<<l1<<endl;

l1.PopFront();

cout<<l1<<endl;

l1.PopFront();

cout<<l1<<endl;

l1.PopFront();

cout<<l1<<endl;

l1.PopFront();

cout<<l1<<endl;

}


/*

 * 测试

 * Node* DList::Find(const DataType& d)

 * void DList::Insert(Node* pos, const DataType& d)

 */

void test3()

{

DList l1;

l1.PushBack(1);

l1.PushBack(2);

l1.PushBack(3);

l1.PushBack(4);

cout<<l1<<endl;


cout<<l1.Find(-1)<<endl;

cout<<l1.Find(1)->_data<<endl;

cout<<l1.Find(2)->_data<<endl;

cout<<l1.Find(3)->_data<<endl;

cout<<l1.Find(4)->_data<<endl;


l1.Insert(NULL,1);

cout<<l1<<endl;

l1.Insert(l1.Find(1),5);

cout<<l1<<endl;

l1.Insert(l1.Find(2),6);

cout<<l1<<endl;

l1.Insert(l1.Find(3),7);

cout<<l1<<endl;

l1.Insert(l1.Find(4),8);

cout<<l1<<endl;


}


/*

 * 测试

 * void DList::Sort()

 * void DList::Reverse()

 */

void test4()

{

DList l1,l2,l3;

l1.PushBack(1);

l1.PushBack(2);

l1.PushBack(3);

l1.PushBack(4);

l2.PushBack(1);

l2.PushBack(2);

cout<<l1<<endl;

cout<<l2<<endl;

cout<<l3<<endl;


l1.Reverse();

cout<<l1<<endl;

l2.Reverse();

cout<<l2<<endl;

l3.Reverse();

cout<<l3<<endl;


l1.Sort();

cout<<l1<<endl;

l2.Sort();

cout<<l2<<endl;

l3.Sort();

cout<<l3<<endl;

}


/*

 * 测试

 * void DList::RemoveAll(const DataType& d)

 * void DList::RemoveAll(const DataType& d)

 */

void test5()

{

DList s1;

s1.PushBack(1);

s1.PushBack(1);

s1.PushBack(2);

s1.PushBack(3);

s1.PushBack(4);

s1.PushBack(1);

s1.PushBack(2);

s1.PushBack(3);

s1.PushBack(4);

s1.PushBack(1);

s1.PushBack(1);

cout<<s1<<endl;

cout<<"================="<<endl;


//s1.Remove(0);

//cout<<s1<<endl;

//s1.Remove(1);

//cout<<s1<<endl;

//s1.Remove(3);

//cout<<s1<<endl;

//s1.Remove(4);

//cout<<s1<<endl;


s1.RemoveAll(5);

cout<<s1<<endl;

s1.RemoveAll(1);

cout<<s1<<endl;

}


/*

 * 测试

 * void DList::Erase(Node* pos) //删除 

 */

void test6()

{

DList l1;

l1.PushBack(1);

l1.PushBack(2);

l1.PushBack(3);

l1.PushBack(4);

l1.PushBack(5);

cout<<l1<<endl;


l1.Erase(NULL);

cout<<l1<<endl;

l1.Erase(l1.Find(1));

cout<<l1<<endl;

l1.Erase(l1.Find(5));

cout<<l1<<endl;

l1.Erase(l1.Find(3));

cout<<l1<<endl;



}

int main()

{

test6();

getchar();

return 0;

}