数据结构——链表

来源:互联网 发布:淘宝上悦诗风吟专柜 编辑:程序博客网 时间:2024/05/16 12:20
学数据结构之前按照自己的理解写的链表模板,不好勿喷。图省事就把所有的函数写在了类里面,这不是个好的做法
/* * 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_ */


0 0