数据结构——链表

学数据结构之前按照自己的理解写的链表模板,不好勿喷。图省事就把所有的函数写在了类里面,这不是个好的做法
/*
 * My_list.h
 *
 *  Created on: 2016年2月3日
 *      Author: triose
 */
#include<iostream>
using namespace std;

#ifndef MY_LIST_H_
#define MY_LIST_H_


/* Define of  elements */
template <class T>
class ListElmt {
public:
	T data;
	ListElmt * next;
	ListElmt(T data_) {
		data = data_;
		next = NULL;
	}
};

/* Define of My_list */
template <class T>
class My_list {
private :
	int size;
	ListElmt<T> *head;
	ListElmt<T> *tail;
public :
	My_list() {												//构造函数
		size = 0;
		head = NULL;
		tail = NULL;
	}
	
	~My_list() {												//析构函数,移除并删除每个结点(删除操作在移除函数里就已完成)
		this->delete_all();
	}
	
	void ins_next(ListElmt<T> *element, int pos) {				//插入函数,把element插入到第pos个结点的后面
		if(size == 0) {										//空表的情况
			head = element;
			tail = element;
			size ++;
			return ;
		}
		if(pos == -1 ) {										//插入表头
			element->next = head;
			head = element;
			size ++;
			return ;
		}
		ListElmt<T> *current_elmt = head;						//插入表中
		int index = 0;
		while(current_elmt->next != NULL && index < pos) {
			index ++;
			current_elmt = current_elmt->next;
		}
		if(index == pos) {
			element->next = current_elmt->next;
			current_elmt->next = element;
			if(pos == size - 1) {
				tail = element;
			}
			size++;
			return ;
		}
	}

	ListElmt<T> * rem_next(int pos) {							//移除函数,移除并返回pos位置之后的结点
		ListElmt<T> * re_element = head;
		ListElmt<T> * delete_element = head;
		if(size == 0) {										//空表,操作失败
			return NULL;
		}
		if(pos == -1) {										//移除表头元素
			head = head->next;
			size--;
			delete delete_element;
			return re_element;
		}
		ListElmt<T> *current_elmt = head;						//移除其他位置元素
		int index = 0;
		while(current_elmt->next != NULL && index < pos) {
			index++;
			current_elmt = current_elmt->next;
		}
		if(index == pos) {
			re_element = current_elmt->next;
			delete_element = current_elmt->next;
			current_elmt->next = current_elmt->next->next;
			if(pos == size - 2) {
				tail = current_elmt;
			}
			delete delete_element;
			size--;
		}
		return re_element;
	}

	void delete_all() {									//移除所有元素
		while(size > 0) {
			this->rem_next(-1);
		}
	}
	
	void output(){										/* For debug	*/
		ListElmt<T> * current_elmt = head;
		int index = 0;
		while((index++) < size) {
			cout << current_elmt->data << ' ';
			current_elmt = current_elmt->next;
		}
		cout << endl;
		cout << "tou:\n" << head->data << endl;
		cout << "wei:\n" << tail->data << endl;
		cout << "size:\n" << size << endl;
	}
};


#endif /* MY_LIST_H_ */

接下来是双向链表的模板

/*
 * DList.h
 *
 *  Created on: 2016年2月3日
 *      Author: triose
 */

#ifndef DLIST_H_
#define DLIST_H_

#include <iostream>
using namespace std;

template <class T>
class DListElmt {
public:
	T data;
	DListElmt * prev;
	DListElmt * next;
	DListElmt(T data_) {
		data = data_;
		prev = NULL;
		next = NULL;
	}
};

template <class T>
class DList {
private:
	DListElmt<T> *head;
	DListElmt<T> *tail;
	int size;
public:

	DList() {
		head = NULL ;
		tail = NULL;
		size = 0;
	}

	~DList() {
		if(size)
			delete_all();
	}

	/*	public Interface*/
	void ins_next(DListElmt<T> * element, int pos) {
		if(size == 0) {
			head = element;
			tail = element;
			size++;
			return ;
		}
		if(pos == -1) {
			element->next = head;
			head->prev = element;
			head = element;
			size++;
			return ;
		}
		DListElmt<T> *current_elmt = head;
		int index = 0;
		while(current_elmt->next != NULL && index < pos) {
			index++;
			current_elmt = current_elmt->next;
		}
		if(index == pos) {
			element->prev = current_elmt;
			element->next = current_elmt->next;
			current_elmt->next = element;
			if(current_elmt->next->next != NULL) {
				current_elmt->next->next->prev = element;
			}
			if(pos == size - 1) {
				tail = element;
			}
			size++;
			return ;
		}
	}

	DListElmt<T> *rem_next(int pos) {
		DListElmt<T> * re_element = head;
		DListElmt<T> * delete_elmt = head;
		if(size == 0) {
			return NULL;
		}
		if(pos == -1) {
			head = head->next;
			delete delete_elmt;
			size--;
			return re_element;
		}
		DListElmt<T> * current_elmt = head;
		int index = 0;
		while(current_elmt->next != NULL && index < pos) {
			current_elmt = current_elmt->next;
			index++;
		}
		if(index == pos) {
			delete_elmt = current_elmt->next;
			re_element = current_elmt->next;
			current_elmt->next = current_elmt->next->next;
			if(current_elmt->next != NULL)
				current_elmt->next->prev = current_elmt;
			if(pos == size - 2) {
				tail = current_elmt;
			}
			size--;
		}
		return re_element;
	}

	void delete_all() {
		while(size > 0) {
			this->rem_next(-1);
		}
	}

	void output() {										/*For debug*/
		cout << "从前往后:" << endl;
		DListElmt<T> * current_elmt = head;
		for(int i = 0; i < size; i++) {
			cout << current_elmt->data << " " ;
			current_elmt = current_elmt->next;
		}
		cout << endl;
		cout << "从后往前:" << endl;
		current_elmt = tail;
		for(int i = 0; i < size; i++) {
			cout << current_elmt->data << " ";
			current_elmt = current_elmt->prev;
		}
		cout << endl;
		cout << "head : " << endl;
		cout << head->data << endl;
		cout << "tail : " << endl;
		cout << tail->data << endl;
		cout << "size : " << endl;
		cout << size << endl;
	}
};



#endif /* DLIST_H_ */

以下为2016.4.8编辑:

贴一个数据结构作业的代码,双向链表,纯C。

/*
 * List.h
 *
 *  Created on: 2016年3月28日
 *      Author: Triose
 */

#ifndef LIST_H_
#define LIST_H_

#include<stdlib.h>
#include"Book.h"


typedef struct ListElmt_ {
	void *data;
	struct ListElmt_ *next;
	struct ListElmt_ *prev;
}ListElmt;
#define pfElmt(current_elmt) (printf("%s\t%s\t%lf\n", ((Book*)(current_elmt->data))->ISBN, ((Book*)(current_elmt->data))->name, ((Book*)(current_elmt->data))->price))
#define pfElmt_to_file(current_elmt, fptr_out) (fprintf(fptr_out, "%s\t%s\t%lf\n", ((Book*)(current_elmt->data))->ISBN, ((Book*)(current_elmt->data))->name, ((Book*)(current_elmt->data))->price))



/* Public Interface. */
ListElmt * new_Elmt(const void *data_) {
	ListElmt * newelement = (ListElmt *) malloc (sizeof(ListElmt));
	newelement->data = (void *)data_;
	newelement->prev = NULL;
	newelement->next = NULL;
	return newelement;
}

typedef struct List_ {
	ListElmt * head;
	ListElmt * tail;
	int size;
}List;

/* Public Interface. */
#define List_size(list) ((list)->size)
#define List_head(list) ((list)->head)
#define List_tail(list) ((list)->tail)

/* List_init. */
void List_init(List * list) {
	list->head = NULL;
	list->tail = NULL;
	list->size = 0;
}


/* List_ins. */
int List_ins(List * list, ListElmt * newelement, int pos) {
	pos--;
	if(pos < 0 || pos > list->size) {
		return -1;
	}
	if(pos && !list->size) {
		return -1;
	}
	if(!pos) {
		newelement->next = list->head;
		if(list->head) {							//如果list->head != NULL 证明不是空表,至少有一个元素
			list->head->prev = newelement;
		}
		else {										//否则就是空表,只需让尾指针也指向newelement即可
			list->tail = newelement;
		}
		list->head = newelement;					//头指针指向插入表头的节点
		list->size++;								//维护表长
		return 0;									//正确返回
	}
	ListElmt * current_elmt = list->head;
	int index = 0;
	while(current_elmt->next && index < pos - 1) {
		index++;
		current_elmt = current_elmt->next;
	}
	if(index == pos - 1) {							//此时current_elmt指向插入位置的前一个元素
//		current_elmt->next = newelement;
		newelement->next = current_elmt->next;
		newelement->prev = current_elmt;
		if(current_elmt->next) {					//如果current_elmt->next != NULL 那么current_elmt不是表尾元素
			current_elmt->next->prev = newelement;
		}
		else {										//current_elmt是表尾元素
			list->tail = newelement;
		}
		current_elmt->next = newelement;
		list->size++;								//维护表长
		return 0;									//正确返回
	}
	return -1;										//除所有限定正确情况之外全都是不正确
}

/* List_rem. */
int List_rem(List * list, int pos) {
	pos--;
	if(!list->size) {								//空表
		return -1;
	}
	if(pos < 0 || pos >= list->size) {				//位置不正确
		return -1;
	}
	if(!pos) {										//删除头结点
		ListElmt *delete_elmt = list->head;
		list->head = list->head->next;				//头指针指向第一个元素
		if(list->head) {							//如果第一个元素不是空,即删除第0个元素之后链表还有元素
			list->head->prev = NULL;				//把现在的头结点的前指针置空
		}
		else {										//否则,即链表之有要删除的一个元素,那么把链表尾指针也置空
			list->tail = NULL;
		}
		free(delete_elmt);							//删除待删除元素
		list->size--;
		return 0;									//返回正确
	}
	ListElmt *current_elmt = list->head;
	int index = 0;
	while(current_elmt->next && index < pos - 1) {	//遍历,令current_elmt指向被删除的前一个元素
		current_elmt = current_elmt->next;
		index++;
	}
	if(index == pos - 1) {
		ListElmt *delete_elmt = current_elmt->next;
		current_elmt->next = current_elmt->next->next;
		if(current_elmt->next) {					//同理
			current_elmt->next->prev = current_elmt;
		}
		else {
			list->tail = current_elmt;
		}
		free(delete_elmt);
		list->size--;
		return 0;
	}
	return -1;										//所有非限定情况全部返回错误
}


/* List_Inverse. */
void List_Inverse(List * list) {
	if(!list->size || list->size == 0) {			//空表或者单元素表直接返回
		return ;
	}
	/* 至少有两个元素. */
	ListElmt * current_elmt = list->head;
	ListElmt * next_elmt = current_elmt->next;
	int index = 0;
	while(index < list->size - 2) {					//交换前后指针
		ListElmt * tmp_elmt = next_elmt->next;
		next_elmt->prev = tmp_elmt;
		next_elmt->next = current_elmt;
		current_elmt = next_elmt;
		next_elmt = tmp_elmt;
		index++;
	}
	list->head->prev = list->head->next;			//处理头尾指针和指向
	list->head->next = NULL;
	list->tail->next = list->tail->prev;
	list->tail->prev = NULL;
	ListElmt *tmp_elmt = list->head;
	list->head = list->tail;
	list->tail = tmp_elmt;
	return ;
}

/* List_get_elmt. */
ListElmt * List_get_elmt(List * list, int pos) {
	pos--;
	if(pos < 0 || pos >= list->size){
		return NULL;
	}
	ListElmt * current_elmt = list->head;
	int index = 0;
	while(index < pos) {
		index++;
		current_elmt = current_elmt->next;
	}
	return current_elmt;
}

/*****************************************************************************
 * 链表的快速排序采用快排并不是最优方案(对,我亲身实践了,因为指针的确会乱而且不止是交换数据那么简单,所以我放弃采用快排而自学了归并)
 * c++ list头文件里默认排序是堆排序。
 * 这三个函数是我读了list头文件里的_Sort函数写出来的。
 * 毕竟这不是工业级代码。。。所以可能会有Bug
 *****************************************************************************/

int cmp(const ListElmt * u, const ListElmt * v) {		//用于归并排序的比较函数
	return (((Book *)u->data)->price > ((Book *)v->data)->price ? 1 : 0);
}

ListElmt * get_mid(ListElmt * start, int lenth) {		//给定头结点,找出中间节点的函数
	int mid = 1;
	ListElmt * current_elmt = start;
	while(mid < lenth ) {
		mid++;
		current_elmt = current_elmt->next;
	}
	return current_elmt;
}
void cut_down(ListElmt * elmt, int len) {				//切断指向范围之外的指针,主要是头结点的prev指针和尾结点的next指针
	ListElmt * current_elmt = elmt;
	current_elmt->prev = NULL;
	int i = 1;
	while(i < len) {
		i++;
		current_elmt = current_elmt->next;
	}
	current_elmt->next = NULL;
}

ListElmt * merge(ListElmt * u, ListElmt * v, int (*cmp)(const ListElmt *u, const ListElmt *v), int uLen, int vLen) {
	/*这个函数用来归并两段链表,两段链表的头结点分别是u和v. */
	cut_down(u, uLen);					//为了避免死循环,必须切断指向这两段链表范围之外的指针
	cut_down(v, vLen);
	int i = 0,
		j = 0;
	ListElmt * _newstart = v;			//先把v作为合并后的头结点
	if(cmp(u, v)) {						//如果u比v大(这里以由降序为例),则合并后的头节点为u
		_newstart = u;
	}
	ListElmt * index = 0;				//用来连接各个节点的指针
	while(i < uLen && j < vLen) {		//合并过程,连接各个指针
		if(cmp(u,v)) {
			if(!index) {
				index = u;
			}
			else {
				index->next = u;
				u->prev = index;
				index = index->next;
			}
			i++;
			if(i == uLen) {
				index->next = v;
				v->prev = index;
			}
			u = u->next;
		}
		else {
			if(!index) {
				index = v;
			}
			else {
				index->next = v;
				v->prev = index;
				index = index->next;
			}
			j++;
			if(j == vLen) {
				index->next = u;
				u->prev = index;
			}
			v = v->next;
		}
	}
	return _newstart;
}

ListElmt * merge_sort(List * list, ListElmt * start, ListElmt * end, int (*cmp)(const ListElmt *u, const ListElmt *v), int lenth) {
	if(lenth < 2) {									//只剩一个元素的时候,直接return就好
		return start;
	}
	int uLen = lenth / 2 + (lenth % 2);				//二分的两部分的长度
	int vLen = lenth - uLen;
	ListElmt * mid = get_mid(start, uLen);			//二分之前首先得找到中间的元素
	ListElmt * _newstart = merge(merge_sort(list, start, mid, cmp, uLen), merge_sort(list, mid->next, end, cmp, vLen), cmp, uLen, vLen);
	list->head = _newstart;							//更新原链表的头结点和尾结点(这段比较啰嗦)
	ListElmt * current_elmt = list->head;
	while(current_elmt->next) {
		current_elmt = current_elmt->next;
	}
	list->tail = current_elmt;
	return _newstart;
}


void find_name(List *list, char * name_) {
	ListElmt * current_elmt = list->head;
	int index = 0;
	while(current_elmt) {							//遍历链表,所有重名的书全部输出
		if(strcmp(((Book *)current_elmt->data)->name, name_) == 0) {
			index = 1;
			printf("%s\t%s\t%lf\n", ((Book *)current_elmt->data)->ISBN, ((Book *)current_elmt->data)->name, ((Book *)current_elmt->data)->price);
		}
		current_elmt = current_elmt->next;
	}
	if(!index) {
		printf("找不到名字为:%s的书\n", name_);
	}
	return ;
}

void find_ISBN(List *list, char * isbn_) {
	ListElmt * current_elmt = list->head;
	int index = 0;
	while(current_elmt) {							//遍历链表,所有ISBN相同的全部输出(不排除有相同的ISBN)
		if(strcmp(((Book *)current_elmt->data)->ISBN, isbn_) == 0) {
			index = 1;
			printf("%s\t%s\t%lf\n", ((Book *)current_elmt->data)->ISBN, ((Book *)current_elmt->data)->name, ((Book *)current_elmt->data)->price);
		}
		current_elmt = current_elmt->next;
	}
	if(!index) {
		printf("找不到标号为:%s的书\n", isbn_);
	}
	return ;
}

/* List_destroy. */
void List_destroy(List * list) {					//析构函数,移除所有节点
	while(list->size) {
		List_rem(list, 1);
	}
}

#endif /* LIST_H_ */


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值