算法与数据结构是编程基础,最近初学Python,学习新语言的同时回顾很久以前学习的数据结构,数据结构的实现本质与语言无关。
单链表的实现点:
1.链表初始化的时候,头结点可以只定义指针域而不定义数据域,也可以在初始化列表(C++)直接定义头结点指针域与数据域。
2.单链表插入操作:
单链表的插入操作相对简单,如上图,p2为插入的指针,2Node为插入结点,直接p2->next=head->next,head->next=p2即可。
3.单链表删除操作:
仍以上图为例,如需从右侧图删除2Node结点至左侧,直接head->next=p1即可
插入与删除需要考虑到结点所处的位置(链表头,链表尾),C++中析构时需要创建辅助变量,不然会出现指针悬挂(野指针)的问题。
Python实现
'''单链表的操作
is_empty() 链表是否为空
length() 链表长度
travel() 遍历整个链表
add(data) 链表头部添加元素
append(data) 链表尾部添加元素
insert(pos, data) 指定位置添加元素
remove(data) 删除节点
find(data) 查找节点是否存在'''
class SingleNode(object):
"""单链表的结点"""
def __init__(self,data):
# _data存放数据元素
self.data = data
# _next是下一个节点的标识
self.next = None
class SingleLinkList(object):
"""单链表"""
def __init__(self):
self._head = None
def is_empty(self):
"""判断链表是否为空"""
return self._head == None
def length(self):
p = self._head
count = 0
while p != None:
count += 1
p = p.next
return count
def travel(self):
p=self._head
while p!=None:
print(p.data," ")
p=p.next
def add(self,data):
item = SingleNode(data)
item.next = self._head
self._head = item
def append(self,data):
item = SingleNode(data)
if self.is_empty():
self.add(data)
else:
p=self._head
while p.next!=None:
p=p.next
item.next=p.next
p.next=item
def find(self,data):
'''比较直接的想法是定位到data所在节点,但是单链表这样处理无法快速定位data的前驱,所以返回p.next.data==d的p指针'''
p=self._head
while p.next:
if p.next.data==data:
return p
p=p.next
return None
def insert(self,pos,data):
if pos <= 0:
self.add(data)
# 若指定位置超过链表尾部,则执行尾部插入
elif pos > (self.length() - 1):
self.append(data)
# 找到指定位置
else:
item = SingleNode(data)
p=self._head
for i in range (1,pos):
p=p.next
item.next=p.next
p.next=item
def remove(self,data):
h = self._head
if h.data == data:
self._head = h.next
else:
if not self.find(data):
print("Not found!Please change your data!")
return
else:
p = self.find(data)
q = p.next
p.next = q.next
if __name__ == "__main__":
ll = SingleLinkList()
ll.add(1)
ll.add(2)
ll.append(3)
ll.travel()
ll.insert(2, 4)
print ("length:",ll.length())
ll.travel()
ll.remove(2)
print ("length:",ll.length())
ll.travel()
C++实现
#include <iostream>
using namespace std;
class List {
public:
List(){create_List();}
~List(){clear();}
//函数声明
void create_List();
//从头节点进行插入
void insert(const int& d);
//在指定位置插入
void insert_pos(const int&d,const int&d1);
//删除指定数据的节点
void erase(const int& d);
//修改指定数据
void updata(const int& d,const int& d1);
//反转链表函数
void reverse();
void reverse_print();
//打印
void print();
//节点结构
struct Node{
int data;
Node* next;
Node(const int& d):data(d),next(NULL){}
};
Node * head;//头节点
//清理链表函数
//逆序打印
void ReversePrint(Node* head);
void clear(){
//从头节点开始循环删除
// delete p;//delete是否会删除对应值,还是只是像free一样将内存控制权移交给系统?
// p = q;//不能注释掉第一句话,然后delete p,再将p->next的值赋给p,必然会出现指针悬挂
Node* p =head;
while(p)
{
Node* q =p->next;
delete p;
p=q;
}
//在对指针进行delete操作时需要很小心,要避免出现指针悬挂的问题。
}
//查找数据d的上一个节点位置的函数
//为了方便后面删除操作
Node* find(const int& d){
Node *p =head;
while (p){
if(p->next->data==d)
break;
p=p->next;
}
return p;
}
};
//创建头结点
void List::create_List()
{
head = new Node(0);
}
//从头插入一个节点,先赋值自身后继,再赋值其前一个元素的后继,类内声明类外定义
void List::insert(const int& d)
{
Node* q =new Node(d);
q->next=head->next;
head->next=q;
}
//打印函数
void List::print()
{
Node* p =head->next;
while(p)
{
cout<<p->data<<endl;
p=p->next;
}
}
//在d位置之前插入d1
void List::insert_pos(const int& d,const int& d1)
{
Node* p =find(d);
Node* q = new Node(d1);
q->next=p->next;
p->next=q;
}
//删除data为某值的节点
void List::erase(const int& d)
{
Node* p = find(d);
Node* q = p->next;
p->next=q->next;
}
//修改指定数据
void List::updata(const int& d,const int& d1)
{
Node* p = find(d);
p->next->data=d1;
}
//反转链表
void List::reverse()
{
Node * p = head->next;//头结点之后的第1个节点
Node * q = p->next;//头结点之后的第2节点
Node * m = q->next;//头结点之后的第3个节点
p->next = NULL;//将头接点之后的第1个节点的next指针置为空
//根据m是否为空来判断 以此逆序每一个节点
while(m){
q->next = p;
p = q;
q = m;
m = m->next;
}
//将最后一个节点逆序
q->next = p;
//将头从新指向新的的第1个节点(之前的最后一个节点)
head ->next = q;
}
void List::reverse_print()
{
ReversePrint(head->next);
}
void List::ReversePrint(Node *head)//递归实现逆序打印(不改变链表结构),比较尴尬的是会输出默认的头结点的data值,为0,
//由于使用递归调用,所以并不方便修改代码体,传参的时候用->next后移一位即可,因为不是顺序存储结构,
//所以不能采用head++的方式
{
if(head!=NULL)
{
if(head->next!=NULL)
ReversePrint(head->next);
cout<<head->data<<endl;
}
}
int main(int argc, const char * argv[])
{
// insert code here...
List list;
list.insert(30);
list.insert(20);
list.insert(10);
// list.insert(40);
list.insert_pos(10, 5);
list.print();
cout << "---------------------" << endl;
list.erase(10);
list.print();
cout << "---------------------" << endl;
list.reverse();
list.print();
cout << "---------------------" << endl;
list.updata(5, 8);
list.print();
cout << "---------------------" << endl;
//list.reverse_print();
return 0;
}
图片于以下博客引用: