#include"iostream" using namespace std; //====================单链表=================================== //如果不提供“头指针”,则整个链表都无法访问,链表的一个重要特点是插入、删除操作灵活方便. //插入操作处理顺序:中间节点的逻辑,后节点逻辑,前节点逻辑。按照这个顺序处理可以完成任何链表的插入操作。 //删除操作的处理顺序:前节点逻辑,后节点逻辑,中间节点逻辑。 /*单链表实际上是由节点(Node)组成的,一个链表拥有不定数量的节点。 而向外暴露的只有一个头节点(Head),我们对链表的所有操作,都是通过其头节点(head)来进行的。 节点:数据+地址*/ struct ListNode { int val; struct ListNode *next; ListNode(int x) :val(x), next(NULL){} }; //头指针与头结点不同,头结点即第一个结点,头指针是指向第一个结点的指针。链表中可以没有头结点,但不能没有头指针。 /*1.初始化单链表(无头结点),头指针为空*/ // void initList(Node **pNode) // { // *pNode = NULL; // cout << "初始化成功!" << endl; // } /*2.创建单链表(头插法):生成的链表中结点的次序和输入的顺序相反 a.先让新节点的next指向头节点之后 b.然后让表头的next指向新节点*/ void CreatListHead(ListNode *pHead,int data) { ListNode *p=new ListNode(-1); p->val = data; p->next = pHead->next; pHead->next = p; } /*2.创建单链表(尾插法):在表的最后插入结点 a.将表尾终端结点的指针指向新结点 b.将当前的新结点定义为表尾终端结点 */ void CreatListTail(ListNode **Node, int data) { if ((*Node)->next == NULL) { ListNode *p = new ListNode(-1); p->val = data; (*Node)->next = p; *Node = p; (*Node)->next = NULL; } } /*单链表的遍历,并返回单链表长度*/ int printList(const ListNode *pHead) { int len = 0; ListNode *p = pHead->next; if (p== NULL) cout << "链表为空!" << endl; else { while (p != NULL) { len++; cout << p->val << " "; p = p->next; } cout << endl; } return len; } /*删除单链表: 1.声明一节点p和q; 2.将第一个结点赋值给p; 3.循环: a.将下一结点赋值给q;b.释放p;c.将q赋值给p; */ bool ClearList(ListNode *pHead) { ListNode *p, *q; p = pHead->next; while (p) { q = p->next; delete p; p = q; } pHead->next = NULL; return true; } /*查找单链表上指定节点的数据*/ bool GetElem(ListNode *pHead, int i, int &data) { ListNode *p = pHead->next; int j = 0; while (p && j < i-1) { p = p->next; j++; } if (!p) return false; else { data = p->val; return true; } } /*单链表指定位置插入数据: 1.找到ai-1存储位置p 2.生成一个数据域为x的新结点*s 3.令结点*p的指针域指向新结点 4.新结点的指针域指向结点ai。*/ bool ListInsert(ListNode *pHead, int i, int data) { ListNode *p = pHead; int j = 0; while (p && j < i - 1) { p = p->next; j++; } if (!p || j>i - 1) return false; else { ListNode *tmpPtr = new ListNode(-1); tmpPtr->val = data; tmpPtr->next = p->next; p->next = tmpPtr; return true; } } /*删除单链表指定的某个结点: 1.找到ai-1的存储位置p(因为在单链表中结点ai的存储地址是在其直接前趋结点ai-1的指针域next中) 2.令p->next指向ai的直接后继结点(即把ai从链上摘下) 3.释放结点ai的空间,将其归还给“存储池”。*/ bool ListDelete(ListNode *pHead, int i) { int j=1; ListNode *p, *q; p= pHead; while (p && j<i) { p = p->next; j++; } if (!p || j>i) return false; else { q = p->next; p->next = q->next; delete q; return true; } } /*单链表逆序:*/ bool ListReverse(ListNode *PHead) { ListNode *current, *pnext, *prev; current = PHead->next; pnext = current->next; current->next = NULL; while (pnext) { prev = pnext->next; pnext->next = current; current = pnext; pnext = prev; } PHead->next = current; return true; } /*判断单链表中是否有环: 1.使用p、q两个指针,p总是向前走,但q每次都从头开始走,对于每个节点,看p走的步数是否和q一样*/ bool HasLoop(ListNode *pHead) { ListNode *cur1 = pHead; int pos1 = 0; while (cur1) { ListNode *cur2 = pHead; int pos2 = 0; pos1++; while (cur2) { pos2++; if (cur1 == cur2) { if (pos1 == pos2) break; else return true; } cur2 = cur2->next; } cur1 = cur1->next; } return false; } /*获取单链表倒数第N个结点值: 建立两个指针,第一个先走n步,然后第2个指针也开始走,两个指针步伐(前进速度)一致。当第一个结点走到链表末尾时,第二个节点的位置就是我们需要的倒数第n个节点的值。*/ bool GetNthNodeFromBack(ListNode *pHead, int n,int &data) { int i = 1; ListNode *firstNode = pHead, *secNode = pHead; while (firstNode->next != NULL && i < n) { firstNode = firstNode->next; i++; } if (firstNode->next == NULL && i < n - 1) { cout << "n超出链表长度" << endl; return false; } while (firstNode->next != NULL) { secNode = secNode->next; firstNode = firstNode->next; } data = secNode->val; return true; } //===================================================== //====================双向循环链表======================= /*双向循环链表的结构:数据、next指针、prior指针 1.链表由头指针head惟一确定的。 2.带头结点的双链表的某些运算变得方便。 3.将头结点和尾结点链接起来,为双(向)循环链表。*/ struct NodeType2 { int val; NodeType2 *next, *prior; NodeType2(int x) :val(x), next(NULL), prior(NULL) {}; }; //创建双向链表 void CreateListtype2(NodeType2 **Node, int data) { NodeType2 *tmpPtr = (*Node)->next; NodeType2 *p = new NodeType2(data); (*Node)->next = p; p->prior = *Node; p->next = tmpPtr; *Node = p; } /*双链表的前插操作*/ bool ListType2Insert1(NodeType2 *pHead, int i, int data) { int j = 0; NodeType2 *p = pHead; while (p && j<i) { p = p->next; j++; } if (!p && j < i - 1) return false; else { NodeType2 *tmpTpr = new NodeType2(data); tmpTpr->next = p; tmpTpr->prior = p->prior; p->prior->next = tmpTpr; p->prior = tmpTpr; return true; } } /*双链表的后插操作*/ bool ListType2Insert2(NodeType2 *pHead, int i, int data) { int j = 0; NodeType2 *p = pHead; while (p && j<i) { p = p->next; j++; } if (!p && j < i - 1) { cout << "超出链表长度!" << endl; return false; } else { NodeType2 *tmpPtr = new NodeType2(data); tmpPtr->next = p->next; p->next->prior = tmpPtr; p->next = tmpPtr; tmpPtr->prior = p; return true; } } /*双链表上删除结点*p*/ bool ListType2Delete(NodeType2 *pHead, int i) { int j = 0; NodeType2 *p = pHead; while (p && j<i) { p = p->next; j++; } if (p && j < i - 1) { cout << "超出链表长度!" << endl; return false; } else { p->prior->next = p->next; p->next->prior = p->prior; delete p; return true; } } //============================================= int main() { //=========单链表============== //ListNode *L = new ListNode(-1); //int n; //ListNode* tmpPtr = L; //while (cin >> n)//ctrl+z结束 //{ // //CreatListHead(L, n); // CreatListTail(&tmpPtr, n);//为什么传指针不行 非得指针的指针 //} //int len = printList(L); //int data = 0; // bool isGetElem = GetElem(L, 2, data); // bool isInsertElem = ListInsert(L, 2, 4); // bool isClear = ClearList(L); //bool isDelete = ListDelete(L, 1); //bool isReverse = ListReverse(L); //tmpPtr->next = L; //bool isloop=HasLoop(L); //bool IsGet = GetNthNodeFromBack(L, 2, data); //len = printList(L); //============双链表================== NodeType2 *L = new NodeType2(-1); int n = 0; NodeType2 *tmpPtr = L; while (cin >> n) { CreateListtype2(&tmpPtr, n); } bool isInsert = ListType2Insert2(L, 2, 4); bool isDelete = ListType2Delete(L, 3); system("pause"); return 0; }
单(双向)链表的基本操作 C++
猜你喜欢
转载自blog.csdn.net/cat1992/article/details/75393770
今日推荐
周排行