数据结构--线性表(单链表)

正在学习数据结构,第一步是线性表,写一个bookLinkList.ios

同时开始用vianal studio. 固然不是很熟悉这个IDE,但感受挺厉害的。算法

下面的这个booklist 不是本人写的,感谢Liu老师。数据结构

 

链表是一种动态结构,整个可用存储空间可为多个链表共同享用。函数

每一个链表占用的空间不须要预先分配划定,而是系统按需及时生成。
学习

创建线性表的链式存储结构的过程是一个动态生成链表的过程。测试

从空表的初始状态起,依次创建各元素节点,并逐个插入链表。spa


// BookLinkList.cpp : This file contains the 'main' function. Program execution begins and ends there. // by lyj.
 #include <iostream>
using namespace std; #define OK 1
#define ERROR 0
#define OVERFLOW -2 typedef int Status; typedef struct Book { char no[20]; char name[50]; float price;
  //符号重载
bool operator==(const Book& anotherbook) { return (!strcmp(no, anotherbook.no)); } bool operator!=(const Book& anotherbook) { return(strcmp(no, anotherbook.no)); } friend istream &operator >> (istream &i, Book& b)//输入流 { cout << "请输入书号:"; i >> b.no; cout << "请输入书名:"; i >> b.name; cout << "请输入价格:"; i >> b.price; cout << "\n"; return i; } }Book; typedef struct LNode//(1)LNode是结构类型名 { Book data; struct LNode *next;//(2)第二个LNode是用的(1)定义了一个LNode类型的指针 }LNode, *LinkList;//(3)第三个LNode是(1)结构体的别名,这里用了相同的名字。LinkList=LNode *; //通常用LinkList定义单链表头指针,用LNode*定义某个节点指针

*** 注意区分头结点,首元结点,头指针。指针

    初始化链表(只有一个头节点的空链表)code

Status InitList(LinkList &L) { L = new LNode; L->next = NULL; return OK; }

 

——下面的函数是假定链表已经存在多个节点:blog


一、取值   用指针p指向首元结点,用 j 作计数器初值赋1 。从首元结点开始依次顺着链域next向下访问,只要指向当前节点的指针p不为NULL,并无达到序号为 i 的节点,则循环操做:p指向下一个节点,计时器 j 相应加1 。取值算法的时间复杂度为:O(n)

tatus GetElem(LinkList L, int i, Book &e) { LNode *p; int j; p = L->next; j = 1; while (p && j < i) { p = p->next; j++; } if (!p || j > i) return ERROR; e = p->data; return OK; }

 二、查找 从链表的首元结点出发,依次将节点值和给定值e进行比较,返回查找结果。查找算法时间复杂度也为:O(n)

LNode *LocateElem(LinkList L, Book e) { LNode *p; p = L->next; while (p && p->data != e) p = p->next; return p; }

 三、插入 (可插入位置为n+1个)时间复杂度也为:O(n)

Status ListInsert(LinkList &L, int i, Book e) { LNode *s, *p; int j; p = L; j = 0; while (p && j < i - 1) { p = p->next; j++; }//查找第i-1个节点,p指向该节点 if (!p || j > i - 1) return ERROR; s = new LNode; s->data = e;//将e存入*s的数据域 s->next = p->next;//把p的下一个节点的地址给*s的指针域,即将p后面的节点连入s的尾部 p->next = s;//将s自己的地址(理解为s的头)放入p的尾部 return OK; }

 删除节点(按序号删除 和 按节点中数据项关键字删除)

Status ListDelete(LinkList &L, int i)   //按序号删除元素(结点)
{ LNode *p, *q; int j; p = L; j = 0; while (p->next && j < i - 1) { p = p->next; j++; } if (!p->next || j > i - 1) return ERROR; q = p->next; p->next = q->next; delete q; return OK; }
Status DelElem(LinkList &L, Book e)  //按结点中数据项的关键字值删除结点
{ LNode *p, *q; p = L; while (p->next && strcmp(p->next->data.no, e.no)) { p = p->next; } if (!p->next) return ERROR; q = p->next; p->next = q->next; delete q; return OK; }

四、链表销毁

Status DestroyList(LinkList &L) { LNode *p; while (L->next != NULL) { p = L; L = L->next; delete p; } delete L; return OK; }

五、链表显示

 

void ListDisplay(LinkList L) { cout << "书号\t书名\t价格\n"; while (L->next != NULL) { L = L->next; cout << L->data.no << "\t" << L->data.name << "\t" << L->data.price << "\n"; } }

 

 

 

前面只建立了有一个头结点的空链表,下面将创建一个包含若干个节点的链表

根据节点插入位置不一样,链表的建立能够分为:前插 和 后插

 

void CreateList_H(LinkList &L, int n)  //前插法
{ LNode *p; L = new LNode; L->next = NULL; for (int i = 0; i < n; i++) { p = new LNode; cin >> p->data; p->next = L->next; L->next = p; } }
void CreateList_R(LinkList &L, int n)  //后插法
{ LNode *r, *p; L = new LNode; L->next = NULL; r = L; for (int i = 0; i < n; i++) { p = new LNode; cin >> p->data; p->next = NULL; r->next = p; r = p; } }

差很少就是这样,而后来一个main测试一下

int main() { LinkList bookLinkList; char ch; int n; cout << "\n+-------------------------------------------------------+\n"; cout << "+ 请选择要进行的操做:\t\t\t\t\t+\n"; cout << "+\t<按数字键1> 建立一个只含头结点的空的单链表\t+\n"; cout << "+\t<按数字键2> 建立一个包含头结点和n个元素的单链表\t+\n"; cout << "+\t<按其余任意键> 退出程序\t\t\t\t+\n"; cout << "+-------------------------------------------------------+\n"; ch = _getwch(); if (ch == '1') { InitList(bookLinkList); } else if (ch == '2') { cout << "\n请输入单链表中要包含的元素个数:"; cin >> n; cout << "请选择:<a>使用前插法\t<b>使用后插法\n"; while (1) { ch = _getwch(); if (ch == 'a') { CreateList_H(bookLinkList, n); break; } else if (ch == 'b') { CreateList_R(bookLinkList, n); break; } } } else { exit(0); } while (1) { cout << "\n\n------------------------------------------------------------------------------------\n"; cout << "+请选择要进行的操做:<a>显示 <b>插入元素 <c>删除元素 <d>查找 <x>退出+\n"; cout << "------------------------------------------------------------------------------------\n"; ch = _getwch(); if (ch == 'x') break; else if (ch == 'a') ListDisplay(bookLinkList); else if (ch == 'b') { int i; cout << "请输入插入的位置:"; cin >> i; Book b; cin >> b; if (ListInsert(bookLinkList, i, b) == OK) cout << "元素插入第" << i << "个位置成功。\n"; else cout << "元素插入第" << i << "个位置失败。\n"; } else if (ch == 'c') { cout << "请选择:<a>按位置序号删除元素\t<b>按元素中数据项的关键字值删除元素\n"; while (1) { ch = _getwch(); if (ch == 'a') { cout << "请输入要删除的元素的位置序号:"; int i; cin >> i; if (ListDelete(bookLinkList, i) == OK) cout << "删除成功!\n"; else cout << "删除失败!\n"; break; } else if (ch == 'b') { cout << "请输入要删除的书籍的书号:"; Book b; cin >> b.no; if (DelElem(bookLinkList, b) == OK) cout << "删除成功!\n"; else cout << "删除失败!\n"; break; } } } else if (ch == 'd') { cout << "请输入要查找的书籍的书号:"; Book t; cin >> t.no; LNode *p = LocateElem(bookLinkList, t); if (p == NULL) cout << "查找失败!\n"; else { cout << "查找成功! 找到的书籍为:\n"; cout << "书号\t书名\t价格\n"; cout << p->data.no << "\t" << p->data.name << "\t" << p->data.price << "\n"; } } } DestroyList(bookLinkList); }