赞
踩
线性表的基本定义和顺序存储的实现见上一篇博客:https://blog.csdn.net/weixin_51352359/article/details/120497500
首先依据线性表要实现的功能,定义线性表的类模板即父类(当然这一步也可以不做):
template<class elemType> class list { public: //对于属性类的函数,因其并不改变原数组or链表的值,在后面加const //可以达到保护隐含this指针以及供常对象使用的目的 virtual int length() const = 0; virtual int search(const elemType& x) const = 0; //const &结构:在数据类型未知or比较复杂时,可以提高运行效率,同时节省空间 virtual elemType visit(int i) const = 0; //数据操纵类函数 virtual void insert(int i, const elemType& x) = 0; virtual void remove(int i) = 0; virtual void clear() = 0; //遍历操作 virtual void traverse()const = 0; //析构函数,防止内存泄露 virtual ~list() {}; };
关于单链表的一些基本概念,可以参考以前的博客:
https://blog.csdn.net/weixin_51352359/article/details/120471969
单链表的存储映像图如下:
描述单链表只需要一个指向头结点的指针型变量——头指针,这里用head指针。
//单链表类的定义 template<class elemType> class linkList :public list<elemType> { private: struct node {//内嵌类 elemType data; node* next; //构造函数 node(const elemType& x, node* p = NULL) { data = x; next = p; } node():next(NULL){} //析构函数 ~node(){} } node* head; public: linkList(); ~linkList() { clear(); delete head; } int length() const; int search(const elemType& x)const; elemType visit(int i)const; void insert(int i, const elemType& x); void remove(int i); void clear(); void traverse()const; };
template<class elemType>
linkList<elemType>::linkList() {
head = new node();
}
template<class elemType>
int linkList<elemType>::length() {
int count = 0;
node* p = head->next;//指向首节点
while (p != NULL) {
count++; p = p->next;
}
return count;
}
template<class elemType>
int linkList<elemType>::search(const elemType& x)const {
//首节点位置为0
int pos = -1;
node* p = head->next;
while (p) {
pos++;
if (p->data == x)break;
p = p->next;
}
if (!p) return-1;//并未找到
return pos;
}
template<class elemType>
elemType linkList<elemType>::visit(int i)const {
//判断i是否出界,若出界则直接跳出
if (i<0 || i>length()) throw OutOfBound();
int count = 0;
node* p = head->next;
while (p) {
if (count == i)break;
else {
count++;
p = p->next;
}
}
return p->data;
}
tmp = new node(x);//新建节点
tmp->next = head->next;//使自己指向下一个节点
head->next = tmp;//使上一个节点指向自己,链入完毕
之后考虑一般情况,即在第i个位置插入元素。由上述可知,在定位到第i-1个元素后,元素的插入就变得很简单了,故主要分为一下几步:
//在第i-1个后面插入 template<class elemType> void linkList<elemType>::insert(int i, const elemType& x) { if (i<0 || i>length()) throw OutOfBound(); node* tmp; tmp = new node(x);//node的构造函数 //使p指向第i-1个节点 int count = 0; p = head; while (count < i) { p = p->next; count++; } //链入tmp tmp->next = p->next; p->next = tmp; }
node* tmp = head->next;
if (!tmp)return;//注意: tmp可能为空!!
head->next = tmp->next;
delete tmp;
之后进入到一般情况:
template<class elemType> void linkList<elemType>::remove(int i) { if (i<0 || i>=length()) throw OutOfBound(); //让p指向第i-1个位置 node* q,*p = head; int count = 0; while (count < i) { p = p->next; if (!p)return;//如果p为空,则直接返回 和上面的边界判定其实有重合 count++; } q = p->next; if (!q) return; p->next = q->next; delete q; }
template<class elemType> void linkList<elemType>::clear() { //第一种方法:永远删首节点 node* p = head->next; while (p) { head->next = p->next; delete p; p = head->next; } head->next = NULL; /* //第二种方法:兄弟协同法 node* p = head->next, * q; head->next = NULL; while (p) { q = p->next; delete p; p = q; } */ }
template<class elemType>
void linkList<elemType>::traverse() {
node* p = head->next;
while(p)
{
cout << p->data << " ";
p = p->next;
}
}
//文件名:linklist.h #include<iostream> using namespace std; class outOfBound {}; /* //类模板的定义 //在使用这种情况时,node可以直接使用,而不用使用node<elemType> template<class elemType> class linkList { private: struct node { elemType data; node* next; node(const elemType& x, node* p = NULL) { data = x; p = next; } node() :next(NULL) {} ~node() {} }; node* head; public: linkList(); ~linkList() { clear(); delete head; } int length()const; int search(const elemType& x)const; elemType visit(int i)const; void insert(int i, const elemType& x); void remove(int i); void clear(); void traverse()const; }; */ //如果用下面这种方式定义,node需用node<elemType> template<class elemType> class linkList;//前声明 template<class elemType> class node { friend class linkList<elemType>; private: elemType data; node* next; public: node(const elemType& x, node* p = NULL) { data = x; next = p; } node() :next(NULL) {} }; template<class elemType> class linkList { private: node<elemType>* head; public: linkList(); ~linkList() { clear(); delete head; } int length()const; int search(const elemType& x)const; elemType visit(int i)const; void insert(int i, const elemType& x); void remove(int i); void clear(); void traverse()const; }; //基本操作实现 template<class elemType> linkList<elemType>::linkList() { head = new node<elemType>(); } template<class elemType> int linkList<elemType>::length() const{ //首节点长度为1 int count = 0; node<elemType>* p = head->next; while (p) { count++; p = p->next; } return count; } template<class elemType> int linkList<elemType>::search(const elemType& x)const { //首节点下标为0 int count = 0; node<elemType>* p = head->next; while (p) { if (p->data == x)break; else count++; p = p->next; } if (!p)return -1; else return count; } template<class elemType> elemType linkList<elemType>::visit(int i)const { //首节点下标为0 if (i<0 || i>length() - 1) throw outOfBound(); int count = 0; node<elemType>* p = head->next; while (p) { if (count == i) break; count++; p = p->next; } return p->data; } template<class elemType> void linkList<elemType>::insert(int i, const elemType& x) { if (i<0 || i>length()) throw outOfBound(); node<elemType>* tmp = new node<elemType>(x); node<elemType>* p = head; int count = 0; while (p) { if (count == i) break; count++; p = p->next; } tmp->next = p->next; p->next = tmp; } template<class elemType> void linkList<elemType>::remove(int i){ if (i<0 || i>length()-1) throw outOfBound(); int count = 0; node<elemType>* p = head; while (p) { if (count == i) break; count++; p = p->next; } node<elemType>* tmp = p->next; p->next = tmp->next; delete tmp; } template<class elemType> void linkList<elemType>::clear() { node<elemType>* p = head->next; head->next = NULL; if (!p) return; node<elemType>* q = p->next; while (q) { delete p; p = q; q = p->next; } delete p; } /* template<class elemType> void linkList<elemType>::clear() { node* p = head->next; while (p) { head->next = p->next; delete p; p = head->next; } } */ template<class elemType> void linkList<elemType>::traverse() const { node<elemType>* p = head->next; while (p) { cout << p->data << " "; p = p->next; } }
#include<iostream> #include"linklist.h" using namespace std; int main() { linkList<char> chlist; char ctemp; int i, n, result; cout << "number of the elements:" << endl; cin >> n; cin.get(ctemp);//将enter抛弃 cout << "input the elements:\n" << endl; //将字符逐个输入到表中,并依次插入表尾 for (i = 0; i < n; i++) { cin.get(ctemp); chlist.insert(i, ctemp); } ctemp = chlist.visit(0);//获得首节点 chlist.remove(0);//将首节点删除 chlist.insert((chlist.length() + 1) / 2, ctemp);//将删除的首节点放在中间位置 cout << "output the elements:\n" << endl; for (i = 0; i < chlist.length(); i++) { cout.put(chlist.visit(i));//读取第i个节点的值并输出 } cout << endl; cout << endl; chlist.traverse();//遍历输出 cout << endl; cout << endl; cout << chlist.search('a'); return 0; }
利用首席插入法和兄弟协同法实现单链表的就地逆置:
(下图为具体思路图示)
代码清单:
template<class elemType>
void linkList<elemType>::reverse() {
node<elemType>* p, *q;
p = head->next;
head->next = NULL;
while (p) {
q = p->next;
p->next = head->next;
head->next = p;
p = q;
}
}
代码运行结果(最后一行为上一行的reverse()):
#include<iostream> #include"linklist.h" using namespace std; int main() { linkList<int> list1, list2, list3; int i = 0, j, x; int len1; //输入第一个集合中的元素 cout << "请输入第一个集合中元素:(以0作为结束标志)"; cin >> x; while (x != 0) { list1.insert(i, x); i++; cin >> x; } //输入第二个集合的元素 i = 0; cout << "请输入第二个集合中元素:(以0作为结束标志)"; cin >> x; while (x != 0) { list2.insert(i, x); i++; cin >> x; } //查找list1中的元素是否在list2中出现 //如果出现则将其存入list3中 len1 = list1.length(); int num = 0; for (j = 0; j < len1; ++j) { int y = list1.visit(j); if (list2.search(y) != -1) { list3.insert(num, y); num++; } } //输出list3 list3.traverse(); }
运行结果:
基本要素:
代码清单:
//文件名:DlinkList.h #include<iostream> using namespace std; template<class elemType> class DlinkList { private: struct node { elemType data; node* prior, * next; node(const elemType& x, node* p = NULL, node* q = NULL) { data = x; prior = p; next = q; } node():next(NULL),prior(NULL){} ~node(){} }; node* head, * tail; int currentlength; node* move(int i)const;//返回第i个节点的地址 public: DlinkList(); ~DlinkList() { clear(); delete head; delete tail; } void clear(); int length()const { return currentlength; } int search(const elemType& x)const; elemType visit(int i)const; void insert(int i, const elemType& x); void remove(int i); void traverse(); void reverse(); }; template<class elemType> DlinkList<elemType>::DlinkList() { head = new node; head->next = tail = new node; tail->prior = head; currentlength = 0; } template<class elemType> typename DlinkList<elemType>::node* DlinkList<elemType>::move(int i)const { node* p = head->next; while (i--) p = p->next; return p; } template<class elemType> int DlinkList<elemType>::search(const elemType& x)const { node* p = head->next; int i; for (i = 0; i < currentlength; ++i) { if (p->data == x)break; p = p->next; } if (i == currentlength)return-1; else return i; } template<class elemType> elemType DlinkList<elemType>::visit(int i)const { return move(i)->data; } template<class elemType> void DlinkList<elemType>::clear() { node* p, * q; p = head->next; while (p!=tail) { q = p->next; delete p; p = q; } head->next = NULL; tail->prior = head; currentlength = 0; } template<class elemType> void DlinkList<elemType>::insert(int i, const elemType& x) { node* p, * tmp; p = move(i);//找到第i个节点 tmp = new node(x, p->prior, p); p->prior->next = tmp; p->prior = tmp; ++currentlength; } template<class elemType> void DlinkList<elemType>::remove(int i) { node* p; p = move(i); p->prior->next = p->next; p->next->prior = p->prior; delete p; --currentlength; } template<class elemType> void DlinkList<elemType>::traverse() { node* p = head->next; while (p != tail) { cout << p->data << " "; p = p->next; } cout << endl; } template<class elemType> void DlinkList<elemType>::reverse() { node* p; for (p = tail->prior; p != head; p = p->prior) { cout << p->data; } }
题目描述
给定一个N个数的数组,M次操作,每次操作为下列操作之一。求最后的数组。
操作1:在第X个数之后插入一个数Y。
操作2:删除第X个数。
输入格式
第一行:两个整数N,M(N,M≤100000)含义见试题描述。
第二行:N个整数,表示原来的数组。
接下来M行,每行第一个数OP,表示操作类型。
对于操作1,接下来两个数X,Y,含义见题面描述,保证0≤X≤当前数的个数,若X=0,表示在数组开头插入。
对于操作2,接下来一个数X,含义见题面描述,保证1≤X≤当前数的个数。
输出格式
输出若干个数,表示最后的数组。
样例输入
5 3
1 2 3 4 5
1 1 6
2 1
2 2
样例输出
6 3 4 5
代码清单:
#include<iostream> using namespace std; struct ListNode { int value; ListNode* next; ListNode(int val) :value(val), next(NULL) {}; ListNode() :value(0), next(NULL) {}; }; void _insert(ListNode* head, int pos, int value) { ListNode* pre = head, * cur = head; for (int i = 0; i <= pos; ++i) { pre = cur; cur = cur->next; } ListNode* to_insert = new ListNode(value); pre->next = to_insert; to_insert->next = cur; } void _delete(ListNode* head, int pos) { ListNode* pre = head, * cur = head; for (int i = 1; i <= pos; ++i) { pre = cur; cur = cur->next; } pre->next = cur->next; cur = cur->next; } int main() { int n, m; cin >> n >> m; ListNode* head = new ListNode(),*cur = head; for (int i = 0; i < n; i++) { int t; cin >> t; ListNode* tmp = new ListNode(t); cur->next = tmp; cur = cur->next; } int c; for (int i = 0; i < m; ++i) { cin >> c; if (c == 1) { int insert_value,pos; cin >> pos >> insert_value ; _insert(head, pos, insert_value); } else { int pos; cin >> pos; _delete(head, pos); } } ListNode* p = head->next; while (p) { cout << p->value <<" "; p = p->next; } return 0; }
运行结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。