为了表示每个数据元素ai与其直接后继元素ai+1之间的逻辑关系,对数据ai,除了存储其自身的信息之外,还需存储一个指示其
直接后继的信息(即直接后继的存储位置)。这两部分信息组成数据元素ai的存储映像,称为结点(Node)。N个结点链结成一个链表,
即为线性表(a1,a2,...,an)的链式存储结构,因为此链表的每个节点中只包含一个指针域,所以叫做单链表。
我们把链表中的第一个结点的存储位置叫做头指针,,为了更方便地对链表进行操作,如删除第一个结点的特殊情况
(第一个结点没有前驱,而要摘除一个结点需要首先找到它的前驱才能做摘除操作),经常在单链表的第一个结点前附设一个结点,
称为头节点,这样头指针就指向了头节点。
示例程序:(改编自《大话数据结构》)
C++ Code
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
#include<iostream>
#include<stdlib.h> #include<time.h> using namespace std; typedef int ElemType; typedef struct Node { ElemType data; struct Node *next; } Node; typedef Node *NodePtr; bool InitList(NodePtr *Npp) { *Npp = (NodePtr)malloc(sizeof(Node)); if (!(*Npp)) return false; //分配失败 (*Npp)->next = NULL; return true; } bool ListEmpty(NodePtr Np) { if (Np->next == NULL) return true; else return false; } bool ClearList(NodePtr *Npp) { cout << "Clear List..." << endl; NodePtr p = *Npp; if (!(p->next)) return true; while (p->next) { NodePtr q = p->next; p->next = q->next; free(q); } return true; } int ListLength(NodePtr Np) { cout << "List's length : "; NodePtr p = Np->next; int i = 0; while (p) { p = p->next; ++i; } return i; } bool GetElem(NodePtr Np, int pos, ElemType *ptr) { cout << "Get Item from pos " << pos << " : "; NodePtr p = Np->next; int i = 1; while (p && i < pos) { p = p->next; ++i; } if (!p) return false; *ptr = p->data; return true; } int LocateElem(NodePtr Np, ElemType Elem) { cout << "Item " << Elem << "'s pos : "; NodePtr p = Np->next; int i = 1; while (p && p->data != Elem) { p = p->next; ++i; } if (!p) return 0; return i; } bool ListInsert(NodePtr *Npp, int pos, ElemType Elem) { cout << "Insert List pos " << pos << " Item " << Elem << endl; NodePtr p = *Npp; int i = 1; while (p && i < pos) { p = p->next; ++i; } if (!p) return false; NodePtr In = (NodePtr)malloc(sizeof(Node)); In->data = Elem; In->next = p->next; p->next = In; return true; } bool ListDelete(NodePtr *Npp, int pos, ElemType *ptr) { cout << "Delete List Item in pos " << pos << endl; NodePtr p = *Npp; int i = 1; while (p && i < pos) { p = p->next; ++i; } if (!p) return false; NodePtr q = p->next; *ptr = q->data; p->next = q->next; free(q); return true; } bool ListTraverse(NodePtr Np) { cout << "List's Items : "; NodePtr p = Np->next; while (p) { cout << p->data << ' '; p = p->next; } cout << endl; return true; } void CreateListHead(NodePtr *Npp, int num) { cout << "Create List from Head ..." << endl; if (*Npp != NULL) free(*Npp); *Npp = (NodePtr)malloc(sizeof(Node)); (*Npp)->next = NULL; srand(time(NULL)); for (int i = 0; i < num; i++) { NodePtr p = (NodePtr)malloc(sizeof(Node)); p->data = rand() % 100 + 1; //随机数 p->next = (*Npp)->next; (*Npp)->next = p; } } void CreateListTail(NodePtr *Npp, int num) { cout << "Create List from Tail ..." << endl; if (*Npp != NULL) free(*Npp); *Npp = (NodePtr)malloc(sizeof(Node)); (*Npp)->next = NULL; srand(time(NULL)); NodePtr tail = *Npp; for (int i = 0; i < num; i++) { NodePtr p = (NodePtr)malloc(sizeof(Node)); p->data = rand() % 100 + 1; tail->next = p; tail = p; } tail->next = NULL; } int main(void) { NodePtr Np; InitList(&Np); for (int i = 1; i < 5; i++) ListInsert(&Np, i, i); if (!ListEmpty(Np)) cout << ListLength(Np) << endl; ListTraverse(Np); cout << LocateElem(Np, 3) << endl; int get; GetElem(Np, 2, &get); cout << get << endl; ClearList(&Np); cout << ListLength(Np) << endl; CreateListHead(&Np, 10); ListTraverse(Np); int result; ListDelete(&Np, 5, &result); ListTraverse(Np); ClearList(&Np); CreateListTail(&Np, 10); ListTraverse(Np); ClearList(&Np); return 0; } |
如果限定每次只在链表的头部插入和删除元素,就形成一个LIFO的访问序列,所以在链表头部插入和删除元素的操作实现了
堆栈的push和pop操作。当然基于单链表也是可以实现队列的enqueue和dequeue操作的,比如在每次在头部插入而在尾部删除,
或者反过来都是一样的道理。
作者:Simba888888 发表于2013-4-21 10:12:45 原文链接
阅读:64 评论:0 查看评论