算法导论之链表

最近在学习算法导论,为了督促自己 就把学习过程中的代码记录下来。

就先从最简单的链表写起,准确的说应该是双链表。大致先简单的介绍一下链表的优缺点,以便在后面对应的数据结构中使用该结构。

优点:链表在内存中存储并不是连续的,可以很方便的进行插入和删除操作。

缺点:由于链表的不连续存储特性,导致索引操作不能使用下标进行,因此对链表进行搜索操作时间复杂度是O(n)级别的。

以下是自己根据算法导论上面的设计书写的代码,链表的操作有插入、删除、搜索。

头文件:

//name:myList1.h

#ifndef MY_LIST1_H
#define MY_LIST1_H

#include<iostream>
#include<memory>

using namespace std;

template<typename T>
class myList1{
	struct list_node{
		list_node* prev;
		T data;
		list_node* next;

		list_node(){
			prev = NULL;
			next = NULL;
		}

		list_node(list_node* node){
			this->data = node->data;
			this->prev = node->prev;
			this->next = node->next;
		}

		list_node(T value){
			this->data = value;
			this->next = this->prev = NULL;
		}
	};

private:
	list_node* list_head; //链表的头
	//list_node* list_rear; //链表的尾

	int count_size; //链表中元素的个数

public:

	myList1(){
		list_head = NULL;
		count_size = 0;
	}

	~myList1(){ }

	//给链表的头部插入节点x
	void insert_head(list_node* x){
		x->next = list_head;
		if (list_head != NULL)
			list_head->prev = x;
		list_head = x;
		x->prev = NULL;
		count_size++;
	}

	void insert_head(T value){
		//----------------------------------------------------------
		//此处如果使用 list_node* x=list_node(value)
		//表示在栈中对x分配了内存,那么后面的list_head指向x之后
		//当x的函数块结束,x会被释放,list_head将变成野指针
		//因此必须使用new在堆中进行内存分配
		//---------------------------------------------------------
		list_node* x = new list_node(value);
		//shared_ptr<list_node> x = make_shared<list_node>(value);
		insert_head(x);
	}

	//搜索链表中第一个值为value的节点,并返回该节点的指针
	list_node* search_first_value(T value){
		list_node* temp = list_head;
		while (temp != NULL&&temp->data != value)
			temp = temp->next;
		return temp;
	}

	//删除链表中的节点x
	void delete_list_node(list_node* x){
		if (x->prev != NULL)
			x->prev->next = x->next;
		else
			list_head = x->next;
		if (x->next != NULL)
			x->next->prev = x->prev;
		count_size--;
	}

	//删除链表中第一个值为value的节点
	void delete_value(T value){
		list_node* delete_node = search_first_value(value);
		delete_list_node(delete_node);
		count_size--;
	}

	//显示链表中的数据data
	void display(){
		list_node* temp = list_head;
		while (temp != NULL){
			cout << temp->data << " ";
			temp = temp->next;
		}
		cout << endl;
	}

};

#endif

以下是测试的代码:

//name:main.c

#include<vector>
#include"myList1.h"

int main(){
	vector<int> test_data = {1,2,3,4,5}; 
	myList1<int> test_list = myList1<int>();

	for (int i = 0; i < test_data.size(); i++){
		test_list.insert_head(test_data[i]);
	}

	test_list.display();

	test_list.delete_value(1);
	test_list.display();

	return 0;
}

本来打算自己实现一下STL中关于List源码,但是能力有限,还需继续学习才能完成,下面在给出STL中List的相关函数及功能

push_back()、push_front():把某个值插入到list的尾部或者头部。
pop_back()、pop_back():删除list中的第一个或者最后一个元素。
insert():这个方法即可以把某个元素插入到指定的位置,也可以把一个指定范围的多个元素插入到list中迭代器所指向的位置,另外还可以把某个具体的多个备份插入到list中迭代器所指定的位置。
erase():主要用来删除list中的元素,即可以删除list中某个位置的单个元素,也可以删除list中的某个范围内的所有元素对象。
clear():该函数主要用来删除list中的所有元素。

merge()函数:用于把两个list对象合并成一个list对象。

remove()函数:删除list中的对象可以使用pop_back(),pop_front(),erase()和clear()等常见函数,在list中同时提供了remove()函数,函数remove()的语法格式为void remove(const T& value)

remove会把list对象中所有等于参数的元素删除。如果list存储的是类,且类中有指针,由于remove不会自动删除类的存储空间,所以一般不能用remove方法对类元素直接删除。

remove_if():remove()函数用于无条件删除所有等于参数值的list成员元素,有时需要满足一定的条件才能把它删除,这时需要使用条件删除函数:remove_if(),函数remove的语法格式为templace<class Pred>void remove_if(Pred pr)

sort()函数:偏于list对象排序,在list成员函数中专门定义了一个成员函数sort,用于对list对象进行排序,函数sort的语法格式为void sort(); void sort(greater<T> pr)

splice()函数:merge()函数可以将两个list对象合并在一起,但是该函数不太灵活,list容器类提供了另一个函数splice。格式为void splice(iterator position, list& x); void splice(iterator position, list& x, iterator it); void splice(iterator position, list& x, iterator first, iterator last)




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值