数据结构(1):单向链表的基本操作

来源:互联网 发布:windows gvim配置模板 编辑:程序博客网 时间:2024/05/18 10:57

建立、插入、查找、删除

/************************************************************************//* 单向链表(1)qcy2017年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;} elsereturn 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;}}elsereturn 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[N] = {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. 查第一次出现某个指定元素的指针 getNodePtFirstFindLNode * 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的前面增加一个元素555head = 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。借助stlvoid 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;}




0 0
原创粉丝点击