数据结构(1):单向链表的基本操作
2017-01-04 20:58
495 查看
建立、插入、查找、删除
这属于对单向链表的基本操作,应该都没有什么太大的技术难点。
为了反向输出链表,如果不用递归,可以用stack实现。
借助STL的stack。
stack.top(); // 获取顶端元素;
stack.push(); // 压栈
stack.pop(); // 弹栈
stack.empty(); // 栈是否为空
如果链表是循环链表的话,就不是用p==nullptr来判断是否结束了。
而是看p是不是等于头结点了。此时对第一个节点做特殊处理。
/************************************************************************/ /* 单向链表(1) qcy 2017年1月4日18:13:45 */ /************************************************************************/ #include <iostream> using namespace std; typedef struct LNode { int data; LNode * next; } LNode, *Linklist; // 递归、反向输出链表 void printReverseListRecursion(Linklist list) { LNode * p = list; if (p) { printReverseListRecursion(p->next); cout<<p->data<<" "; } } // 递归、正向输出链表 void printListRecursion(Linklist list) { LNode * p = list; if (p) { cout<<p->data<<" "; printListRecursion(p->next); } else { cout<<"\n"; } } // while循环 输出链表 void printList(Linklist list) { LNode * p = list; while (p) { cout<<p->data<<" "; p = p->next; } cout<<"\n"; } // 获取指定位置的指针(假设idx不会越界) LNode * getNodePtAtIndex(Linklist list, int idx) { LNode * p = list; int i = 0; while (i!=idx && p!=nullptr) { i++; p = p->next; } return p; } // 查第一次出现某个指定元素的指针 LNode * getNodePtFirstFindRecursion(Linklist list, int target) { LNode * p = list; if (p) { if (p->data!=target) // 继续找 { return getNodePtFirstFindRecursion(p->next,target); } else { // 找到了 return p; } } else { return nullptr; } } // 在首位增加一个元素 Linklist insertAtFirst(Linklist list, int data) { // 建立一个节点 LNode * node = new LNode; node->data = data; node->next = list; return node; } // 返回指向最后一个元素的指针(递归) LNode * getLastElemPtRecursion(Linklist list) { if (list) // 本身不是空的 { if (list->next) // 下一个还不是空的,还没有到末尾 { return getLastElemPtRecursion(list->next); } else { // 已经到了末尾 return list; // 返回指向当前结点的指针 } } else { return nullptr; } } // 返回指向最后一个元素的指针(非递归) LNode * getLastElemPt(Linklist list) { if (list) // 不为空 { while (list->next) // 下一个不为空 { list = list->next; } // 直到到末尾 return list; } else return nullptr; } // 在末尾增加一个元素 void insertAtLast(Linklist list, int data) { LNode * newNode = new LNode; newNode->data = data; newNode->next = nullptr; LNode * lastElmePt = getLastElemPt(list); lastElmePt->next = newNode; } // 假设一定存在target // 在某个元素的前面增加一个元素 (用2个指针操作) Linklist insertElmeBeforeTarget(Linklist list, int target, int data) { LNode * p, * q; p = list; // 1. 先要找到指向target元素的指针 和 指向target之前的一个元素的指针 if (p) // 不为nullptr { if (p->data == target) // 第一个元素就是target { LNode * newNode = new LNode; newNode->data = data; newNode->next = p; // 在list的第一个位置插入元素 return newNode; } else { // 不是target不在第一个元素 while (p->data!=target) // 还没有找到 { q = p; p = p->next; } // 直到找到 LNode * newNode = new LNode; newNode->data = data; newNode->next = p; // 接上后面的 q->next = newNode; // 接上前面的 return list; } } else return nullptr; } // 假设不越界 // 在指定的Idx前面增加一个元素(用2个指针操作) Linklist insertElemBeforeIdx(Linklist list, int idx, int data) { if (idx==0) // 在首位添加 { return insertAtFirst(list,data); } else { int i = 0; LNode *p, *q; p = list; while (i!=idx && p!=nullptr) // 把指针移动到指定位置 { q = p; p = p->next; ++i; } LNode * newNode = new LNode; newNode->data = data; newNode->next = p; q->next = newNode; return list; } } void destroyList(Linklist list) { if (!list) { return; } else { LNode* p,*q; p = list; while (p) { q = p->next; // 保留下一个 --> 不然一会儿找不到 int temp = p->data; cout<<"即将删除"<<temp<<endl; delete p; // 删掉当前的 // cout<<"已删除"<<temp<<endl; p = q; // 把当前的移动到下一个 } } } int main () { const int N = 10; int iArray = {1,2,3,4,5,6,7,8,9,10}; Linklist list,head,p; list = new LNode; head = list; p = head; // 第1个 list->data = iArray[0]; list->next = nullptr; // 之后的 for (int i = 1;i<N;i++) { LNode * node = new LNode; node->data = iArray[i]; node->next = nullptr; p->next = node; p = p->next; } printList(head); printListRecursion(head); printReverseListRecursion(head); cout<<"\n"; ////////////////////////////////////////////////////////////////////////// // 查 // 1. 获取最后一个元素的指针 LNode * lastElemPt = getLastElemPt(list); // 非递归做 cout<<lastElemPt->data<<endl; cout<<getLastElemPtRecursion(list)->data<<endl; // 递归做 // 2. 获取指定位置的指针 LNode * nodeAt3 = getNodePtAtIndex(list,3); cout<<nodeAt3->data<<endl; // 3. 查第一次出现某个指定元素的指针 getNodePtFirstFind LNode * nodeFisrtFind = getNodePtFirstFindRecursion(list,1000); if (!nodeFisrtFind) { cout<<"没有找到"<<endl; } ////////////////////////////////////////////////////////////////////////// // 增 // 1. 在首位新增一个元素 head = insertAtFirst(list,777); list = head; printList(head); // 2. 在末尾增加一个元素 insertAtLast(list,999); printList(head); // 3. 在3的前面增加一个元素555 head = insertElmeBeforeTarget(list,3,555); list = head; printList(head); // 4. 在指定的位置加一个元素 head = insertElemBeforeIdx(list,4,456); cout<<"在指定的位置加一个元素"<<endl; printList(head); head = insertElemBeforeIdx(list,0,123); printList(head); ////////////////////////////////////////////////////////////////////////// // 删除 // 没什么太大的技术难点吧 ////////////////////////////////////////////////////////////////////////// // 清空 // 和销毁没有太大的区别吧? ////////////////////////////////////////////////////////////////////////// // 销毁 destroyList(head); system("pause"); return 0; }
这属于对单向链表的基本操作,应该都没有什么太大的技术难点。
为了反向输出链表,如果不用递归,可以用stack实现。
借助STL的stack。
stack.top(); // 获取顶端元素;
stack.push(); // 压栈
stack.pop(); // 弹栈
stack.empty(); // 栈是否为空
// 反向输出链表 非递归。用stack。借助stl void printReverseList(Linklist head) { stack<Linklist> s; auto p = head; while (p) { s.push(p); p = p->next; } while (!s.empty()) { LNode * node = s.top(); s.pop(); cout<<node->data<<" "; } cout<<"\n"; }
如果链表是循环链表的话,就不是用p==nullptr来判断是否结束了。
而是看p是不是等于头结点了。此时对第一个节点做特殊处理。
#include <iostream> using namespace std; typedef struct Node { int data; Node * next; } Node, * List; void printList(List head) { if (!head) { cout<<"list为空"<<endl; } else { // 特殊处理头结点 // 输出头结点 cout<<head->data<<" "; auto p = head->next; // 下一个 while (p!=head) { cout<<p->data<<" "; p = p->next; } cout<<"\n"; } } int main () { const int N = 10; List head,p; Node * node = new Node; node->data = 1; node->next = nullptr; head = node; p = head; for ( int i = 2;i<N;i++) { Node * node = new Node; node->data = i; node->next = nullptr; p->next = node; p = p->next; } p->next = head; // 循环 printList(head); system("pause"); return 0; }
相关文章推荐
- 数据结构之链表基本操作算法演示
- 数据结构与算法-链表的基本操作---ShinPans
- c语言实现单链表数据结构及其基本操作
- 数据结构(4):双向链表的基本操作
- 数据结构——单向链表操作
- 数据结构——单链表及其基本操作
- 实战数据结构(5)_双向循环链表的基本操作
- [数据结构]链表的基本操作
- (总结)数据结构之链表的基本操作说明和示例(待补充)
- 单链表的基本操作-数据结构
- 数据结构之链表与数组(二) -单向链表上的简单操作问题
- 数据结构(二)链表1:链式存储的基本操作
- [数据结构]基本概念、单链表操作
- 【学习总结】数据结构之循环链表的基本操作
- 手把手写数据结构之单向循环链表操作
- 数据结构 【实验3 链表基本操作】
- 数据结构之链表的基本操作
- 数据结构实验一--单链表的基本操作的算法
- 手把手写数据结构之单向链表操作(二)
- 数据结构之链表队列基本操作