C++学习笔记(Day16 实验九)

//
// Created by BoBo on 2021/10/26.
//

#ifndef NODE_H
#define NODE_H
template <class T>
class Node {
private:
    Node<T>* next;
public:
    T data;
    Node() {data = 0;next = NULL;}
    Node(const T& data, Node<T>* next = 0);
    void insertAfter(Node<T>* p);
    Node<T>* deleteAfter();
    Node<T>* nextNode();
    const Node<T>* nextNode() const;
};
template <class T>
Node<T>::Node(const T &data,Node<T> *next):data(data),next(next){}

template <class T>
Node<T>* Node<T>::nextNode(){
    return next;
}
template<class T>
const Node<T>* Node<T>::nextNode() const{
    return next;
}

template <class T>
void Node<T>::insertAfter(Node<T> *p) {
    p->next = next;
    next = p;
}
template <class T>
Node<T>* Node<T>::deleteAfter() {
    Node<T>* temPtr = next;
    if(next == 0)
        return 0;
    next = temPtr->next;
    return temPtr;
}
#endif //NODE_H
#include <iostream>
#include "Node.h"
using namespace std;

int main() {
    int a[10];
    Node<int> n[10];
    cout << "输入10个整数:" << endl;
    for(int i = 0;i<10;i++){
        cin >> a[i];
    }
    for(int i =0;i<9;i++){
        n[i].data = a[i];
        n[i].insertAfter(&n[i+1]);
    }
    n[9].data = a[9];
    Node<int>*  np = &n[0];
    while(np !=NULL){
        cout << np->data<< " ";
        np = np->nextNode();
    }
    cout << endl;
    int f;
    cout<<"请输入要查找的数: ";
    cin >> f;
    Node<int> p(0,&n[0]);//定义了一个新的对象,其中指针指向数组n的首地址,调用当前对象的nextNode方法返回地址,用此指针调用数组n中的data
    np = &p;
    while(np->nextNode()!=NULL){
        while(np->nextNode()->data == f)
            np->deleteAfter();
        np = np->nextNode();
    }
    cout << "删除后的链表: " <<endl;
    np=&n[0];
    while(np != NULL){
        cout << np->data<<" ";
        np = np->nextNode();
    }
    np = &p;
    while(np->nextNode()!= NULL)
        np->deleteAfter();
    cout << endl;
    return 0;
}

实验9-2

编写程序实现链表类,在测试程序中声明两个整型链表A和B,分别插入5个元素,然后把B中的元素加入A的尾部。

#ifndef NODE_H_
#define NODE_H_

template <class T>
class Node {
private:
	T data;
public:
	Node* next;
	Node();
	Node(const T& data, Node<T>* nt = 0);
//	Node(T data, Node<T>* n = NULL);
	T& getData();
};

template <class T>
Node<T>::Node() {
	data = 0;
	next = NULL;
}

template <class T>
Node<T>::Node(const T& d, Node<T>* nt) {
	data = d;
	next = nt;
}

template <class T>
T& Node<T>::getData() {
	return data;
}

#endif //NODE_H_
#ifndef LINK_H_
#define LINK_H_

#include "node.h"

/*
* 在LinkedList的设计中,采用了附加指针front和rear,即链表的结构为front->a1->a2->...->rear
* 只有在析构函数中才删除这两个指针,其余的时间这两个指针都是存在的,其中的数据始终为0,不存储用户数据
*/
template <class T>
class LinkedList {
private:
	Node<T> *front, *rear; //表头和表尾指针
	Node<T> *prevPtr, *currPtr; //记录表当前遍历位置的指针,由插入和删除操作更新
	int size; //表中元素个数
	int position; //当前元素在表中的位置序号。由函数reset使用

	Node<T>* newNode(const T& item, Node<T> *ptrNext = NULL); //生成新节点,数据与为item,指针域为prtNext
	void freeNode(Node<T> *p); //释放节点

	void copy(const LinkedList<T>& L); //将链表L复制到当前表(假设当前表为空),被复制构造函数和operator=调用

public:
	LinkedList(); //构造函数
	LinkedList(const LinkedList<T>& L); //复制构造函数
	~LinkedList(); //析构函数
	LinkedList<T>& operator = (const LinkedList<T>& L); //重载赋值运算符

	int getSize() const; //返回链表中元素个数
	bool isEmpty() const; //链表是否为空

	void reset(int pos = 0); //初始化游标的位置
	void next(); //使游标移动到下一个节点
	bool endOfList() const; //游标是否移动到链尾
	int currentPosition() const; //返回游标当前的位置
	
	void insertFront(const T& item); //在表头插入节点
	void insertRear(const T& item); //在表尾插入节点
	void insertAt(const T& item); //在当前节点之前插入节点
	void insertAfter(const T& item); //在当前节点之后插入节点

	T deleteFront(); //删除头节点
	void deleteCurrent(); //删除当前节点
	
	T& data(); //返回对当前节点成员数据的引用
	const T& data() const; //返回对当前节点成员数据的常引用

	void clear(); //清空链表:释放所有节点的内存空间,被析构函数和operator=使用
};

//生成新节点,数据与为item,指针域为prtNext
template <class T>
Node<T>* LinkedList<T>::newNode(const T& item, Node<T> *ptrNext) {
	Node<T> *n = new Node<T>(item, ptrNext);
	return n;
}

//释放节点
template <class T>
void LinkedList<T>::freeNode(Node<T> *p) {
	Node<T>* temp = front;
	while (temp->next != p) {
		temp = temp->next;
		if (temp == currPtr)
			position ++;
	}
	temp->next = p->next;
	if (currPtr == p)
		currPtr = currPtr->next;
	if (prevPtr == p) {
		prevPtr = prevPtr->next;
		currPtr = currPtr->next;
	}
	delete p;
	size --;
	position --;
}

//将链表L复制到当前表(假设当前表为空),被复制构造函数和operator=调用
template <class T>
void LinkedList<T>::copy(const LinkedList<T>& L) {
	Node<T> *temp = L.front, *ptr = front;
	while (temp != L.rear) {
		ptr->next = new Node<T>(temp->getData, NULL);
		ptr = ptr->next;
		temp = temp->next;
	}
	ptr->next = rear;
	size = L.getSize();
	position = L.currentPosition();
}

//构造函数
template <class T>
LinkedList<T>::LinkedList() {
	front = new Node<T>();
	rear = new Node<T>();
	front->next = rear;
	currPtr = rear;
	prevPtr = front;
	size = 0; //不计算front和rear
	position = 0; //在front下一个元素视为0
}

//复制构造函数
template <class T>
LinkedList<T>::LinkedList(const LinkedList<T>& L) {
	clear();
	copy(L);
}

//析构函数
template <class T>
LinkedList<T>::~LinkedList() {
	LinkedList::clear();
	delete front;
	delete rear;
}

//重载赋值运算符
template <class T>
LinkedList<T>& LinkedList<T>::operator = (const LinkedList<T>& L) {
	clear();
	copy(L);
}

//返回链表中元素个数
template <class T>
int LinkedList<T>::getSize() const {
	return size;
}

//链表是否为空
template <class T>
bool LinkedList<T>::isEmpty() const {
	return (size == 0);
}

//初始化游标的位置
template <class T>
void LinkedList<T>::reset(int pos) { //初始化游标位置
	if (pos > size) {
		cout << "越界,无法访问" << endl;
		return;
	}
	int i = 0;
	prevPtr = front;
	currPtr = front->next;
	while (i < pos) {
		if (currPtr == rear) {
			cout << "越界,无法访问" << endl;
			return;
		}
		i ++;
		currPtr = currPtr->next;
		prevPtr = prevPtr->next;
	}
	position = pos;
}

//使游标移动到下一个节点
template <class T>
void LinkedList<T>::next() {
	if (currPtr == rear) {
		cout << "已经到达链表尾,无法移动" << endl;
		return;
	}
	currPtr = currPtr->next;
	prevPtr = prevPtr->next;
	position ++;
}

//游标是否移动到链尾
template <class T>
bool LinkedList<T>::endOfList() const {
	return (currPtr == rear);
}

//返回游标当前的位置
template <class T>
int LinkedList<T>::currentPosition() const {
	return position;
}

//在表头插入节点
template <class T>
void LinkedList<T>::insertFront(const T& item) {
	Node<T>* n = new Node<T>(item, front);
	front = n;
	size ++;
	position ++;
}

//在表尾插入节点
template <class T>
void LinkedList<T>::insertRear(const T& item) {
	Node<T>* temp = front;
	while (temp->next != rear)
		temp = temp->next;
	Node<T> *n = new Node<T>(item, rear);
	temp->next = n;
	size ++;
}

//在当前节点之前插入节点
template <class T>
void LinkedList<T>::insertAt(const T& item) {
	Node<T>* temp = new Node<T>(item, currPtr);
	prevPtr->next = temp;
	prevPtr = temp;
	size ++;
	position ++;
}

//在当前节点之后插入节点
template <class T>
void LinkedList<T>::insertAfter(const T& item) {
	Node<T>* temp = new Node<T>(item, NULL);
	temp->next = currPtr->next;
	currPtr->next = temp;
	size ++;
}

//删除头节点,实质是删除front->next
template <class T>
T LinkedList<T>::deleteFront() {
	if (front->next == rear) {
		cout << "没有节点可以删除" << endl; 
	}
	if (prevPtr == front->next) {
		prevPtr = prevPtr->next;
		currPtr = currPtr->next;
	}
	Node<T>* temp = front->next;
	T d = temp->getData();
	front->next = temp->next;
	delete temp;
	size --;
	if (front->next != rear)
		position --;
	return d;
}

//删除当前节点
template <class T>
void LinkedList<T>::deleteCurrent() {
	Node<T>* temp = currPtr;
	currPtr = currPtr->next;
	delete temp;
	size --;
}
	
//返回对当前节点成员数据的引用
template <class T>
T& LinkedList<T>::data() {
	return currPtr->getData();
}

//返回对当前节点成员数据的常引用
template <class T>
const T& LinkedList<T>::data() const {
	return currPtr->getData();
}

//清空链表:释放所有节点的内存空间,被析构函数和operator=使用
template <class T>
void LinkedList<T>::clear() {
	Node<T>* temp;
	while (front->next != rear) {
		temp = front->next;
		front->next = temp->next;
		delete temp;
	}
	size = 0;
	position = 0;
}

#endif //LINK_H_
#include "stdafx.h"

#include <iostream>
#include "link.h"
using namespace std;

int main()
{
	LinkedList<int> A, B;
    int i, item;
	
    cout << "请输入加入链表A的五个整数:";
	for (i = 0; i < 5; i ++) {
		cin >> item;
		A.insertRear(item);
	}
	cout << "请输入加入链表B的五个整数:";
	for (i = 0; i < 5; i ++) {
		cin >> item;
		B.insertRear(item);
	}
	cout << endl << "有序链表A中的元素为:";
	A.reset();
	while(!A.endOfList()) {
		cout << A.data() << "  ";
		A.next();
	}
	cout << endl << "有序链表B中的元素为:";
	B.reset();
	while(!B.endOfList()) {
		A.insertRear(B.data());//在遍历链表B的时候,一边插入A、一边输出
		cout << B.data() << "  ";
		B.next();
	}
	
	cout << endl << "加入链表B中元素后,链表A中的元素为:";
	A.reset();
	while(!A.endOfList()) {
		cout << A.data() << "  ";
		A.next();    
	}
	cout << endl;
	return 0;
}

例题9-4

将直接插入排序、直接选择排序、冒泡排序、顺序查找函数封装到数组类Array中,作为成员函数。实现并测试这个类。

#ifndef ARRAY1_H_
#define ARRAY1_H_

template <class T>
class Array
{
	T* alist;
	int size;
public:
	Array() {size = 0;}
	Array(int sz) {alist = new T[sz]; size = sz;}
	Array(T a[], int sz) {
		size = sz;
		alist = new T[size];
		for (int i = 0; i < size; i ++)
			alist[i] = a[i];
	}
	~Array() {size = 0; delete []alist;}
	int getSize() {return size;}
	T& operator [](int i) {return alist[i];}
	void insertSort();
	void selectSort();
	void bubbleSort();
	int seqSearch(T key) {
		int i;
		for (i = 0; i < size; i ++)
			if (alist[i] == key)
				return i;
		if (i == size) {
			cout << "没有找到元素" << endl;
			return -1;
		}
	}
};

template <class T>
void Array<T>::insertSort()
{
	int i, j;
	T temp;
	//将下标为1~size-1的元素逐个插入到已排序序列中适当的位置
	for (i = 1; i < size; i ++) 
	{
		//从a[i-1]开始向a[0]方向扫描各元素,寻找适当位置插入a[i]
		j = i;
		temp = alist[i];
		while (j > 0 && temp < alist[j-1]) 
		{   //逐个比较,直到temp>=a[j-1]时,j便是应插入的位置。
			alist[j] = alist[j-1];  //将元素逐个后移,以便找到插入位置时可立即插入。
			j--;
		}
		//插入位置已找到,立即插入。
		alist[j] = temp;
	}
	//输出数据
	for(i = 0; i < size; i ++)
		cout << alist[i] << "  ";
	cout << endl;
}

template <class T>
void Array<T>::selectSort()
{
	int minIndex; //每一次选出的最小元素之下标
	int i, j;
	T temp;
	//sort a[0]..a[size-2], and a[size-1] is in place
	for (i = 0; i < size - 1; i ++) 
	{
		minIndex = i;    //最小元素之下标初值设为i
		//在元素a[i+1]..a[size-1]中逐个比较显出最小值
		for (j = i + 1; j < size; j++) 
			//minIndex始终记录当前找到的最小值的下标
			if (alist[j] < alist[minIndex])
				minIndex = j;
		//将这一趟找到的最小元素与a[i]交换
		temp = alist[i];
		alist[i] = alist[minIndex];
		alist[minIndex] = temp;
	}
	//输出数据
	for(i = 0; i < size; i ++)
		cout << alist[i] << "  ";
	cout << endl;
}

template <class T>
void Array<T>::bubbleSort()
{
	T temp;
	int i, j;
	for (i = 1; i < size; i ++) {
		for (j = size - 1; j >= i; j --) {
			if (alist[j - 1] > alist[j]) {
				temp = alist[j];
				alist[j] = alist[j - 1];
				alist[j - 1] = temp;
			}
		}
	}
	for(i = 0; i < size; i ++)
		cout << alist[i] << "  ";
	cout << endl;
}

#endif //ARRAY1_H_
#include <iostream>
#include "array1.h"
using namespace std;

int main()
{
	int a[5] = {3, 6, 1, 8, 2};
	double d[4] = {4.1, 3.2, 5.6, 1.9};
	char c[3] = {'g', 'c', 'A'};
	Array<int> iArray(a, 5);
	iArray.insertSort();
	Array<double> dArray(d, 4);
	dArray.selectSort();
	Array<char> cArray(c, 3);
	cArray.bubbleSort();
	return 0;
}

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【问题描述】 请设计一个链表,实现链表的初始化、插入、删除和打印操。 节点的定义如下: typedef int elementType; typedef struct node { elementType data; node* next; } LList, *PList; 链表的定义及要求如下: class linkedList { public: linkedList();//构造函数 virtual ~linkedList();//析构函数,注意要链表所有节点的资源 void insert( int value );//警告:必须初始化才能使用! bool initiate();//初始化单链表,使用new操创建头结点。如果创建失败,则返回false,否则返回true bool isEmpty();//判断单链表是否为空 //删除单链表第pos个元素结点,并将删除的节点的值存在value。 //注意:如果链表为空、删除位置大于链表长度、以及删除位置为0的情况,需要终止删除并输出相应信息 bool remove( int pos, int& value ); void print();//顺序打印单链表,如果是单链表为空,则输出 Empty int Length();//返回单链表长度。如果是单链表为空,则返回-1 private: LList *head; int len; }; main函数: int main(int argc, char* argv[]) { linkedList L1; int n; int val; //初始化链表 if(!L1.initiate()) return 0; cin>>n;//输入链表数据个数 for(int i=0; i<n; i++) //输入n个数,并插入链表 { cin>>val; L1.insert(val); } cout << "Origin Length:" << L1.Length() << endl;//输出链表长度 cout << "data:" ; L1.print();//打印链表 cin>>n;//输入需要删除的数据的位置 if (L1.remove(n,val)) { //删除位置n的数据,并将删除的数据值放在val cout<<"Delete the data at position("<<n<<"):"<<val<<endl; cout<< "New Length:" << L1.Length()<< endl;//输出链表长度 cout<< "data:" ; L1.print();//打印链表 } return 0; } 【输入形式】 输入包括3行。 第一行是链表元素个数n。第二行为n个元素的值。第三行为拟删除的数据位置。 【输出形式】 输出格式不固定。具体参见样例。 【样例输入1】 4 1 2 3 4 2 【样例输出1】 Origin Length:4 data:1 2 3 4 Delete the data at position(2):2 New Length:3 data:1 3 4 【样例输入2】 2 100 -1 3 【样例输出2】 Origin Length:2 data:100 -1 pos > len, failed 【样例输入3】 8 8 7 6 5 4 3 2 1 0 【样例输出3】 Origin Length:8 data:8 7 6 5 4 3 2 1 pos <= 0, failed
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值