常见笔试面试题:实现一个递增排序的单链表

题目:实现一个递增排序的单链表(不允许重复),即每次向链表中插入一个或多个元素后都能保证链表仍是递增有序的,在此基础上实现一些基本操作,如插入元素、清空元素、判断两个链表是否相等及查找某个指定的元素。


为了实现该功能,首先定义一个头文件linked_list.h声明单链表的基本操作:

#ifndef LINKED_LIST_H_
#define LINKED_LIST_H_

#define _INVALID 0xFFFFFFFF

class linked_list {

	// value
	unsigned int data;
	
	// pointer to the next node in list
	linked_list *next;

public:

	// instantiated a linked list with the element value. If value is not specified
	// an empty list is instantiated
	linked_list(unsigned int value = _INVALID);

	// destructor
	~linked_list();

	// check if the list is empty
	bool empty();

	// insert a value into the list.
	void insert(unsigned int value);

	// insert all the values from list into the current linked list.
	void add(linked_list *list);

	// get the size of the linked list.
	int size();

	// is the current set equal to s (does it contains the same elements?)
	bool equal(linked_list *l);

	// //removes all elements from the list.
	void clear();

	// returns the value associated with the current element of the list.
	unsigned int value();

	// returns the next element in the linked list
	linked_list *succ();

	// is data in linked_list?
	bool find(unsigned int value);
};

inline unsigned int linked_list::value() { return data; } 

inline linked_list *linked_list::succ() { return next; }

#endif /* LINKED_LIST_H_ */

最重要的是如何实现插入一个元素,需要分情况讨论:

(1)如果链表为空,则直接插入返回;

(2)如果链表不为空,需要分三种情形:

  • 插入的值小于链表头结点值:这是最简单的情形,那么直接将其插入头结点之前即可。为了实现更加简单方便,这里采用的方法是:交换头结点与插入结点的值,然后直接将交换后的值插入到头结点之后即可;
  • 插入的值等于链表头结点值:直接返回,因为不允许重复;
  • 插入的值大于链表头结点值:这时就需要与头结点后面的值继续比较,寻找待插入的位置,可以使用递归的方法。需要注意的是,这时需要判断头结点的下一节点是否为空,如果为空,直接插入,否则进行判断,若插入值小于next节点值,则直接将插入值插入头结点与next节点之间即可,否则就递归查询,继续后面节点的比较和判断。


其它的操作都很简单,基本上每个操作都可以使用递归完成,详细实现代码如下。

实现该头文件的linked_list.cpp文件如下:

#include "linked_list.h"
#include "util.h"

linked_list::linked_list(unsigned int value) {
	data = value;
	next = NULL;
}

linked_list::~linked_list() {
	if(next != NULL) delete next;
}

// 不能通过next是否为NULL来判断是否为空,因为一个结点时next也为空,只能根据还没有结点时data的默认值
bool linked_list::empty() {
	return (data == _INVALID);
}

// 插入后保持链表所有节点仍是递增排序,且不允许插入data相同的节点
void linked_list::insert(unsigned int value) {
	if(this->empty()) {
		data = value;
		return;
	} 

	// if not empty
	if(value < data) { // 最简单的情形,小于头结点值
		linked_list *listnode = new linked_list(data);
		data = value;
		listnode->next = next;
		next = listnode;
	} else if(value == data) {
		return;
	} else {  // value > data
		if(next == NULL) { // 必须判断
			next = new linked_list(value);
		} else if(value < next->data) {
			linked_list *listnode = new linked_list(value);
			listnode->next = next;
			next = listnode;
		} else {
			next->insert(value);
		}
	}

	linked_list *listnode = new linked_list(value);
	listnode->next = this->next;
	this->next = listnode;
}

void linked_list::add(linked_list *list) {
	linked_list *ll = list;

	while(ll != NULL && !ll->empty()) {
		this->insert(ll->data);
		ll = ll->next;
	}
}

int linked_list::size() {
	if(this->empty())
		return 0;

	int s = 0;
	linked_list *l = this;
	while(l) {
		s++;
		l = l->next;
	}

	return s;
}

//int linked_list::size() {
//	if(this->empty())
//		return 0;
//	if(next == NULL)
//		return 1;
//
//	return 1 + next->size();
//}

bool linked_list::equal(linked_list *l) {
	if(size() != l->size())
		return false;

	linked_list *pl1 = this, *pl2 = l;

	while(pl1 && pl2) {
		if(pl1->data != pl2->data) {
			return false;
		}
		pl1 = pl1->next;
		pl2 = pl2->next;
	}

	return true;
}

//bool linked_list::equal(linked_list *l) {
//	if(l == NULL && !empty())
//		return false;
//	if(data != l->data)
//		return false;
//	if (next == NULL && l->next == NULL)
//		return true;
//	if (next == NULL || l->next == NULL)
//		return false;
//
//	return next->equal(l->next);
//}

void linked_list::clear() {
	// 首先记得得释放所有节点的空间
	if(next != NULL) delete next;

	data = _INVALID;
	next = NULL;
}

bool linked_list::find(unsigned int value) {
	if(data == value)
		return true;
	if(next == NULL)
		return false;

	return next->find(value);
}


你可能感兴趣的:(C++,递归,面试题,单链表,笔试题)