您的位置:首页 > 理论基础 > 数据结构算法

数据结构——链表

2016-03-03 16:24 483 查看
学数据结构之前按照自己的理解写的链表模板,不好勿喷。图省事就把所有的函数写在了类里面,这不是个好的做法
/*
* 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_ */
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: